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:
authorAlexander Pinzon <apinzonf@gmail.com>2013-10-08 23:08:21 +0400
committerAlexander Pinzon <apinzonf@gmail.com>2013-10-08 23:08:21 +0400
commit6b3a34d2c96c9b10e3a28bdfcb07518302c07ff2 (patch)
treedac72c7563008479dd213626d3047afdf10eaa4b /source
parentd57f58cfc6c373da71ab071e4313096373e67cf7 (diff)
parent0973270fbf43c8ab85423a0dd0dcab39d434e644 (diff)
svn merge ^/trunk/blender 59138:60616
Diffstat (limited to 'source')
-rw-r--r--source/CMakeLists.txt4
-rw-r--r--source/blender/blenfont/intern/blf_font.c61
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c62
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h4
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h16
-rw-r--r--source/blender/blenkernel/BKE_action.h7
-rw-r--r--source/blender/blenkernel/BKE_addon.h4
-rw-r--r--source/blender/blenkernel/BKE_anim.h2
-rw-r--r--source/blender/blenkernel/BKE_animsys.h3
-rw-r--r--source/blender/blenkernel/BKE_armature.h8
-rw-r--r--source/blender/blenkernel/BKE_blender.h16
-rw-r--r--source/blender/blenkernel/BKE_brush.h4
-rw-r--r--source/blender/blenkernel/BKE_ccg.h4
-rw-r--r--source/blender/blenkernel/BKE_cloth.h2
-rw-r--r--source/blender/blenkernel/BKE_curve.h26
-rw-r--r--source/blender/blenkernel/BKE_customdata.h4
-rw-r--r--source/blender/blenkernel/BKE_displist.h2
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h4
-rw-r--r--source/blender/blenkernel/BKE_editmesh_bvh.h2
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h5
-rw-r--r--source/blender/blenkernel/BKE_idprop.h171
-rw-r--r--source/blender/blenkernel/BKE_key.h12
-rw-r--r--source/blender/blenkernel/BKE_lamp.h8
-rw-r--r--source/blender/blenkernel/BKE_lattice.h11
-rw-r--r--source/blender/blenkernel/BKE_library.h30
-rw-r--r--source/blender/blenkernel/BKE_mask.h7
-rw-r--r--source/blender/blenkernel/BKE_material.h3
-rw-r--r--source/blender/blenkernel/BKE_mball.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h352
-rw-r--r--source/blender/blenkernel/BKE_modifier.h22
-rw-r--r--source/blender/blenkernel/BKE_navmesh_conversion.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h6
-rw-r--r--source/blender/blenkernel/BKE_object.h5
-rw-r--r--source/blender/blenkernel/BKE_ocean.h4
-rw-r--r--source/blender/blenkernel/BKE_paint.h1
-rw-r--r--source/blender/blenkernel/BKE_particle.h3
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h23
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h2
-rw-r--r--source/blender/blenkernel/BKE_report.h13
-rw-r--r--source/blender/blenkernel/BKE_screen.h12
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h3
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h6
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h4
-rw-r--r--source/blender/blenkernel/BKE_text.h2
-rw-r--r--source/blender/blenkernel/BKE_texture.h4
-rw-r--r--source/blender/blenkernel/BKE_tracking.h73
-rw-r--r--source/blender/blenkernel/BKE_treehash.h52
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c19
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h5
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c91
-rw-r--r--source/blender/blenkernel/intern/action.c50
-rw-r--r--source/blender/blenkernel/intern/addon.c4
-rw-r--r--source/blender/blenkernel/intern/anim.c56
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c83
-rw-r--r--source/blender/blenkernel/intern/armature.c24
-rw-r--r--source/blender/blenkernel/intern/blender.c11
-rw-r--r--source/blender/blenkernel/intern/boids.c24
-rw-r--r--source/blender/blenkernel/intern/bpath.c27
-rw-r--r--source/blender/blenkernel/intern/brush.c11
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c2
-rw-r--r--source/blender/blenkernel/intern/camera.c25
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c36
-rw-r--r--source/blender/blenkernel/intern/cloth.c113
-rw-r--r--source/blender/blenkernel/intern/collision.c5
-rw-r--r--source/blender/blenkernel/intern/colortools.c5
-rw-r--r--source/blender/blenkernel/intern/constraint.c94
-rw-r--r--source/blender/blenkernel/intern/context.c3
-rw-r--r--source/blender/blenkernel/intern/curve.c364
-rw-r--r--source/blender/blenkernel/intern/customdata.c116
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c112
-rw-r--r--source/blender/blenkernel/intern/displist.c226
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c8
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c2
-rw-r--r--source/blender/blenkernel/intern/editmesh.c15
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c21
-rw-r--r--source/blender/blenkernel/intern/effect.c5
-rw-r--r--source/blender/blenkernel/intern/fcurve.c64
-rw-r--r--source/blender/blenkernel/intern/font.c26
-rw-r--r--source/blender/blenkernel/intern/freestyle.c5
-rw-r--r--source/blender/blenkernel/intern/gpencil.c8
-rw-r--r--source/blender/blenkernel/intern/group.c4
-rw-r--r--source/blender/blenkernel/intern/idprop.c208
-rw-r--r--source/blender/blenkernel/intern/image.c15
-rw-r--r--source/blender/blenkernel/intern/key.c136
-rw-r--r--source/blender/blenkernel/intern/lattice.c89
-rw-r--r--source/blender/blenkernel/intern/library.c5
-rw-r--r--source/blender/blenkernel/intern/linestyle.c1
-rw-r--r--source/blender/blenkernel/intern/mask.c133
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c18
-rw-r--r--source/blender/blenkernel/intern/material.c45
-rw-r--r--source/blender/blenkernel/intern/mball.c11
-rw-r--r--source/blender/blenkernel/intern/mesh.c2294
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c2301
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c662
-rw-r--r--source/blender/blenkernel/intern/modifier.c144
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c5
-rw-r--r--source/blender/blenkernel/intern/movieclip.c1
-rw-r--r--source/blender/blenkernel/intern/multires.c21
-rw-r--r--source/blender/blenkernel/intern/navmesh_conversion.c5
-rw-r--r--source/blender/blenkernel/intern/node.c70
-rw-r--r--source/blender/blenkernel/intern/object.c268
-rw-r--r--source/blender/blenkernel/intern/object_deform.c11
-rw-r--r--source/blender/blenkernel/intern/ocean.c3
-rw-r--r--source/blender/blenkernel/intern/packedFile.c3
-rw-r--r--source/blender/blenkernel/intern/paint.c4
-rw-r--r--source/blender/blenkernel/intern/particle.c56
-rw-r--r--source/blender/blenkernel/intern/particle_system.c60
-rw-r--r--source/blender/blenkernel/intern/pbvh.c34
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c384
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h8
-rw-r--r--source/blender/blenkernel/intern/pointcache.c90
-rw-r--r--source/blender/blenkernel/intern/property.c5
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c2
-rw-r--r--source/blender/blenkernel/intern/sca.c15
-rw-r--r--source/blender/blenkernel/intern/scene.c33
-rw-r--r--source/blender/blenkernel/intern/screen.c22
-rw-r--r--source/blender/blenkernel/intern/sequencer.c136
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c34
-rw-r--r--source/blender/blenkernel/intern/smoke.c13
-rw-r--r--source/blender/blenkernel/intern/sound.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c28
-rw-r--r--source/blender/blenkernel/intern/text.c34
-rw-r--r--source/blender/blenkernel/intern/texture.c63
-rw-r--r--source/blender/blenkernel/intern/tracking.c807
-rw-r--r--source/blender/blenkernel/intern/treehash.c164
-rw-r--r--source/blender/blenlib/BLI_alloca.h1
-rw-r--r--source/blender/blenlib/BLI_array.h2
-rw-r--r--source/blender/blenlib/BLI_bitmap.h10
-rw-r--r--source/blender/blenlib/BLI_boxpack2d.h2
-rw-r--r--source/blender/blenlib/BLI_buffer.h24
-rw-r--r--source/blender/blenlib/BLI_callbacks.h8
-rw-r--r--source/blender/blenlib/BLI_compiler_attrs.h88
-rw-r--r--source/blender/blenlib/BLI_convexhull2d.h (renamed from source/blender/compositor/operations/COM_MixBlendOperation.h)37
-rw-r--r--source/blender/blenlib/BLI_dynstr.h14
-rw-r--r--source/blender/blenlib/BLI_edgehash.h94
-rw-r--r--source/blender/blenlib/BLI_endian_switch.h41
-rw-r--r--source/blender/blenlib/BLI_fileops.h6
-rw-r--r--source/blender/blenlib/BLI_fnmatch.h9
-rw-r--r--source/blender/blenlib/BLI_ghash.h179
-rw-r--r--source/blender/blenlib/BLI_jitter.h4
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h2
-rw-r--r--source/blender/blenlib/BLI_kdtree.h33
-rw-r--r--source/blender/blenlib/BLI_lasso.h6
-rw-r--r--source/blender/blenlib/BLI_linklist.h18
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h159
-rw-r--r--source/blender/blenlib/BLI_listbase.h5
-rw-r--r--source/blender/blenlib/BLI_math_base.h1
-rw-r--r--source/blender/blenlib/BLI_math_geom.h40
-rw-r--r--source/blender/blenlib/BLI_math_interp.h10
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h2
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h11
-rw-r--r--source/blender/blenlib/BLI_math_vector.h97
-rw-r--r--source/blender/blenlib/BLI_memarena.h54
-rw-r--r--source/blender/blenlib/BLI_mempool.h99
-rw-r--r--source/blender/blenlib/BLI_path_util.h27
-rw-r--r--source/blender/blenlib/BLI_scanfill.h32
-rw-r--r--source/blender/blenlib/BLI_smallhash.h32
-rw-r--r--source/blender/blenlib/BLI_sort.h (renamed from source/blender/compositor/operations/COM_MixColorOperation.h)46
-rw-r--r--source/blender/blenlib/BLI_sort_utils.h61
-rw-r--r--source/blender/blenlib/BLI_strict_flags.h (renamed from source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h)45
-rw-r--r--source/blender/blenlib/BLI_string.h157
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h60
-rw-r--r--source/blender/blenlib/BLI_threads.h1
-rw-r--r--source/blender/blenlib/BLI_utildefines.h8
-rw-r--r--source/blender/blenlib/BLI_winstuff.h1
-rw-r--r--source/blender/blenlib/CMakeLists.txt20
-rw-r--r--source/blender/blenlib/PIL_time.h38
-rw-r--r--source/blender/blenlib/PIL_time_utildefines.h96
-rw-r--r--source/blender/blenlib/intern/BLI_array.c2
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c793
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c9
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c68
-rw-r--r--source/blender/blenlib/intern/BLI_kdtree.c171
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c86
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c77
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c469
-rw-r--r--source/blender/blenlib/intern/boxpack2d.c16
-rw-r--r--source/blender/blenlib/intern/buffer.c4
-rw-r--r--source/blender/blenlib/intern/callbacks.c4
-rw-r--r--source/blender/blenlib/intern/convexhull2d.c338
-rw-r--r--source/blender/blenlib/intern/edgehash.c488
-rw-r--r--source/blender/blenlib/intern/fileops.c5
-rw-r--r--source/blender/blenlib/intern/gsqueue.c17
-rw-r--r--source/blender/blenlib/intern/lasso.c17
-rw-r--r--source/blender/blenlib/intern/listbase.c51
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c11
-rw-r--r--source/blender/blenlib/intern/math_geom.c366
-rw-r--r--source/blender/blenlib/intern/math_geom_inline.c5
-rw-r--r--source/blender/blenlib/intern/math_interp.c4
-rw-r--r--source/blender/blenlib/intern/math_matrix.c18
-rw-r--r--source/blender/blenlib/intern/math_rotation.c34
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c49
-rw-r--r--source/blender/blenlib/intern/path_util.c40
-rw-r--r--source/blender/blenlib/intern/quadric.c2
-rw-r--r--source/blender/blenlib/intern/rand.c16
-rw-r--r--source/blender/blenlib/intern/scanfill.c299
-rw-r--r--source/blender/blenlib/intern/smallhash.c17
-rw-r--r--source/blender/blenlib/intern/sort.c173
-rw-r--r--source/blender/blenlib/intern/sort_utils.c74
-rw-r--r--source/blender/blenlib/intern/storage.c1
-rw-r--r--source/blender/blenlib/intern/threads.c13
-rw-r--r--source/blender/blenloader/BLO_readfile.h5
-rw-r--r--source/blender/blenloader/CMakeLists.txt1
-rw-r--r--source/blender/blenloader/intern/readblenentry.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c289
-rw-r--r--source/blender/blenloader/intern/undofile.c6
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c57
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c34
-rw-r--r--source/blender/blenloader/intern/writefile.c70
-rw-r--r--source/blender/bmesh/CMakeLists.txt11
-rw-r--r--source/blender/bmesh/bmesh.h57
-rw-r--r--source/blender/bmesh/bmesh_class.h12
-rw-r--r--source/blender/bmesh/bmesh_tools.h (renamed from source/blender/compositor/operations/COM_MixBurnOperation.h)50
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c177
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h18
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c84
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h13
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_inline.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c56
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h28
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c64
-rw-r--r--source/blender/bmesh/intern/bmesh_log.h15
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c12
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c11
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c70
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h32
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api_inline.h84
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c222
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c98
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h50
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c157
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c14
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c195
-rw-r--r--source/blender/bmesh/operators/bmo_beautify.c211
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c1
-rw-r--r--source/blender/bmesh/operators/bmo_bisect_plane.c112
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c15
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c12
-rw-r--r--source/blender/bmesh/operators/bmo_connect_nonplanar.c19
-rw-r--r--source/blender/bmesh/operators/bmo_create.c9
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c78
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c198
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c1018
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c20
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c176
-rw-r--r--source/blender/bmesh/operators/bmo_fill_edgeloop.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c311
-rw-r--r--source/blender/bmesh/operators/bmo_fill_holes.c120
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c42
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c444
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c35
-rw-r--r--source/blender/bmesh/operators/bmo_normals.c17
-rw-r--r--source/blender/bmesh/operators/bmo_poke.c6
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c42
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c70
-rw-r--r--source/blender/bmesh/operators/bmo_split_edges.c1
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c2
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c38
-rw-r--r--source/blender/bmesh/operators/bmo_symmetrize.c673
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c38
-rw-r--r--source/blender/bmesh/operators/bmo_unsubdivide.c1
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c6
-rw-r--r--source/blender/bmesh/operators/bmo_wireframe.c34
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c59
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c408
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.h (renamed from source/blender/compositor/operations/COM_RenderLayersAlphaProg.h)27
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_dissolve.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c7
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c508
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.h (renamed from source/blender/compositor/operations/COM_RenderLayersColorOperation.h)24
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.h6
-rw-r--r--source/blender/collada/AnimationExporter.cpp4
-rw-r--r--source/blender/collada/ArmatureExporter.cpp8
-rw-r--r--source/blender/collada/CameraExporter.cpp12
-rw-r--r--source/blender/collada/CameraExporter.h2
-rw-r--r--source/blender/collada/ControllerExporter.cpp4
-rw-r--r--source/blender/collada/DocumentImporter.cpp7
-rw-r--r--source/blender/collada/ExportSettings.h2
-rw-r--r--source/blender/collada/MeshImporter.cpp17
-rw-r--r--source/blender/collada/collada.cpp14
-rw-r--r--source/blender/collada/collada.h2
-rw-r--r--source/blender/collada/collada_utils.cpp2
-rw-r--r--source/blender/collada/version.conf1
-rw-r--r--source/blender/compositor/CMakeLists.txt135
-rw-r--r--source/blender/compositor/COM_compositor.h5
-rw-r--r--source/blender/compositor/COM_defines.h6
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp15
-rw-r--r--source/blender/compositor/intern/COM_Debug.cpp413
-rw-r--r--source/blender/compositor/intern/COM_Debug.h79
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cpp28
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h3
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp15
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp147
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.h6
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp9
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h81
-rw-r--r--source/blender/compositor/intern/COM_NodeBase.h2
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h3
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_AlphaOverNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ChannelMatteNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_ChromaMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorBalanceNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorRampNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorToBWNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CombineHSVANode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_CombineRGBANode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CombineYCCANode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CombineYUVANode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_DistanceMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_FilterNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_GlareNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp25
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.h2
-rw-r--r--source/blender/compositor/nodes/COM_KeyingNode.cpp5
-rw-r--r--source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.cpp19
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp81
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h (renamed from source/blender/compositor/operations/COM_RenderLayersMistOperation.h)25
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cpp21
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.h2
-rw-r--r--source/blender/compositor/nodes/COM_SeparateHSVANode.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_SeparateRGBANode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_SeparateYCCANode.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_SeparateYUVANode.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_SplitViewerNode.cpp5
-rw-r--r--source/blender/compositor/nodes/COM_TranslateNode.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_ZCombineNode.cpp2
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverKeyOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverMixedOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_ChangeHSVOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_ChromaMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_ColorMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_CombineChannelsOperation.cpp76
-rw-r--r--source/blender/compositor/operations/COM_CombineChannelsOperation.h42
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp47
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorToBWOperation.h60
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorToValueProg.cpp47
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorToValueProg.h59
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorToVectorOperation.cpp45
-rw-r--r--source/blender/compositor/operations/COM_ConvertColorToVectorOperation.h59
-rw-r--r--source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.cpp50
-rw-r--r--source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.h59
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.cpp429
-rw-r--r--source/blender/compositor/operations/COM_ConvertOperation.h202
-rw-r--r--source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp60
-rw-r--r--source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.cpp49
-rw-r--r--source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.h60
-rw-r--r--source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.cpp70
-rw-r--r--source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.h68
-rw-r--r--source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.cpp48
-rw-r--r--source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.h59
-rw-r--r--source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp55
-rw-r--r--source/blender/compositor/operations/COM_ConvertValueToColorProg.cpp47
-rw-r--r--source/blender/compositor/operations/COM_ConvertValueToColorProg.h53
-rw-r--r--source/blender/compositor/operations/COM_ConvertValueToVectorOperation.cpp50
-rw-r--r--source/blender/compositor/operations/COM_ConvertValueToVectorOperation.h59
-rw-r--r--source/blender/compositor/operations/COM_ConvertVectorToColorOperation.cpp46
-rw-r--r--source/blender/compositor/operations/COM_ConvertVectorToColorOperation.h59
-rw-r--r--source/blender/compositor/operations/COM_ConvertVectorToValueOperation.cpp47
-rw-r--r--source/blender/compositor/operations/COM_ConvertVectorToValueOperation.h59
-rw-r--r--source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.cpp70
-rw-r--r--source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.h68
-rw-r--r--source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.cpp49
-rw-r--r--source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.h58
-rw-r--r--source/blender/compositor/operations/COM_DifferenceMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_GlareGhostOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_GlareStreaksOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.cpp64
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_LuminanceMatteOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.cpp26
-rw-r--r--source/blender/compositor/operations/COM_MixAddOperation.cpp51
-rw-r--r--source/blender/compositor/operations/COM_MixAddOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixBaseOperation.cpp95
-rw-r--r--source/blender/compositor/operations/COM_MixBaseOperation.h81
-rw-r--r--source/blender/compositor/operations/COM_MixBlendOperation.cpp52
-rw-r--r--source/blender/compositor/operations/COM_MixBurnOperation.cpp90
-rw-r--r--source/blender/compositor/operations/COM_MixColorOperation.cpp68
-rw-r--r--source/blender/compositor/operations/COM_MixDarkenOperation.cpp60
-rw-r--r--source/blender/compositor/operations/COM_MixDarkenOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixDifferenceOperation.cpp53
-rw-r--r--source/blender/compositor/operations/COM_MixDifferenceOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixDivideOperation.cpp63
-rw-r--r--source/blender/compositor/operations/COM_MixDivideOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixDodgeOperation.cpp95
-rw-r--r--source/blender/compositor/operations/COM_MixDodgeOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixGlareOperation.cpp53
-rw-r--r--source/blender/compositor/operations/COM_MixGlareOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixHueOperation.cpp67
-rw-r--r--source/blender/compositor/operations/COM_MixHueOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixLightenOperation.cpp58
-rw-r--r--source/blender/compositor/operations/COM_MixLightenOperation.h44
-rw-r--r--source/blender/compositor/operations/COM_MixLinearLightOperation.cpp60
-rw-r--r--source/blender/compositor/operations/COM_MixLinearLightOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixMultiplyOperation.cpp52
-rw-r--r--source/blender/compositor/operations/COM_MixMultiplyOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.cpp848
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.h197
-rw-r--r--source/blender/compositor/operations/COM_MixOverlayOperation.cpp69
-rw-r--r--source/blender/compositor/operations/COM_MixOverlayOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixSaturationOperation.cpp64
-rw-r--r--source/blender/compositor/operations/COM_MixSaturationOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixScreenOperation.cpp53
-rw-r--r--source/blender/compositor/operations/COM_MixScreenOperation.h44
-rw-r--r--source/blender/compositor/operations/COM_MixSoftLightOperation.cpp59
-rw-r--r--source/blender/compositor/operations/COM_MixSoftLightOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixSubtractOperation.cpp51
-rw-r--r--source/blender/compositor/operations/COM_MixSubtractOperation.h45
-rw-r--r--source/blender/compositor/operations/COM_MixValueOperation.cpp58
-rw-r--r--source/blender/compositor/operations/COM_MixValueOperation.h44
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.cpp21
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp18
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp95
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h62
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp70
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h (renamed from source/blender/compositor/operations/COM_SeparateChannelOperation.h)41
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp184
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h (renamed from source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h)46
-rw-r--r--source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.cpp34
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.h5
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersAOOperation.cpp29
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersAOOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersAlphaProg.cpp49
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp178
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersColorOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersCyclesOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersCyclesOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersDepthProg.cpp29
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersDepthProg.h34
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersEmitOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersEmitOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersImageProg.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersImageProg.h34
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersIndirectOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersIndirectOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersMistOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersNormalOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersNormalOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp361
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h (renamed from source/blender/compositor/operations/COM_RenderLayersBaseProg.h)103
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersReflectionOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersReflectionOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersRefractionOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersRefractionOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersShadowOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersShadowOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersSpecularOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersSpecularOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersSpeedOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersSpeedOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersUVOperation.cpp28
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersUVOperation.h33
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_SeparateChannelOperation.cpp47
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_SetVectorOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.cpp26
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.cpp16
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_ZCombineOperation.h2
-rw-r--r--source/blender/datatoc/datatoc.c4
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c7
-rw-r--r--source/blender/editors/animation/anim_filter.c26
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c2
-rw-r--r--source/blender/editors/animation/drivers.c38
-rw-r--r--source/blender/editors/animation/keyframes_edit.c2
-rw-r--r--source/blender/editors/animation/keyframing.c90
-rw-r--r--source/blender/editors/armature/armature_naming.c28
-rw-r--r--source/blender/editors/armature/armature_skinning.c5
-rw-r--r--source/blender/editors/armature/armature_utils.c2
-rw-r--r--source/blender/editors/armature/meshlaplacian.c2
-rw-r--r--source/blender/editors/armature/pose_edit.c30
-rw-r--r--source/blender/editors/armature/pose_slide.c6
-rw-r--r--source/blender/editors/armature/reeb.c2
-rw-r--r--source/blender/editors/curve/CMakeLists.txt1
-rw-r--r--source/blender/editors/curve/curve_intern.h39
-rw-r--r--source/blender/editors/curve/curve_ops.c2
-rw-r--r--source/blender/editors/curve/editcurve.c1667
-rw-r--r--source/blender/editors/curve/editcurve_add.c812
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/curve/lorem.c1
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt10
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c13
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c8
-rw-r--r--source/blender/editors/include/BIF_glutil.h3
-rw-r--r--source/blender/editors/include/ED_anim_api.h36
-rw-r--r--source/blender/editors/include/ED_armature.h7
-rw-r--r--source/blender/editors/include/ED_clip.h8
-rw-r--r--source/blender/editors/include/ED_curve.h1
-rw-r--r--source/blender/editors/include/ED_keyframing.h1
-rw-r--r--source/blender/editors/include/ED_lattice.h5
-rw-r--r--source/blender/editors/include/ED_mask.h2
-rw-r--r--source/blender/editors/include/ED_mball.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h16
-rw-r--r--source/blender/editors/include/ED_object.h18
-rw-r--r--source/blender/editors/include/ED_render.h2
-rw-r--r--source/blender/editors/include/ED_screen_types.h6
-rw-r--r--source/blender/editors/include/ED_util.h6
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h7
-rw-r--r--source/blender/editors/include/UI_icons.h10
-rw-r--r--source/blender/editors/include/UI_interface.h37
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/include/UI_view2d.h3
-rw-r--r--source/blender/editors/interface/CMakeLists.txt1
-rw-r--r--source/blender/editors/interface/interface.c43
-rw-r--r--source/blender/editors/interface/interface_anim.c2
-rw-r--r--source/blender/editors/interface/interface_draw.c6
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c639
-rw-r--r--source/blender/editors/interface/interface_handlers.c569
-rw-r--r--source/blender/editors/interface/interface_intern.h10
-rw-r--r--source/blender/editors/interface/interface_layout.c19
-rw-r--r--source/blender/editors/interface/interface_ops.c379
-rw-r--r--source/blender/editors/interface/interface_regions.c45
-rw-r--r--source/blender/editors/interface/interface_templates.c571
-rw-r--r--source/blender/editors/interface/interface_widgets.c43
-rw-r--r--source/blender/editors/interface/resources.c21
-rw-r--r--source/blender/editors/interface/view2d.c11
-rw-r--r--source/blender/editors/interface/view2d_ops.c50
-rw-r--r--source/blender/editors/io/io_collada.c32
-rw-r--r--source/blender/editors/mask/mask_add.c156
-rw-r--r--source/blender/editors/mask/mask_edit.c53
-rw-r--r--source/blender/editors/mask/mask_intern.h5
-rw-r--r--source/blender/editors/mask/mask_ops.c127
-rw-r--r--source/blender/editors/mask/mask_relationships.c56
-rw-r--r--source/blender/editors/mask/mask_shapekey.c1
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt2
-rw-r--r--source/blender/editors/mesh/editface.c31
-rw-r--r--source/blender/editors/mesh/editmesh_add.c39
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c331
-rw-r--r--source/blender/editors/mesh/editmesh_deform_laplacian.c6
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c2
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c6
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c455
-rw-r--r--source/blender/editors/mesh/editmesh_path.c3
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c122
-rw-r--r--source/blender/editors/mesh/editmesh_select.c133
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c329
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c7
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c8
-rw-r--r--source/blender/editors/mesh/mesh_ops.c1
-rw-r--r--source/blender/editors/mesh/meshtools.c36
-rw-r--r--source/blender/editors/metaball/mball_edit.c14
-rw-r--r--source/blender/editors/object/object_add.c48
-rw-r--r--source/blender/editors/object/object_bake.c87
-rw-r--r--source/blender/editors/object/object_edit.c132
-rw-r--r--source/blender/editors/object/object_group.c4
-rw-r--r--source/blender/editors/object/object_hook.c4
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/object/object_relations.c90
-rw-r--r--source/blender/editors/object/object_transform.c87
-rw-r--r--source/blender/editors/object/object_vgroup.c460
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c6
-rw-r--r--source/blender/editors/physics/particle_edit.c48
-rw-r--r--source/blender/editors/physics/physics_pointcache.c4
-rw-r--r--source/blender/editors/render/render_internal.c80
-rw-r--r--source/blender/editors/render/render_opengl.c27
-rw-r--r--source/blender/editors/render/render_preview.c7
-rw-r--r--source/blender/editors/render/render_shading.c48
-rw-r--r--source/blender/editors/screen/area.c9
-rw-r--r--source/blender/editors/screen/glutil.c63
-rw-r--r--source/blender/editors/screen/screen_edit.c30
-rw-r--r--source/blender/editors/screen/screen_ops.c44
-rw-r--r--source/blender/editors/screen/screendump.c18
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c26
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c38
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c56
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c23
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c24
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c138
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c230
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c8
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c37
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c15
-rw-r--r--source/blender/editors/space_clip/clip_draw.c326
-rw-r--r--source/blender/editors/space_clip/clip_editor.c33
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c6
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c39
-rw-r--r--source/blender/editors/space_clip/clip_intern.h12
-rw-r--r--source/blender/editors/space_clip/clip_ops.c81
-rw-r--r--source/blender/editors/space_clip/clip_utils.c69
-rw-r--r--source/blender/editors/space_clip/space_clip.c160
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c586
-rw-r--r--source/blender/editors/space_clip/tracking_select.c277
-rw-r--r--source/blender/editors/space_console/console_ops.c1
-rw-r--r--source/blender/editors/space_console/space_console.c1
-rw-r--r--source/blender/editors/space_file/file_intern.h2
-rw-r--r--source/blender/editors/space_file/file_ops.c4
-rw-r--r--source/blender/editors/space_file/file_panels.c3
-rw-r--r--source/blender/editors/space_file/filelist.c34
-rw-r--r--source/blender/editors/space_file/filesel.c56
-rw-r--r--source/blender/editors/space_file/space_file.c9
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_graph/graph_edit.c51
-rw-r--r--source/blender/editors/space_graph/graph_select.c31
-rw-r--r--source/blender/editors/space_image/image_draw.c12
-rw-r--r--source/blender/editors/space_image/image_ops.c53
-rw-r--r--source/blender/editors/space_image/space_image.c8
-rw-r--r--source/blender/editors/space_info/info_stats.c10
-rw-r--r--source/blender/editors/space_info/textview.c13
-rw-r--r--source/blender/editors/space_info/textview.h4
-rw-r--r--source/blender/editors/space_logic/logic_ops.c5
-rw-r--r--source/blender/editors/space_logic/logic_window.c11
-rw-r--r--source/blender/editors/space_node/drawnode.c91
-rw-r--r--source/blender/editors/space_node/node_add.c14
-rw-r--r--source/blender/editors/space_node/node_buttons.c6
-rw-r--r--source/blender/editors/space_node/node_draw.c36
-rw-r--r--source/blender/editors/space_node/node_edit.c32
-rw-r--r--source/blender/editors/space_node/node_intern.h8
-rw-r--r--source/blender/editors/space_node/node_ops.c2
-rw-r--r--source/blender/editors/space_node/node_relationships.c42
-rw-r--r--source/blender/editors/space_node/node_select.c20
-rw-r--r--source/blender/editors/space_node/node_view.c69
-rw-r--r--source/blender/editors/space_node/space_node.c14
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c99
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c112
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c12
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c6
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c1
-rw-r--r--source/blender/editors/space_text/space_text.c2
-rw-r--r--source/blender/editors/space_text/text_draw.c22
-rw-r--r--source/blender/editors/space_text/text_intern.h5
-rw-r--r--source/blender/editors/space_text/text_ops.c49
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c20
-rw-r--r--source/blender/editors/space_view3d/drawobject.c104
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c1
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c510
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h6
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c13
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c44
-rw-r--r--source/blender/editors/transform/transform.c98
-rw-r--r--source/blender/editors/transform/transform.h7
-rw-r--r--source/blender/editors/transform/transform_constraints.c8
-rw-r--r--source/blender/editors/transform/transform_conversions.c389
-rw-r--r--source/blender/editors/transform/transform_generics.c41
-rw-r--r--source/blender/editors/transform/transform_manipulator.c17
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c38
-rw-r--r--source/blender/editors/transform/transform_snap.c137
-rw-r--r--source/blender/editors/util/crazyspace.c249
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c14
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c8
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c76
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h2
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c5
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c6
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp7
-rw-r--r--source/blender/freestyle/intern/application/Controller.h1
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp14
-rw-r--r--source/blender/freestyle/intern/geometry/BBox.h6
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp2
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp2
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRep.cpp12
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeShader.h2
-rw-r--r--source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp39
-rw-r--r--source/blender/freestyle/intern/stroke/TextStrokeRenderer.h49
-rw-r--r--source/blender/freestyle/intern/view_map/Functions0D.h4
-rw-r--r--source/blender/freestyle/intern/view_map/Functions1D.h2
-rw-r--r--source/blender/freestyle/intern/view_map/SteerableViewMap.h2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.h2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp2
-rw-r--r--source/blender/gpu/GPU_buffers.h9
-rw-r--r--source/blender/gpu/GPU_extensions.h1
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c99
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c4
-rw-r--r--source/blender/gpu/intern/gpu_draw.c2
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c10
-rw-r--r--source/blender/gpu/intern/gpu_material.c9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl31
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h55
-rw-r--r--source/blender/imbuf/IMB_imbuf.h18
-rw-r--r--source/blender/imbuf/intern/IMB_allocimbuf.h4
-rw-r--r--source/blender/imbuf/intern/IMB_colormanagement_intern.h29
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h1
-rw-r--r--source/blender/imbuf/intern/IMB_indexer.h4
-rw-r--r--source/blender/imbuf/intern/IMB_metadata.h6
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c108
-rw-r--r--source/blender/imbuf/intern/bmp.c4
-rw-r--r--source/blender/imbuf/intern/colormanagement.c318
-rw-r--r--source/blender/imbuf/intern/divers.c4
-rw-r--r--source/blender/imbuf/intern/imageprocess.c14
-rw-r--r--source/blender/imbuf/intern/indexer.c4
-rw-r--r--source/blender/imbuf/intern/indexer_dv.c4
-rw-r--r--source/blender/imbuf/intern/jpeg.c6
-rw-r--r--source/blender/imbuf/intern/metadata.c30
-rw-r--r--source/blender/makesdna/DNA_ID.h2
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h6
-rw-r--r--source/blender/makesdna/DNA_color_types.h1
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h6
-rw-r--r--source/blender/makesdna/DNA_curve_types.h3
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h110
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h4
-rw-r--r--source/blender/makesdna/DNA_ipo_types.h2
-rw-r--r--source/blender/makesdna/DNA_key_types.h1
-rw-r--r--source/blender/makesdna/DNA_lattice_types.h4
-rw-r--r--source/blender/makesdna/DNA_linestyle_types.h4
-rw-r--r--source/blender/makesdna/DNA_mask_types.h13
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h2
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h245
-rw-r--r--source/blender/makesdna/DNA_meta_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h970
-rw-r--r--source/blender/makesdna/DNA_node_types.h21
-rw-r--r--source/blender/makesdna/DNA_object_types.h430
-rw-r--r--source/blender/makesdna/DNA_particle_types.h4
-rw-r--r--source/blender/makesdna/DNA_scene_types.h53
-rw-r--r--source/blender/makesdna/DNA_screen_types.h71
-rw-r--r--source/blender/makesdna/DNA_sensor_types.h3
-rw-r--r--source/blender/makesdna/DNA_space_types.h18
-rw-r--r--source/blender/makesdna/DNA_texture_types.h8
-rw-r--r--source/blender/makesdna/DNA_tracking_types.h56
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h8
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt3
-rw-r--r--source/blender/makesdna/intern/SConscript4
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c2
-rw-r--r--source/blender/makesrna/RNA_access.h52
-rw-r--r--source/blender/makesrna/RNA_define.h6
-rw-r--r--source/blender/makesrna/RNA_enum_types.h2
-rw-r--r--source/blender/makesrna/RNA_types.h200
-rw-r--r--source/blender/makesrna/SConscript1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt6
-rw-r--r--source/blender/makesrna/intern/makesrna.c35
-rw-r--r--source/blender/makesrna/intern/rna_ID.c3
-rw-r--r--source/blender/makesrna/intern/rna_access.c225
-rw-r--r--source/blender/makesrna/intern/rna_action.c5
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c16
-rw-r--r--source/blender/makesrna/intern/rna_animation.c3
-rw-r--r--source/blender/makesrna/intern/rna_animviz.c5
-rw-r--r--source/blender/makesrna/intern/rna_armature.c2
-rw-r--r--source/blender/makesrna/intern/rna_boid.c10
-rw-r--r--source/blender/makesrna/intern/rna_brush.c5
-rw-r--r--source/blender/makesrna/intern/rna_color.c85
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c38
-rw-r--r--source/blender/makesrna/intern/rna_controller.c1
-rw-r--r--source/blender/makesrna/intern/rna_curve.c20
-rw-r--r--source/blender/makesrna/intern/rna_define.c37
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c14
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c25
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c12
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h12
-rw-r--r--source/blender/makesrna/intern/rna_key.c10
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c3
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c2
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c11
-rw-r--r--source/blender/makesrna/intern/rna_mask.c49
-rw-r--r--source/blender/makesrna/intern/rna_material.c13
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c128
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c61
-rw-r--r--source/blender/makesrna/intern/rna_mesh_utils.h8
-rw-r--r--source/blender/makesrna/intern/rna_meta.c8
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c11
-rw-r--r--source/blender/makesrna/intern/rna_nla.c7
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c356
-rw-r--r--source/blender/makesrna/intern/rna_object.c30
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c10
-rw-r--r--source/blender/makesrna/intern/rna_packedfile.c1
-rw-r--r--source/blender/makesrna/intern/rna_particle.c118
-rw-r--r--source/blender/makesrna/intern/rna_pose.c8
-rw-r--r--source/blender/makesrna/intern/rna_property.c4
-rw-r--r--source/blender/makesrna/intern/rna_render.c47
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c33
-rw-r--r--source/blender/makesrna/intern/rna_rna.c12
-rw-r--r--source/blender/makesrna/intern/rna_scene.c132
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_screen.c3
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c10
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c34
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c23
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c74
-rw-r--r--source/blender/makesrna/intern/rna_test.c7
-rw-r--r--source/blender/makesrna/intern/rna_text.c11
-rw-r--r--source/blender/makesrna/intern/rna_texture.c28
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c369
-rw-r--r--source/blender/makesrna/intern/rna_ui.c259
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c59
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c13
-rw-r--r--source/blender/makesrna/intern/rna_wm.c61
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c73
-rw-r--r--source/blender/modifiers/intern/MOD_array.c21
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c3
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c108
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.h6
-rw-r--r--source/blender/modifiers/intern/MOD_build.c2
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c2
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c32
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_util.c4
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_util.h3
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c8
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c18
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c8
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c3
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c21
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/NOD_common.h6
-rw-r--r--source/blender/nodes/NOD_composite.h3
-rw-r--r--source/blender/nodes/NOD_shader.h3
-rw-r--r--source/blender/nodes/NOD_static_types.h7
-rw-r--r--source/blender/nodes/NOD_texture.h2
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c30
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapValue.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c17
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c64
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_scale.c19
-rw-r--r--source/blender/nodes/intern/node_exec.c4
-rw-r--r--source/blender/nodes/intern/node_util.c104
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c9
-rw-r--r--source/blender/nodes/shader/node_shader_util.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c66
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c15
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c44
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_checker.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c5
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.c2
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_common.c18
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c26
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c37
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h6
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c1
-rw-r--r--source/blender/python/generic/blf_py_api.h6
-rw-r--r--source/blender/python/generic/idprop_py_api.c2
-rw-r--r--source/blender/python/generic/py_capi_utils.c11
-rw-r--r--source/blender/python/generic/py_capi_utils.h2
-rw-r--r--source/blender/python/intern/bpy.h1
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c2
-rw-r--r--source/blender/python/intern/bpy_driver.c6
-rw-r--r--source/blender/python/intern/bpy_interface.c12
-rw-r--r--source/blender/python/intern/bpy_intern_string.h5
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c9
-rw-r--r--source/blender/python/intern/bpy_props.c34
-rw-r--r--source/blender/python/intern/bpy_rna.c85
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c3
-rw-r--r--source/blender/python/intern/bpy_rna_anim.h5
-rw-r--r--source/blender/python/intern/bpy_rna_callback.h6
-rw-r--r--source/blender/python/intern/gpu.h9
-rw-r--r--source/blender/python/mathutils/mathutils.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c10
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c10
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c145
-rw-r--r--source/blender/quicktime/apple/qtkit_export.m14
-rw-r--r--source/blender/quicktime/apple/qtkit_import.m28
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h4
-rw-r--r--source/blender/render/intern/include/texture.h12
-rw-r--r--source/blender/render/intern/include/texture_ocean.h4
-rw-r--r--source/blender/render/intern/source/bake.c15
-rw-r--r--source/blender/render/intern/source/convertblender.c10
-rw-r--r--source/blender/render/intern/source/external_engine.c31
-rw-r--r--source/blender/render/intern/source/pipeline.c68
-rw-r--r--source/blender/render/intern/source/pointdensity.c8
-rw-r--r--source/blender/render/intern/source/rayshade.c13
-rw-r--r--source/blender/render/intern/source/render_result.c2
-rw-r--r--source/blender/render/intern/source/rendercore.c52
-rw-r--r--source/blender/render/intern/source/shadbuf.c15
-rw-r--r--source/blender/render/intern/source/shadeoutput.c4
-rw-r--r--source/blender/render/intern/source/texture_ocean.c4
-rw-r--r--source/blender/render/intern/source/voxeldata.c2
-rw-r--r--source/blender/render/intern/source/zbuf.c2
-rw-r--r--source/blender/windowmanager/WM_api.h37
-rw-r--r--source/blender/windowmanager/WM_keymap.h5
-rw-r--r--source/blender/windowmanager/WM_types.h34
-rw-r--r--source/blender/windowmanager/intern/wm.c17
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c26
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c8
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c56
-rw-r--r--source/blender/windowmanager/intern/wm_files.c13
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c96
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c3
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c18
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c29
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c137
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c2
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c9
-rw-r--r--source/blender/windowmanager/intern/wm_window.c12
-rw-r--r--source/blender/windowmanager/wm_subwindow.h1
-rw-r--r--source/blender/windowmanager/wm_window.h2
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c11
-rw-r--r--source/creator/CMakeLists.txt12
-rw-r--r--source/creator/creator.c27
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp4
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp10
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp7
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.h2
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp25
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.h2
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp2
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.cpp12
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp15
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.h1
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp24
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp37
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_IScene.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.cpp19
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp4
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp27
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp11
-rw-r--r--source/gameengine/Ketsji/BL_Action.h14
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.cpp6
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.h9
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp1
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.h8
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp165
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h19
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_Light.h4
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.h4
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp11
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.cpp65
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.cpp7
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp69
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.h3
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp5
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h1
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp6
-rw-r--r--source/tests/bl_run_operators.py3
987 files changed, 33084 insertions, 21923 deletions
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 529aaac4923..391fdf42d28 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -28,9 +28,5 @@ add_subdirectory(blender)
if(WITH_GAMEENGINE)
add_subdirectory(gameengine)
endif()
-
-if(WINDOWS)
- add_subdirectory(icons)
-endif()
add_subdirectory(tests)
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 15098d50531..d46df829295 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -50,6 +50,7 @@
#include "BLI_string_utf8.h"
#include "BLI_threads.h"
#include "BLI_linklist.h" /* linknode */
+#include "BLI_strict_flags.h"
#include "BIF_gl.h"
#include "BLF_api.h"
@@ -59,10 +60,6 @@
#include "blf_internal_types.h"
#include "blf_internal.h"
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-#endif
-
/* freetype2 handle ONLY for this file!. */
static FT_Library ft_lib;
static SpinLock ft_lib_mutex;
@@ -163,7 +160,7 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
_kern_mode, \
&(_delta)) == 0) \
{ \
- _pen_x += _delta.x >> 6; \
+ _pen_x += (int)_delta.x >> 6; \
} \
} \
} (void)0
@@ -194,7 +191,7 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len)
/* 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;
+ pen_x += (int)g->advance;
g_prev = g;
}
}
@@ -221,7 +218,7 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
/* 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;
+ pen_x += (int)g->advance;
g_prev = g;
}
}
@@ -273,10 +270,11 @@ void blf_font_buffer(FontBLF *font, const char *str)
/* buffer specific vars */
FontBufInfoBLF *buf_info = &font->buf_info;
float b_col_float[4];
- const unsigned char b_col_char[4] = {buf_info->col[0] * 255,
- buf_info->col[1] * 255,
- buf_info->col[2] * 255,
- buf_info->col[3] * 255};
+ const unsigned char b_col_char[4] = {
+ (unsigned char)(buf_info->col[0] * 255),
+ (unsigned char)(buf_info->col[1] * 255),
+ (unsigned char)(buf_info->col[2] * 255),
+ (unsigned char)(buf_info->col[3] * 255)};
unsigned char *cbuf;
int chx, chy;
@@ -378,14 +376,27 @@ void blf_font_buffer(FontBLF *font, const char *str)
cbuf[0] = b_col_char[0];
cbuf[1] = b_col_char[1];
cbuf[2] = b_col_char[2];
- cbuf[3] = (alphatest = ((int)cbuf[3] + (int)b_col_char[3])) < 255 ? alphatest : 255;
+
+ alphatest = (int)cbuf[3] + (int)b_col_char[3];
+ if (alphatest < 255) {
+ cbuf[3] = (unsigned char)(alphatest);
+ }
+ else {
+ cbuf[3] = 255;
+ }
}
else {
- cbuf[0] = (b_col_char[0] * a) + (cbuf[0] * (1.0f - a));
- cbuf[1] = (b_col_char[1] * a) + (cbuf[1] * (1.0f - a));
- cbuf[2] = (b_col_char[2] * a) + (cbuf[2] * (1.0f - a));
- cbuf[3] = (alphatest = ((int)cbuf[3] + (int)((b_col_float[3] * a) * 255.0f))) <
- 255 ? alphatest : 255;
+ cbuf[0] = (unsigned char)((b_col_char[0] * a) + (cbuf[0] * (1.0f - a)));
+ cbuf[1] = (unsigned char)((b_col_char[1] * a) + (cbuf[1] * (1.0f - a)));
+ cbuf[2] = (unsigned char)((b_col_char[2] * a) + (cbuf[2] * (1.0f - a)));
+
+ alphatest = ((int)cbuf[3] + (int)((b_col_float[3] * a) * 255.0f));
+ if (alphatest < 255) {
+ cbuf[3] = (unsigned char)(alphatest);
+ }
+ else {
+ cbuf[3] = 255;
+ }
}
}
}
@@ -398,7 +409,7 @@ void blf_font_buffer(FontBLF *font, const char *str)
}
}
- pen_x += g->advance;
+ pen_x += (int)g->advance;
g_prev = g;
}
}
@@ -433,10 +444,10 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
- gbox.xmin = pen_x;
- gbox.xmax = pen_x + g->advance;
- gbox.ymin = g->box.ymin + pen_y;
- gbox.ymax = g->box.ymax + pen_y;
+ gbox.xmin = (float)pen_x;
+ gbox.xmax = (float)pen_x + g->advance;
+ gbox.ymin = g->box.ymin + (float)pen_y;
+ gbox.ymax = g->box.ymax + (float)pen_y;
if (gbox.xmin < box->xmin) box->xmin = gbox.xmin;
if (gbox.ymin < box->ymin) box->ymin = gbox.ymin;
@@ -444,7 +455,7 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
if (gbox.xmax > box->xmax) box->xmax = gbox.xmax;
if (gbox.ymax > box->ymax) box->ymax = gbox.ymax;
- pen_x += g->advance;
+ pen_x += (int)g->advance;
g_prev = g;
}
@@ -524,9 +535,7 @@ void blf_font_free(FontBLF *font)
GlyphCacheBLF *gc;
font->glyph_cache = NULL;
- while (font->cache.first) {
- gc = font->cache.first;
- BLI_remlink(&font->cache, gc);
+ while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
}
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 37e874fa396..2a8e91299b4 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -56,9 +56,7 @@
#include "blf_internal_types.h"
#include "blf_internal.h"
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-#endif
+#include "BLI_strict_flags.h"
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
{
@@ -89,28 +87,28 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
gc->textures = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__);
gc->ntex = 256;
- gc->cur_tex = -1;
+ gc->cur_tex = BLF_CURTEX_UNSET;
gc->x_offs = 0;
gc->y_offs = 0;
gc->pad = 3;
- gc->num_glyphs = font->face->num_glyphs;
- gc->rem_glyphs = font->face->num_glyphs;
+ gc->num_glyphs = (int)font->face->num_glyphs;
+ gc->rem_glyphs = (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 = (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_width = (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 = (float)((font->face->bbox.yMax - font->face->bbox.yMin) *
- (((float)font->face->size->metrics.y_ppem) /
- ((float)font->face->units_per_EM)));
+ gc->max_glyph_height = (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 = ((float)font->face->size->metrics.max_advance) / 64.0f;
- gc->max_glyph_height = ((float)font->face->size->metrics.height) / 64.0f;
+ 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->p2_width = 0;
@@ -128,9 +126,7 @@ void blf_glyph_cache_clear(FontBLF *font)
for (gc = font->cache.first; gc; gc = gc->next) {
for (i = 0; i < 257; i++) {
- while (gc->bucket[i].first) {
- g = gc->bucket[i].first;
- BLI_remlink(&(gc->bucket[i]), g);
+ while ((g = BLI_pophead(&gc->bucket[i]))) {
blf_glyph_free(g);
}
}
@@ -145,15 +141,13 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
int i;
for (i = 0; i < 257; i++) {
- while (gc->bucket[i].first) {
- g = gc->bucket[i].first;
- BLI_remlink(&(gc->bucket[i]), g);
+ while ((g = BLI_pophead(&gc->bucket[i]))) {
blf_glyph_free(g);
}
}
- if (gc->cur_tex > -1)
- glDeleteTextures(gc->cur_tex + 1, gc->textures);
+ if (gc->cur_tex != BLF_CURTEX_UNSET)
+ glDeleteTextures((int)gc->cur_tex + 1, gc->textures);
MEM_freeN((void *)gc->textures);
MEM_freeN(gc);
}
@@ -287,7 +281,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
int i;
for (i = 0; i < (g->width * g->height); i++) {
- bitmap.buffer[i] = 255 * bitmap.buffer[i];
+ bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0;
}
}
@@ -296,8 +290,8 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
}
g->advance = ((float)slot->advance.x) / 64.0f;
- g->pos_x = slot->bitmap_left;
- g->pos_y = slot->bitmap_top;
+ g->pos_x = (float)slot->bitmap_left;
+ g->pos_y = (float)slot->bitmap_top;
g->pitch = slot->bitmap.pitch;
FT_Outline_Get_CBox(&(slot->outline), &bbox);
@@ -351,7 +345,7 @@ static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x
const float *fp = soft;
float color[4];
- int dx, dy;
+ float dx, dy;
color[0] = shadow_col[0];
color[1] = shadow_col[1];
@@ -376,7 +370,7 @@ static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x
const float *fp = soft;
float color[4];
- int dx, dy;
+ float dx, dy;
color[0] = shadow_col[0];
color[1] = shadow_col[1];
@@ -395,10 +389,10 @@ static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
{
- rect->xmin = floor(x + g->pos_x);
- rect->xmax = rect->xmin + g->width;
+ rect->xmin = (float)floor(x + g->pos_x);
+ rect->xmax = rect->xmin + (float)g->width;
rect->ymin = y + g->pos_y;
- rect->ymax = y + g->pos_y - g->height;
+ rect->ymax = y + g->pos_y - (float)g->height;
}
void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
@@ -414,7 +408,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
if (font->max_tex_size == -1)
glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size);
- if (gc->cur_tex == -1) {
+ if (gc->cur_tex == BLF_CURTEX_UNSET) {
blf_glyph_cache_texture(font, gc);
gc->x_offs = gc->pad;
gc->y_offs = 0;
@@ -462,7 +456,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
g->uv[1][1] = ((float)(g->yoff + 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->x_offs += (int)BLI_rctf_size_x(&g->box) + gc->pad;
gc->rem_glyphs--;
g->build_tex = 1;
@@ -486,7 +480,9 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
if (font->flags & BLF_SHADOW) {
rctf rect_ofs;
- blf_glyph_calc_rect(&rect_ofs, g, x + font->shadow_x, y + font->shadow_y);
+ blf_glyph_calc_rect(&rect_ofs, g,
+ x + (float)font->shadow_x,
+ y + (float)font->shadow_y);
switch (font->shadow) {
case 3:
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 096ff50a3ca..c64b7e974e7 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -54,7 +54,7 @@ typedef struct GlyphCacheBLF {
unsigned int ntex;
/* and the last texture, aka. the current texture. */
- int cur_tex;
+ unsigned int cur_tex;
/* like bftgl, we draw every glyph in a big texture, so this is the
* current position inside the texture.
@@ -235,4 +235,6 @@ typedef struct DirBLF {
char *path;
} DirBLF;
+#define BLF_CURTEX_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 8396380fd06..2bba968e03b 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -28,7 +28,9 @@
#ifndef __BKE_DERIVEDMESH_H__
#define __BKE_DERIVEDMESH_H__
-/**
+/** \file BKE_DerivedMesh.h
+ * \ingroup bke
+ *
* Basic design of the DerivedMesh system:
*
* DerivedMesh is a common set of interfaces for mesh systems.
@@ -72,6 +74,8 @@
#include "DNA_customdata_types.h"
#include "DNA_meshdata_types.h"
+#include "BLI_compiler_attrs.h"
+
#include "BKE_customdata.h"
#include "BKE_bvhutils.h"
@@ -95,8 +99,6 @@ struct BMEditMesh;
struct ListBase;
struct PBVH;
-#define DM_OMP_LIMIT 10000 /* setting zero so we can catch bugs in OpenMP/BMesh */
-
/* number of sub-elements each mesh element has (for interpolation) */
#define SUB_ELEMS_VERT 0
#define SUB_ELEMS_EDGE 2
@@ -733,14 +735,12 @@ void DM_init_origspace(DerivedMesh *dm);
char *DM_debug_info(DerivedMesh *dm);
void DM_debug_print(DerivedMesh *dm);
void DM_debug_print_cdlayers(CustomData *cdata);
-#endif
-#ifdef __GNUC__
-BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i)
- __attribute__((nonnull(1)))
-;
+bool DM_is_valid(DerivedMesh *dm);
#endif
+BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) ATTR_NONNULL(1);
+
BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i)
{
const int j = index_mf_to_mpoly[i];
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 12c9f6b449f..698098d28c3 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -188,6 +188,10 @@ struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
*/
struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name);
+#ifndef NDEBUG
+bool BKE_pose_channels_is_valid(const struct bPose *pose);
+#endif
+
/* Copy the data from the action-pose (src) into the pose */
void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
@@ -203,6 +207,9 @@ void BKE_pose_ikparam_init(struct bPose *pose);
/* initialize a bItasc structure with default value */
void BKE_pose_itasc_init(struct bItasc *itasc);
+/* Checks if a bone is part of an IK chain or not */
+bool BKE_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
+
/* clears BONE_UNKEYED flags for frame changing */
// XXX to be deprecated for a more general solution in animsys...
void framechange_poses_clear_unkeyed(void);
diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h
index eafaec3e605..739a4e3eee6 100644
--- a/source/blender/blenkernel/BKE_addon.h
+++ b/source/blender/blenkernel/BKE_addon.h
@@ -22,6 +22,10 @@
#ifndef __BKE_ADDON_H__
#define __BKE_ADDON_H__
+/** \file BKE_addon.h
+ * \ingroup bke
+ */
+
#include "RNA_types.h"
typedef struct bAddonPrefType {
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 539c5780cd5..7de7a745ed6 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -59,7 +59,7 @@ void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets);
/* Curve Paths */
void free_path(struct Path *path);
-void calc_curvepath(struct Object *ob);
+void calc_curvepath(struct Object *ob, struct ListBase *nurbs);
int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius, float *weight);
/* ---------------------------------------------------- */
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index dd150ba6a63..f0f6b5a2319 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -112,6 +112,9 @@ void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, st
/* Fix all the paths for the entire database... */
void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const char *oldName, const char *newName);
+/* Fix the path after removing elements that are not ID (e.g., node) */
+void BKE_animdata_fix_paths_remove(struct ID *id, const char *path);
+
/* -------------------------------------- */
/* Move animation data from src to destination if it's paths are based on basepaths */
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index fb9e9f4e691..60e03af5077 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -124,16 +124,18 @@ void BKE_pchan_to_pose_mat(struct bPoseChannel *pchan, float rotscale_mat[4][4],
void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode);
/* B-Bone support */
+#define MAX_BBONE_SUBDIV 32
+
typedef struct Mat4 {
float mat[4][4];
} Mat4;
-Mat4 *b_bone_spline_setup(struct bPoseChannel *pchan, int rest);
+void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]);
/* like EBONE_VISIBLE */
#define PBONE_VISIBLE(arm, bone) ( \
- CHECK_TYPE_INLINE(arm, bArmature), \
- CHECK_TYPE_INLINE(bone, Bone), \
+ CHECK_TYPE_INLINE(arm, bArmature *), \
+ CHECK_TYPE_INLINE(bone, Bone *), \
(((bone)->layer & (arm)->layer) && !((bone)->flag & BONE_HIDDEN_P)) \
)
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 84e24df43e5..5b32e7229d5 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,15 +41,15 @@ extern "C" {
/* these lines are grep'd, watch out for our not-so-awesome regex
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
-#define BLENDER_VERSION 268
-#define BLENDER_SUBVERSION 2
+#define BLENDER_VERSION 269
+#define BLENDER_SUBVERSION 1
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
#define BLENDER_MINSUBVERSION 0
/* used by packaging tools */
/* can be left blank, otherwise a,b,c... etc with no quotes */
-#define BLENDER_VERSION_CHAR a
+#define BLENDER_VERSION_CHAR
/* alpha/beta/rc/release, docs use this */
#define BLENDER_VERSION_CYCLE alpha
@@ -69,8 +69,10 @@ int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *r
#define BKE_READ_FILE_OK 1 /* OK */
#define BKE_READ_FILE_OK_USERPREFS 2 /* OK, and with new user settings */
-int BKE_read_file_from_memory(struct bContext *C, const void *filebuf, int filelength, struct ReportList *reports);
-int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile, struct ReportList *reports);
+int BKE_read_file_from_memory(struct bContext *C, const void *filebuf,
+ int filelength, struct ReportList *reports, int update_defaults);
+int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile,
+ struct ReportList *reports);
int BKE_read_file_userdef(const char *filepath, struct ReportList *reports);
int BKE_write_file_userdef(const char *filepath, struct ReportList *reports);
@@ -100,11 +102,11 @@ extern const char *BKE_undo_get_name(int nr, int *active);
extern int BKE_undo_save_file(const char *filename);
extern struct Main *BKE_undo_get_main(struct Scene **scene);
- /* copybuffer */
+/* copybuffer */
void BKE_copybuffer_begin(void);
void BKE_copybuffer_tag_ID(struct ID *id);
int BKE_copybuffer_save(const char *filename, struct ReportList *reports);
- int BKE_copybuffer_paste(struct bContext *C, const char *libname, struct ReportList *reports);
+int BKE_copybuffer_paste(struct bContext *C, const char *libname, struct ReportList *reports);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index edf710ef7c9..b4c5f47cf25 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -76,10 +76,10 @@ float BKE_brush_sample_masktex(const Scene *scene, struct Brush *br, const float
const int thread, struct ImagePool *pool);
/* texture */
-unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side);
+unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool use_secondary);
/* radial control */
-struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br);
+struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondary);
/* unified strength and size */
diff --git a/source/blender/blenkernel/BKE_ccg.h b/source/blender/blenkernel/BKE_ccg.h
index fb6211504ae..7d5d423282d 100644
--- a/source/blender/blenkernel/BKE_ccg.h
+++ b/source/blender/blenkernel/BKE_ccg.h
@@ -28,6 +28,10 @@
#ifndef __BKE_CCG_H__
#define __BKE_CCG_H__
+/** \file BKE_ccg.h
+ * \ingroup bke
+ */
+
/* defines BLI_INLINE */
#include "BLI_utildefines.h"
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 947e680d119..1b61d0a5443 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -80,7 +80,7 @@ typedef struct Cloth {
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */
- struct EdgeHash *edgehash; /* used for selfcollisions */
+ struct EdgeHash *edgehash; /* used for selfcollisions (currently used as a 'set', value is ignored) */
int last_frame, pad4;
} Cloth;
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index baa90e7a856..07116979eab 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -42,6 +42,13 @@ struct Main;
struct Nurb;
struct Object;
struct Scene;
+struct Path;
+
+typedef struct CurveCache {
+ ListBase disp;
+ ListBase bev;
+ struct Path *path;
+} CurveCache;
#define KNOTSU(nu) ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
#define KNOTSV(nu) ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
@@ -63,7 +70,11 @@ void BKE_curve_make_local(struct Curve *cu);
short BKE_curve_type_get(struct Curve *cu);
void BKE_curve_type_test(struct Object *ob);
void BKE_curve_curve_dimension_update(struct Curve *cu);
+
+void BKE_curve_boundbox_calc(struct Curve *cu, float r_loc[3], float r_size[3]);
+struct BoundBox *BKE_curve_boundbox_get(struct Object *ob);
void BKE_curve_texspace_calc(struct Curve *cu);
+void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], float r_size[3]);
bool BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]);
bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
@@ -74,11 +85,11 @@ void BKE_curve_material_index_clear(struct Curve *cu);
ListBase *BKE_curve_nurbs_get(struct Curve *cu);
-float (*BKE_curve_vertexCos_get(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3];
-void BK_curve_vertexCos_apply(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]);
+float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *numVerts_r))[3];
+void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
-float (*BKE_curve_keyVertexCos_get(struct Curve *cu, struct ListBase *lb, float *key))[3];
-void BKE_curve_keyVertexTilts_apply(struct Curve *cu, struct ListBase *lb, float *key);
+float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
+void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
void BKE_curve_editNurb_keyIndex_free(struct EditNurb *editnurb);
void BKE_curve_editNurb_free(struct Curve *cu);
@@ -87,7 +98,7 @@ struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts);
float *BKE_curve_surf_make_orco(struct Object *ob);
-void BKE_curve_bevelList_make(struct Object *ob);
+void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBase *disp, int forRender, int renderResolution);
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
@@ -104,6 +115,7 @@ void BKE_nurbList_duplicate(struct ListBase *lb1, struct ListBase *lb2);
void BKE_nurbList_handles_set(struct ListBase *editnurb, short code);
void BKE_nurbList_handles_autocalc(ListBase *editnurb, int flag);
+void BKE_nurbList_flag_set(ListBase *editnurb, short flag);
void BKE_nurb_free(struct Nurb *nu);
struct Nurb *BKE_nurb_duplicate(struct Nurb *nu);
@@ -139,9 +151,11 @@ void BKE_nurb_bezt_calc_normal(struct Nurb *nu, struct BezTriple *bezt, float r_
void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]);
void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode);
+void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
void BKE_nurb_handles_calc(struct Nurb *nu);
void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
-void BKE_nurb_handles_test(struct Nurb *nu);
+void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle);
+void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles);
#endif /* __BKE_CURVE_H__ */
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 72aae1b2361..5a283922707 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -56,6 +56,7 @@ extern const CustomDataMask CD_MASK_EDITMESH;
extern const CustomDataMask CD_MASK_DERIVEDMESH;
extern const CustomDataMask CD_MASK_BMESH;
extern const CustomDataMask CD_MASK_FACECORNERS;
+extern const CustomDataMask CD_MASK_EVERYTHING;
/* for ORIGINDEX layer type, indicates no original index for this element */
#define ORIGINDEX_NONE -1
@@ -191,6 +192,9 @@ void CustomData_set_only_copy(const struct CustomData *data,
void CustomData_copy_data(const struct CustomData *source,
struct CustomData *dest, int source_index,
int dest_index, int count);
+void CustomData_copy_data_named(const struct CustomData *source,
+ struct CustomData *dest, int source_index,
+ int dest_index, int count);
void CustomData_copy_elements(int type, void *source, void *dest, int count);
void CustomData_bmesh_copy_data(const struct CustomData *source,
struct CustomData *dest, void *src_block,
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 1cf77c68345..2178f860825 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -102,4 +102,6 @@ float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int
/* add Orco layer to the displist object which has got derived mesh and return orco */
float *BKE_displist_make_orco(struct Scene *scene, struct Object *ob, struct DerivedMesh *derivedFinal, int forRender, int renderResolution);
+void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]);
+
#endif
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index edfb501b590..738cd87dc39 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -23,6 +23,10 @@
#ifndef __BKE_EDITMESH_H__
#define __BKE_EDITMESH_H__
+/** \file BKE_editmesh.h
+ * \ingroup bke
+ */
+
#include "BKE_customdata.h"
#include "bmesh.h"
diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index 6750ee1ff3e..7b4ad4284c6 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -44,7 +44,7 @@ typedef struct BMBVHTree BMBVHTree;
BMBVHTree *BKE_bmbvh_new(struct BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free);
void BKE_bmbvh_free(BMBVHTree *tree);
struct BVHTree *BKE_bmbvh_tree_get(BMBVHTree *tree);
-struct BMFace *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3],
+struct BMFace *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
float *r_dist, float r_hitout[3], float r_cagehit[3]);
/* find a face intersecting a segment (but not apart of the segment) */
struct BMFace *BKE_bmbvh_find_face_segment(BMBVHTree *tree, const float co_a[3], const float co_b[3],
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 64a6811bf51..c31dd745911 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -229,12 +229,13 @@ short calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ym
short fcurve_are_keyframes_usable(struct FCurve *fcu);
/* Can keyframes be added to F-Curve? */
-short fcurve_is_keyframable(struct FCurve *fcu);
+bool fcurve_is_keyframable(struct FCurve *fcu);
+bool BKE_fcurve_is_protected(struct FCurve *fcu);
/* -------- Curve Sanity -------- */
void calchandles_fcurve(struct FCurve *fcu);
-void testhandles_fcurve(struct FCurve *fcu, const short use_handle);
+void testhandles_fcurve(struct FCurve *fcu, const bool use_handle);
void sort_time_fcurve(struct FCurve *fcu);
short test_time_fcurve(struct FCurve *fcu);
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 133a0690dc6..71fd163a8ee 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -30,6 +30,8 @@
#include "DNA_ID.h"
+#include "BLI_compiler_attrs.h"
+
struct IDProperty;
struct ID;
@@ -55,32 +57,14 @@ typedef union IDPropertyTemplate {
/* ----------- Property Array Type ---------- */
-IDProperty *IDP_NewIDPArray(const char *name)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-IDProperty *IDP_CopyIDPArray(IDProperty *array)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+IDProperty *IDP_CopyIDPArray(IDProperty *array) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void IDP_FreeIDPArray(IDProperty *prop);
/* shallow copies item */
-void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item);
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL();
+struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item);
void IDP_ResizeIDPArray(struct IDProperty *prop, int len);
@@ -90,33 +74,11 @@ void IDP_ResizeArray(struct IDProperty *prop, int newlen);
void IDP_FreeArray(struct IDProperty *prop);
/* ---------- String Type ------------ */
-IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) /* maxlen excludes '\0' */
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull (2))) /* 'name' arg */
-#endif
-;
-
-void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen) /* maxlen excludes '\0' */
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-void IDP_ConcatStringC(struct IDProperty *prop, const char *st)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-void IDP_FreeString(struct IDProperty *prop)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2 /* 'name 'arg */); /* maxlen excludes '\0' */
+void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen) ATTR_NONNULL(); /* maxlen excludes '\0' */
+void IDP_ConcatStringC(struct IDProperty *prop, const char *st) ATTR_NONNULL();
+void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) ATTR_NONNULL();
+void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL();
/*-------- ID Type -------*/
void IDP_LinkID(struct IDProperty *prop, ID *id);
@@ -125,107 +87,30 @@ void IDP_UnlinkID(struct IDProperty *prop);
/*-------- Group Functions -------*/
/** Sync values from one group to another, only where they match */
-void IDP_SyncGroupValues(struct IDProperty *dest, struct IDProperty *src)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-
-void IDP_ReplaceGroupInGroup(struct IDProperty *dest, struct IDProperty *src)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-
-void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-
-int IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+void IDP_SyncGroupValues(struct IDProperty *dest, struct IDProperty *src) ATTR_NONNULL();
+void IDP_ReplaceGroupInGroup(struct IDProperty *dest, struct IDProperty *src) ATTR_NONNULL();
+void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
+void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite) ATTR_NONNULL();
+int IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
int IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous,
- struct IDProperty *pnew)
-#ifdef __GNUC__
-__attribute__((nonnull (1, 3))) /* 'group', 'pnew' */
-#endif
-;
-void IDP_RemFromGroup(struct IDProperty *group, struct IDProperty *prop)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+ struct IDProperty *pnew) ATTR_NONNULL(1 /* group */, 3 /* pnew */);
+void IDP_RemFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
-IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, const char *name)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-void *IDP_GetGroupIterator(struct IDProperty *prop)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-#endif
-;
-IDProperty *IDP_GroupIterNext(void *vself)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-void IDP_FreeIterBeforeEnd(void *vself)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *IDP_GetGroupIterator(struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT;
+IDProperty *IDP_GroupIterNext(void *vself) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void IDP_FreeIterBeforeEnd(void *vself) ATTR_NONNULL();
/*-------- Main Functions --------*/
-struct IDProperty *IDP_GetProperties(struct ID *id, int create_if_needed)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-struct IDProperty *IDP_CopyProperty(struct IDProperty *prop)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+struct IDProperty *IDP_GetProperties(struct ID *id, int create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+struct IDProperty *IDP_CopyProperty(struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-#endif
-;
+int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict) ATTR_WARN_UNUSED_RESULT;
-int IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-#endif
-;
+int IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;
-struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void IDP_FreeProperty(struct IDProperty *prop);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index de60d316426..19264feaf48 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -41,6 +41,7 @@ struct Object;
struct Scene;
struct Lattice;
struct Mesh;
+struct WeightsArrayCache;
/* Kernel prototypes */
#ifdef __cplusplus
@@ -73,8 +74,17 @@ struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index);
struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]);
void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *kb_src);
char *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb);
+
// needed for the GE
-void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode);
+typedef struct WeightsArrayCache {
+ int num_defgroup_weights;
+ float **defgroup_weights;
+} WeightsArrayCache;
+
+float **BKE_keyblock_get_per_block_weights(struct Object *ob, struct Key *key, struct WeightsArrayCache *cache);
+void BKE_keyblock_free_per_block_weights(struct Key *key, float **per_keyblock_weights, struct WeightsArrayCache *cache);
+void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb,
+ float **per_keyblock_weights, const int mode);
/* conversion functions */
void BKE_key_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index 205c7c7d1e6..fb2c4da91ea 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -36,13 +36,15 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
struct Lamp;
struct Main;
struct Scene;
-struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) WARN_UNUSED;
-struct Lamp *BKE_lamp_copy(struct Lamp *la) WARN_UNUSED;
-struct Lamp *localize_lamp(struct Lamp *la) WARN_UNUSED;
+struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
+struct Lamp *BKE_lamp_copy(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
+struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
void BKE_lamp_make_local(struct Lamp *la);
void BKE_lamp_free(struct Lamp *la);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 9b29412675b..ba33da7729c 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -49,9 +49,14 @@ void BKE_lattice_free(struct Lattice *lt);
void BKE_lattice_make_local(struct Lattice *lt);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
-void init_latt_deform(struct Object *oblatt, struct Object *ob);
-void calc_latt_deform(struct Object *, float co[3], float weight);
-void end_latt_deform(struct Object *);
+struct LatticeDeformData;
+struct LatticeDeformData *init_latt_deform(struct Object *oblatt, struct Object *ob)
+#ifdef __GNUC__
+__attribute__((warn_unused_result))
+#endif
+;
+void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight);
+void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
int object_deform_mball(struct Object *ob, struct ListBase *dispbase);
void outside_lattice(struct Lattice *lt);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 3c5406c4a77..b8da5002d84 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -36,6 +36,8 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
struct ListBase;
struct ID;
struct Main;
@@ -45,24 +47,9 @@ struct bContext;
struct PointerRNA;
struct PropertyRNA;
-void *BKE_libblock_alloc(struct ListBase *lb, short type, const char *name)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-void *BKE_libblock_copy(struct ID *id)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+void *BKE_libblock_alloc(struct ListBase *lb, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
@@ -99,12 +86,7 @@ void rename_id(struct ID *id, const char *name);
void name_uiprefix_id(char *name, const struct ID *id);
void test_idbutton(char *name);
void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagged_only);
-struct ID *BKE_libblock_find_name(const short type, const char *name)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void clear_id_newpoins(void);
#if 0
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 92332116ba6..9e73e0662ce 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -28,6 +28,10 @@
#ifndef __BKE_MASK_H__
#define __BKE_MASK_H__
+/** \file BKE_mask.h
+ * \ingroup bke
+ */
+
struct ImageUser;
struct Image;
struct ListBase;
@@ -53,9 +57,11 @@ void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay);
void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay);
void BKE_mask_layer_free_shapes(struct MaskLayer *masklay);
+void BKE_mask_layer_free_deform(struct MaskLayer *mask_layer);
void BKE_mask_layer_free(struct MaskLayer *masklay);
void BKE_mask_layer_free_list(struct ListBase *masklayers);
void BKE_mask_spline_free(struct MaskSpline *spline);
+void BKE_mask_spline_free_list(struct ListBase *splines);
struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline);
void BKE_mask_point_free(struct MaskSplinePoint *point);
@@ -134,6 +140,7 @@ void BKE_mask_layer_calc_handles_deform(struct MaskLayer *masklay);
void BKE_mask_calc_handles(struct Mask *mask);
void BKE_mask_update_deform(struct Mask *mask);
void BKE_mask_spline_ensure_deform(struct MaskSpline *spline);
+void BKE_mask_point_parent_matrix_get(struct MaskSplinePoint *point, float ctime, float parent_matrix[3][3]);
/* animation */
int BKE_mask_layer_shape_totvert(struct MaskLayer *masklay);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index f52dc030873..91c1715cca6 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -50,7 +50,7 @@ void init_def_material(void);
void BKE_material_free(struct Material *sc);
void BKE_material_free_ex(struct Material *ma, int do_id_user);
void test_object_materials(struct Main *bmain, struct ID *id);
-void resize_object_material(struct Object *ob, const short totcol);
+void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
void init_material(struct Material *ma);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Material *ma);
@@ -87,6 +87,7 @@ int object_add_material_slot(struct Object *ob);
int object_remove_material_slot(struct Object *ob);
/* rna api */
+void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user);
void BKE_material_append_id(struct ID *id, struct Material *ma);
struct Material *BKE_material_pop_id(struct ID *id, int index, bool update_data); /* index is an int because of RNA */
void BKE_material_clear_id(struct ID *id, bool update_data);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 44459300c56..7665e1b54dc 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -47,7 +47,7 @@ void BKE_mball_make_local(struct MetaBall *mb);
void BKE_mball_cubeTable_free(void);
-void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
+void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, bool for_render);
bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
bool BKE_mball_is_basis(struct Object *ob);
struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index e582af77d61..9e80a93fd63 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -31,8 +31,6 @@
* \ingroup bke
*/
-/***/
-
struct ID;
struct BoundBox;
struct DispList;
@@ -60,108 +58,31 @@ struct UvVertMap;
struct UvMapVert;
struct UvElementMap;
struct UvElement;
+
#ifdef __cplusplus
extern "C" {
#endif
-struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob);
-
-/*
- * this function recreates a tessellation.
- * returns number of tessellation faces.
- *
- * use_poly_origindex sets whether or not the tessellation faces' origindex
- * layer should point to original poly indices or real poly indices.
- *
- * use_face_origindex sets the tessellation faces' origindex layer
- * to point to the tessellation faces themselves, not the polys.
- *
- * if both of the above are 0, it'll use the indices of the mpolys of the MPoly
- * data in pdata, and ignore the origindex layer altogether.
- */
-int BKE_mesh_recalc_tessellation(struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
- struct MVert *mvert,
- int totface, int totloop, int totpoly,
- const bool do_face_normals);
-
-/* for forwards compat only quad->tri polys to mface, skip ngons.
- */
-int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
- struct CustomData *pdata, int totface, int totloop, int totpoly);
-
-/*calculates a face normal.*/
-void BKE_mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray, float no[3]);
-
-void BKE_mesh_calc_poly_normal_coords(struct MPoly *mpoly, struct MLoop *loopstart,
- const float (*vertex_coords)[3], float no[3]);
-
-void BKE_mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray, float cent[3]);
-
-float BKE_mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray, const float polynormal[3]);
-
-void BKE_mesh_calc_poly_angles(struct MPoly *mpoly, struct MLoop *loopstart,
- struct MVert *mvarray, float angles[]);
-
-int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge, const int totedge,
- const struct MPoly *mpoly, const int totpoly,
- const struct MLoop *mloop, const int totloop,
- int *r_totgroup);
+/* setting zero so we can catch bugs in OpenMP/BMesh */
+#ifdef DEBUG
+# define BKE_MESH_OMP_LIMIT 0
+#else
+# define BKE_MESH_OMP_LIMIT 10000
+#endif
-void BKE_mesh_calc_relative_deform(
- const struct MPoly *mpoly, const int totpoly,
- const struct MLoop *mloop, const int totvert,
+/* *** mesh.c *** */
- const float (*vert_cos_src)[3],
- const float (*vert_cos_dst)[3],
-
- const float (*vert_cos_org)[3],
- float (*vert_cos_new)[3]);
+struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob);
-/* Find the index of the loop in 'poly' which references vertex,
- * returns -1 if not found */
int poly_find_loop_from_vert(const struct MPoly *poly,
const struct MLoop *loopstart,
unsigned vert);
-/* Fill 'adj_r' with the loop indices in 'poly' adjacent to the
- * vertex. Returns the index of the loop matching vertex, or -1 if the
- * vertex is not in 'poly' */
int poly_get_adj_loops_from_vert(unsigned adj_r[3], const struct MPoly *poly,
const struct MLoop *mloop, unsigned vert);
-/* Return the index of the edge vert that is not equal to 'v'. If
- * neither edge vertex is equal to 'v', returns -1. */
int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
-/* update the hide flag for edges and polys from the corresponding
- * flag in verts */
-void BKE_mesh_flush_hidden_from_verts_ex(const struct MVert *mvert,
- const struct MLoop *mloop,
- struct MEdge *medge, const int totedge,
- struct MPoly *mpoly, const int totpoly);
-void BKE_mesh_flush_hidden_from_verts(struct Mesh *me);
-
-void BKE_mesh_flush_hidden_from_polys_ex(struct MVert *mvert,
- const struct MLoop *mloop,
- struct MEdge *medge, const int totedge,
- const struct MPoly *mpoly, const int totpoly);
-void BKE_mesh_flush_hidden_from_polys(struct Mesh *me);
-
-
-void BKE_mesh_flush_select_from_polys_ex(struct MVert *mvert, const int totvert,
- const struct MLoop *mloop,
- struct MEdge *medge, const int totedge,
- const struct MPoly *mpoly, const int totpoly);
-void BKE_mesh_flush_select_from_polys(struct Mesh *me);
-void BKE_mesh_flush_select_from_verts_ex(const struct MVert *mvert, const int totvert,
- const struct MLoop *mloop,
- struct MEdge *medge, const int totedge,
- struct MPoly *mpoly, const int totpoly);
-void BKE_mesh_flush_select_from_verts(struct Mesh *me);
-
void BKE_mesh_unlink(struct Mesh *me);
void BKE_mesh_free(struct Mesh *me, int unlink);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
@@ -191,64 +112,99 @@ void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
void BKE_mesh_material_index_remove(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
-void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
-void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
-void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id,
- struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
- int totedge_i, int totface_i, int totloop_i, int totpoly_i,
- struct MEdge *medge, struct MFace *mface,
- int *totloop_r, int *totpoly_r,
- struct MLoop **mloop_r, struct MPoly **mpoly_r);
-
-void BKE_mesh_calc_normals_tessface(struct MVert *mverts, int numVerts, struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]);
-
-/* used for unit testing; compares two meshes, checking only
- * differences we care about. should be usable with leaf's
- * testing framework I get RNA work done, will use hackish
- * testing code for now.*/
+
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
struct BoundBox *BKE_mesh_boundbox_get(struct Object *ob);
void BKE_mesh_texspace_get(struct Mesh *me, float r_loc[3], float r_rot[3], float r_size[3]);
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
-/* if old, it converts mface->edcode to edge drawflags */
-void BKE_mesh_make_edges(struct Mesh *me, const bool use_old);
+bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, const int poly_index, const int loop_index, const int face_index,
+ const char *new_name, const bool do_tessface);
+bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const char *new_name, bool do_tessface);
-void BKE_mesh_strip_loose_faces(struct Mesh *me); /* Needed for compatibility (some old read code). */
-void BKE_mesh_strip_loose_polysloops(struct Mesh *me);
-void BKE_mesh_strip_loose_edges(struct Mesh *me);
+float (*BKE_mesh_vertexCos_get(struct Mesh *me, int *r_numVerts))[3];
+
+/* vertex level transformations & checks (no derived mesh) */
+
+bool BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]);
+void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys);
+
+void BKE_mesh_ensure_navmesh(struct Mesh *me);
+
+void BKE_mesh_tessface_calc(struct Mesh *mesh);
+void BKE_mesh_tessface_ensure(struct Mesh *mesh);
+void BKE_mesh_tessface_clear(struct Mesh *mesh);
+
+void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);
+
+
+void BKE_mesh_mselect_clear(struct Mesh *me);
+void BKE_mesh_mselect_validate(struct Mesh *me);
+int BKE_mesh_mselect_find(struct Mesh *me, int index, int type);
+int BKE_mesh_mselect_active_get(struct Mesh *me, int type);
+void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
+
+
+
+/* *** mesh_evaluate.c *** */
-/* Calculate vertex and face normals, face normals are returned in *faceNors_r if non-NULL
- * and vertex normals are stored in actual mverts.
- */
void BKE_mesh_calc_normals_mapping(
struct MVert *mverts, int numVerts,
struct MLoop *mloop, struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3]);
-/* extended version of 'BKE_mesh_calc_normals_poly' with option not to calc vertex normals */
void BKE_mesh_calc_normals_mapping_ex(
struct MVert *mverts, int numVerts,
struct MLoop *mloop, struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3],
const bool only_face_normals);
-
void BKE_mesh_calc_normals_poly(
struct MVert *mverts, int numVerts,
struct MLoop *mloop, struct MPoly *mpolys,
int numLoops, int numPolys, float (*polyNors_r)[3],
const bool only_face_normals);
-
void BKE_mesh_calc_normals(struct Mesh *me);
+void BKE_mesh_calc_normals_tessface(
+ struct MVert *mverts, int numVerts,
+ struct MFace *mfaces, int numFaces,
+ float (*faceNors_r)[3]);
+void BKE_mesh_normals_loop_split(
+ struct MVert *mverts, int numVerts, struct MEdge *medges, int numEdges,
+ struct MLoop *mloops, float (*r_loopnors)[3], int numLoops,
+ struct MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle);
+
+void BKE_mesh_calc_poly_normal(
+ struct MPoly *mpoly, struct MLoop *loopstart,
+ struct MVert *mvarray, float no[3]);
+void BKE_mesh_calc_poly_normal_coords(
+ struct MPoly *mpoly, struct MLoop *loopstart,
+ const float (*vertex_coords)[3], float no[3]);
+void BKE_mesh_calc_poly_center(
+ struct MPoly *mpoly, struct MLoop *loopstart,
+ struct MVert *mvarray, float cent[3]);
+float BKE_mesh_calc_poly_area(
+ struct MPoly *mpoly, struct MLoop *loopstart,
+ struct MVert *mvarray, const float polynormal[3]);
+void BKE_mesh_calc_poly_angles(
+ struct MPoly *mpoly, struct MLoop *loopstart,
+ struct MVert *mvarray, float angles[]);
+
+void BKE_mesh_poly_edgehash_insert(
+ struct EdgeHash *ehash,
+ const struct MPoly *mp, const struct MLoop *mloop);
+void BKE_mesh_poly_edgebitmap_insert(
+ unsigned int *edge_bitmap,
+ const struct MPoly *mp, const struct MLoop *mloop);
+
+
+bool BKE_mesh_center_median(struct Mesh *me, float cent[3]);
+bool BKE_mesh_center_bounds(struct Mesh *me, float cent[3]);
+bool BKE_mesh_center_centroid(struct Mesh *me, float cent[3]);
-/* Return a newly MEM_malloc'd array of all the mesh vertex locations
- * (_numVerts_r_ may be NULL) */
-float (*BKE_mesh_vertexCos_get(struct Mesh *me, int *r_numVerts))[3];
/* map from uv vertex to face (for select linked, stitch, uv suburf) */
/* UvVertMap */
-
#define STD_UV_CONNECT_LIMIT 0.0001f
typedef struct UvVertMap {
@@ -302,46 +258,109 @@ typedef struct UvElementMap {
* to make that many islands, he can bite me :p */
#define INVALID_ISLAND 0xFFFF
-UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
- unsigned int totpoly, unsigned int totvert, int selected, float *limit);
-UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
-void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
-
/* Connectivity data */
typedef struct MeshElemMap {
int *indices;
int count;
} MeshElemMap;
-
-typedef struct IndexNode {
- struct IndexNode *next, *prev;
- int index;
-} IndexNode;
-void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
- const struct MPoly *mface, const struct MLoop *mloop,
- int totvert, int totface, int totloop);
+/* mapping */
+UvVertMap *BKE_mesh_uv_vert_map_create(
+ struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
+ unsigned int totpoly, unsigned int totvert, int selected, float *limit);
+UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
+void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
-void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
- const struct MEdge *medge, int totvert, int totedge);
+void BKE_mesh_vert_poly_map_create(
+ MeshElemMap **r_map, int **r_mem,
+ const struct MPoly *mface, const struct MLoop *mloop,
+ int totvert, int totface, int totloop);
+void BKE_mesh_vert_edge_map_create(
+ MeshElemMap **r_map, int **r_mem,
+ const struct MEdge *medge, int totvert, int totedge);
+void BKE_mesh_edge_poly_map_create(
+ MeshElemMap **r_map, int **r_mem,
+ const struct MEdge *medge, const int totedge,
+ const struct MPoly *mpoly, const int totpoly,
+ const struct MLoop *mloop, const int totloop);
+
+/* tessface */
+void BKE_mesh_loops_to_mface_corners(
+ struct CustomData *fdata, struct CustomData *ldata,
+ struct CustomData *pdata, int lindex[4], int findex,
+ const int polyindex, const int mf_len,
+ const int numTex, const int numCol,
+ const bool hasPCol, const bool hasOrigSpace);
+int BKE_mesh_recalc_tessellation(
+ struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
+ struct MVert *mvert,
+ int totface, int totloop, int totpoly,
+ const bool do_face_normals);
+int BKE_mesh_mpoly_to_mface(
+ struct CustomData *fdata, struct CustomData *ldata,
+ struct CustomData *pdata, int totface, int totloop, int totpoly);
+void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
+void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
+void BKE_mesh_convert_mfaces_to_mpolys_ex(
+ struct ID *id,
+ struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
+ int totedge_i, int totface_i, int totloop_i, int totpoly_i,
+ struct MEdge *medge, struct MFace *mface,
+ int *totloop_r, int *totpoly_r,
+ struct MLoop **mloop_r, struct MPoly **mpoly_r);
+
+/* flush flags */
+void BKE_mesh_flush_hidden_from_verts_ex(
+ const struct MVert *mvert,
+ const struct MLoop *mloop,
+ struct MEdge *medge, const int totedge,
+ struct MPoly *mpoly, const int totpoly);
+void BKE_mesh_flush_hidden_from_verts(struct Mesh *me);
+void BKE_mesh_flush_hidden_from_polys_ex(
+ struct MVert *mvert,
+ const struct MLoop *mloop,
+ struct MEdge *medge, const int totedge,
+ const struct MPoly *mpoly, const int totpoly);
+void BKE_mesh_flush_hidden_from_polys(struct Mesh *me);
+void BKE_mesh_flush_select_from_polys_ex(
+ struct MVert *mvert, const int totvert,
+ const struct MLoop *mloop,
+ struct MEdge *medge, const int totedge,
+ const struct MPoly *mpoly, const int totpoly);
+void BKE_mesh_flush_select_from_polys(struct Mesh *me);
+void BKE_mesh_flush_select_from_verts_ex(
+ const struct MVert *mvert, const int totvert,
+ const struct MLoop *mloop,
+ struct MEdge *medge, const int totedge,
+ struct MPoly *mpoly, const int totpoly);
+void BKE_mesh_flush_select_from_verts(struct Mesh *me);
-void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem,
- const struct MEdge *medge, const int totedge,
- const struct MPoly *mpoly, const int totpoly,
- const struct MLoop *mloop, const int totloop);
+/* smoothgroups */
+int *BKE_mesh_calc_smoothgroups(
+ const struct MEdge *medge, const int totedge,
+ const struct MPoly *mpoly, const int totpoly,
+ const struct MLoop *mloop, const int totloop,
+ int *r_totgroup, const bool use_bitflags);
-/* vertex level transformations & checks (no derived mesh) */
+/* spatial evaluation */
+void BKE_mesh_calc_relative_deform(
+ const struct MPoly *mpoly, const int totpoly,
+ const struct MLoop *mloop, const int totvert,
-int BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]);
-int BKE_mesh_center_median(struct Mesh *me, float cent[3]);
-int BKE_mesh_center_bounds(struct Mesh *me, float cent[3]);
-int BKE_mesh_center_centroid(struct Mesh *me, float cent[3]);
-void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys);
+ const float (*vert_cos_src)[3],
+ const float (*vert_cos_dst)[3],
+
+ const float (*vert_cos_org)[3],
+ float (*vert_cos_new)[3]);
-/* mesh_validate.c */
-/* XXX Loop v/e are unsigned, so using max uint_32 value as invalid marker... */
-#define INVALID_LOOP_EDGE_MARKER 4294967295u
-int BKE_mesh_validate_arrays(
+
+
+/* *** mesh_validate.c *** */
+
+int BKE_mesh_validate(struct Mesh *me, const int do_verbose);
+void BKE_mesh_cd_validate(struct Mesh *me);
+
+bool BKE_mesh_validate_arrays(
struct Mesh *me,
struct MVert *mverts, unsigned int totvert,
struct MEdge *medges, unsigned int totedge,
@@ -349,35 +368,22 @@ int BKE_mesh_validate_arrays(
struct MLoop *mloops, unsigned int totloop,
struct MPoly *mpolys, unsigned int totpoly,
struct MDeformVert *dverts, /* assume totvert length */
- const bool do_verbose, const bool do_fixes);
-int BKE_mesh_validate(struct Mesh *me, const int do_verbose);
-int BKE_mesh_validate_dm(struct DerivedMesh *dm);
+ const bool do_verbose, const bool do_fixes,
+ bool *r_change);
-void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
-
-void BKE_mesh_ensure_navmesh(struct Mesh *me);
-
-void BKE_mesh_tessface_calc(struct Mesh *mesh);
-void BKE_mesh_tessface_ensure(struct Mesh *mesh);
-void BKE_mesh_tessface_clear(struct Mesh *mesh);
-
-/* Convert a triangle or quadrangle of loop/poly data to tessface data */
-void BKE_mesh_loops_to_mface_corners(struct CustomData *fdata, struct CustomData *ldata,
- struct CustomData *pdata, int lindex[4], int findex,
- const int polyindex, const int mf_len,
- const int numTex, const int numCol, const int hasPCol, const int hasOrigSpace);
-
-void BKE_mesh_poly_edgehash_insert(struct EdgeHash *ehash, const struct MPoly *mp, const struct MLoop *mloop);
-void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap, const struct MPoly *mp, const struct MLoop *mloop);
-
-void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);
+bool BKE_mesh_validate_all_customdata(
+ struct CustomData *vdata, struct CustomData *edata,
+ struct CustomData *ldata, struct CustomData *pdata,
+ const bool check_meshmask,
+ const bool do_verbose, const bool do_fixes,
+ bool *r_change);
+void BKE_mesh_strip_loose_faces(struct Mesh *me);
+void BKE_mesh_strip_loose_polysloops(struct Mesh *me);
+void BKE_mesh_strip_loose_edges(struct Mesh *me);
-void BKE_mesh_mselect_clear(struct Mesh *me);
-void BKE_mesh_mselect_validate(struct Mesh *me);
-int BKE_mesh_mselect_find(struct Mesh *me, int index, int type);
-int BKE_mesh_mselect_active_get(struct Mesh *me, int type);
-void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
+void BKE_mesh_calc_edges_legacy(struct Mesh *me, const bool use_old);
+void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 0727e11f397..6bf42a3e885 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -29,6 +29,7 @@
*/
#include "DNA_modifier_types.h" /* needed for all enum typdefs */
+#include "BLI_compiler_attrs.h"
#include "BKE_customdata.h"
struct ID;
@@ -304,6 +305,9 @@ typedef struct ModifierTypeInfo {
TexWalkFunc walk, void *userData);
} ModifierTypeInfo;
+/* Initialize modifier's global data (type info and some common global storages). */
+void BKE_modifier_init(void);
+
ModifierTypeInfo *modifierType_getInfo(ModifierType type);
/* Modifier utility calls, do call through type pointer and return
@@ -322,11 +326,7 @@ bool modifier_isCorrectableDeformed(struct ModifierData *md);
bool modifier_isSameTopology(ModifierData *md);
bool modifier_isNonGeometrical(ModifierData *md);
bool modifier_isEnabled(struct Scene *scene, struct ModifierData *md, int required_mode);
-void modifier_setError(struct ModifierData *md, const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
-;
+void modifier_setError(struct ModifierData *md, const char *format, ...) ATTR_PRINTF_FORMAT(2, 3);
bool modifier_isPreview(struct ModifierData *md);
void modifiers_foreachObjectLink(struct Object *ob,
@@ -354,7 +354,7 @@ struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
struct Object *modifiers_isDeformedByCurve(struct Object *ob);
bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
-bool modifiers_isCorrectableDeformed(struct Object *ob);
+bool modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob);
void modifier_freeTemporaryData(struct ModifierData *md);
bool modifiers_isPreview(struct Object *ob);
@@ -377,7 +377,15 @@ struct CDMaskLink *modifiers_calcDataMasks(struct Scene *scene,
struct ModifierData *modifiers_getLastPreview(struct Scene *scene,
struct ModifierData *md,
int required_mode);
-struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob);
+
+typedef struct VirtualModifierData {
+ ArmatureModifierData amd;
+ CurveModifierData cmd;
+ LatticeModifierData lmd;
+ ShapeKeyModifierData smd;
+} VirtualModifierData;
+
+struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob, struct VirtualModifierData *data);
/* ensure modifier correctness when changing ob->data */
void test_object_modifiers(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_navmesh_conversion.h b/source/blender/blenkernel/BKE_navmesh_conversion.h
index cc9c18c764d..3be363f4d7b 100644
--- a/source/blender/blenkernel/BKE_navmesh_conversion.h
+++ b/source/blender/blenkernel/BKE_navmesh_conversion.h
@@ -28,6 +28,10 @@
#ifndef __BKE_NAVMESH_CONVERSION_H__
#define __BKE_NAVMESH_CONVERSION_H__
+/** \file BKE_navmesh_conversion.h
+ * \ingroup bke
+ */
+
struct DerivedMesh;
/* navmesh_conversion.c */
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 4e9e18d43e3..7f19a867093 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -32,8 +32,8 @@
* \ingroup bke
*/
-#include "BLI_ghash.h"
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "DNA_listBase.h"
@@ -337,7 +337,7 @@ struct GHashIterator *ntreeTypeGetIterator(void);
#define NODE_TREE_TYPES_END \
} \
BLI_ghashIterator_free(__node_tree_type_iter__); \
-}
+} (void)0
void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
@@ -746,6 +746,7 @@ struct ShadeResult;
#define SH_NODE_VECT_TRANSFORM 182
#define SH_NODE_SEPHSV 183
#define SH_NODE_COMBHSV 184
+#define SH_NODE_BSDF_HAIR 185
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
@@ -898,6 +899,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define CMP_NODE_PIXELATE 318
#define CMP_NODE_MAP_RANGE 319
+#define CMP_NODE_PLANETRACKDEFORM 320
/* channel toggles */
#define CMP_CHAN_RGB 1
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 992792dcb99..e99eb2a64f2 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -60,6 +60,7 @@ void BKE_object_copy_softbody(struct Object *obn, struct Object *ob);
void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_bulletsoftbody(struct Object *ob);
+void BKE_object_free_curve_cache(struct Object *ob);
void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
void BKE_object_free(struct Object *ob);
@@ -169,7 +170,7 @@ int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob);
void BKE_object_relink(struct Object *ob);
-struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, int use_default);
+struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default);
/* this function returns a superset of the scenes selection based on relationships */
@@ -193,6 +194,8 @@ struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet
struct LinkNode *BKE_object_groups(struct Object *ob);
void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
+struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h
index b733204e078..b750d8b283a 100644
--- a/source/blender/blenkernel/BKE_ocean.h
+++ b/source/blender/blenkernel/BKE_ocean.h
@@ -23,6 +23,10 @@
#ifndef __BKE_OCEAN_H__
#define __BKE_OCEAN_H__
+/** \file BKE_ocean.h
+ * \ingroup bli
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 2baa8b78e47..1d81dfefe65 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -173,5 +173,4 @@ void free_sculptsession(struct Object *ob);
void free_sculptsession_deformMats(struct SculptSession *ss);
void sculptsession_bm_to_me(struct Object *ob, int reorder);
void sculptsession_bm_to_me_for_render(struct Object *object);
-
#endif
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 56b550a6f5d..d4965cf55fe 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -54,6 +54,7 @@ struct MCol;
struct MFace;
struct MVert;
struct IpoCurve;
+struct LatticeDeformData;
struct LinkNode;
struct KDTree;
struct RNG;
@@ -258,7 +259,7 @@ void psys_set_current_num(Object *ob, int index);
/* UNUSED */
// struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
-struct Object *psys_get_lattice(struct ParticleSimulationData *sim);
+struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 7d3d8d7dcbd..9e21831dba0 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -172,8 +172,8 @@ int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
/* test if AABB is at least partially outside the planes' volume */
int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
-struct GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
-struct GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
+struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
+struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node);
void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
@@ -235,9 +235,10 @@ typedef struct PBVHVertexIter {
float *vmask;
/* bmesh */
- struct GHashIterator bm_unique_verts;
- struct GHashIterator bm_other_verts;
+ struct GSetIterator bm_unique_verts;
+ struct GSetIterator bm_other_verts;
struct CustomData *bm_vdata;
+ int cd_vert_mask_offset;
/* result: these are all computed in the macro, but we assume
* that compiler optimization's will skip the ones we don't use */
@@ -294,22 +295,20 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \
} \
else { \
- if (!BLI_ghashIterator_done(&vi.bm_unique_verts)) {\
- vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_unique_verts); \
- BLI_ghashIterator_step(&vi.bm_unique_verts); \
+ if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) {\
+ vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_unique_verts); \
+ BLI_gsetIterator_step(&vi.bm_unique_verts); \
} \
else { \
- vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_other_verts); \
- BLI_ghashIterator_step(&vi.bm_other_verts); \
+ vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_other_verts); \
+ BLI_gsetIterator_step(&vi.bm_other_verts); \
} \
if (mode == PBVH_ITER_UNIQUE && \
BM_elem_flag_test(vi.bm_vert, BM_ELEM_HIDDEN)) \
continue; \
vi.co = vi.bm_vert->co; \
vi.fno = vi.bm_vert->no; \
- vi.mask = CustomData_bmesh_get(vi.bm_vdata, \
- vi.bm_vert->head.data, \
- CD_PAINT_MASK); \
+ vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \
}
#define BKE_pbvh_vertex_iter_end \
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 1cb50425c40..d5131fcd19e 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -156,6 +156,8 @@ typedef struct PTCacheID {
/* total number of simulated points (the cfra parameter is just for using same function pointer with totwrite) */
int (*totpoint)(void *calldata, int cfra);
+ /* report error if number of points does not match */
+ void (*error)(void *calldata, const char *message);
/* number of points written for current cache frame */
int (*totwrite)(void *calldata, int cfra);
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index ae457cf4f47..101fc463375 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -34,6 +34,7 @@ extern "C" {
#include <stdio.h>
#include "DNA_windowmanager_types.h"
+#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
/* Reporting Information and Errors
@@ -47,18 +48,10 @@ void BKE_reports_init(ReportList *reports, int flag);
void BKE_reports_clear(ReportList *reports);
void BKE_report(ReportList *reports, ReportType type, const char *message);
-void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 3, 4)))
-#endif
-;
+void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4);
void BKE_reports_prepend(ReportList *reports, const char *prepend);
-void BKE_reports_prependf(ReportList *reports, const char *prepend, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
-;
+void BKE_reports_prependf(ReportList *reports, const char *prepend, ...) ATTR_PRINTF_FORMAT(2, 3);
ReportType BKE_report_print_level(ReportList *reports);
void BKE_report_print_level_set(ReportList *reports, ReportType level);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index c883bdf74e0..3c0928d38a0 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -189,9 +189,15 @@ typedef struct PanelType {
/* uilist types */
-/* draw an item in the uiList */
+/* Draw an item in the uiList */
typedef void (*uiListDrawItemFunc)(struct uiList *, struct bContext *, struct uiLayout *, struct PointerRNA *,
- struct PointerRNA *, int, struct PointerRNA *, const char *, int);
+ struct PointerRNA *, int, struct PointerRNA *, const char *, int, int);
+
+/* Draw the filtering part of an uiList */
+typedef void (*uiListDrawFilterFunc)(struct uiList *, struct bContext *, struct uiLayout *);
+
+/* Filter items of an uiList */
+typedef void (*uiListFilterItemsFunc)(struct uiList *, struct bContext *, struct PointerRNA *, const char *);
typedef struct uiListType {
struct uiListType *next, *prev;
@@ -199,6 +205,8 @@ typedef struct uiListType {
char idname[BKE_ST_MAXNAME]; /* unique name */
uiListDrawItemFunc draw_item;
+ uiListDrawFilterFunc draw_filter;
+ uiListFilterItemsFunc filter_items;
/* RNA integration */
ExtensionRNA ext;
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 78018f04458..12b6d18ab7c 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -194,6 +194,7 @@ void BKE_sequencer_editing_free(struct Scene *scene);
void BKE_sequencer_sort(struct Scene *scene);
+struct Sequence *BKE_sequencer_from_elem(ListBase *seqbase, struct StripElem *se);
struct Sequence *BKE_sequencer_active_get(struct Scene *scene);
int BKE_sequencer_active_get_pair(struct Scene *scene, struct Sequence **seq_act, struct Sequence **seq_other);
void BKE_sequencer_active_set(struct Scene *scene, struct Sequence *seq);
@@ -318,6 +319,8 @@ void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq
void BKE_sequencer_update_muting(struct Editing *ed);
void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound);
+void BKE_sequencer_refresh_sound_length(struct Scene *scene);
+
void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq);
void BKE_sequence_base_dupli_recursive(struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag);
bool BKE_sequence_is_valid_check(struct Sequence *seq);
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 61d82e6c604..323a926863c 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -134,9 +134,9 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object
* Thus it provides an easy way to cast the same ray across several trees
* (where each tree was built on its own coords space)
*/
-int normal_projection_project_vertex(char options, const float vert[3], const float dir[3],
- const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
- BVHTree_RayCastCallback callback, void *userdata);
+int BKE_shrinkwrap_project_normal(char options, const float vert[3], const float dir[3],
+ const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
+ BVHTree_RayCastCallback callback, void *userdata);
/*
* NULL initializers to local data
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index 653f2a42675..ab8b8b29915 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -72,11 +72,11 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
void subsurf_calculate_limit_positions(struct Mesh *me, float (*positions_r)[3]);
/* get gridsize from 'level', level must be greater than zero */
-int ccg_gridsize(int level);
+int BKE_ccg_gridsize(int level);
/* x/y grid coordinates at 'low_level' can be multiplied by the result
* of this function to convert to grid coordinates at 'high_level' */
-int ccg_factor(int low_level, int high_level);
+int BKE_ccg_factor(int low_level, int high_level);
void subsurf_copy_grid_hidden(struct DerivedMesh *dm,
const struct MPoly *mpoly,
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 24fd763d078..bba209334d4 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -58,7 +58,7 @@ void BKE_text_write (struct Text *text, const char *str);
char *txt_to_buf (struct Text *text);
void txt_clean_text (struct Text *text);
-void txt_order_cursors (struct Text *text);
+void txt_order_cursors (struct Text *text, const bool reverse);
int txt_find_string (struct Text *text, const char *findstr, int wrap, int match_case);
int txt_has_sel (struct Text *text);
int txt_get_span (struct TextLine *from, struct TextLine *to);
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index ac0d507003e..2a00dee2a3f 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -101,8 +101,8 @@ void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex
int has_current_material_texture(struct Material *ma);
-struct TexMapping *add_tex_mapping(void);
-void default_tex_mapping(struct TexMapping *texmap);
+struct TexMapping *add_tex_mapping(int type);
+void default_tex_mapping(struct TexMapping *texmap, int type);
void init_tex_mapping(struct TexMapping *texmap);
struct ColorMapping *add_color_mapping(void);
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 84bca0bd3ba..51f97180ddb 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -38,6 +38,8 @@ struct ListBase;
struct MovieReconstructContext;
struct MovieTrackingTrack;
struct MovieTrackingMarker;
+struct MovieTrackingPlaneTrack;
+struct MovieTrackingPlaneMarker;
struct MovieTracking;
struct MovieTrackingContext;
struct MovieTrackingObject;
@@ -55,6 +57,7 @@ void BKE_tracking_free(struct MovieTracking *tracking);
void BKE_tracking_settings_init(struct MovieTracking *tracking);
struct ListBase *BKE_tracking_get_active_tracks(struct MovieTracking *tracking);
+struct ListBase *BKE_tracking_get_active_plane_tracks(struct MovieTracking *tracking);
struct MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(struct MovieTracking *tracking);
/* matrices for constraints and drawing */
@@ -65,7 +68,7 @@ void BKE_tracking_get_projection_matrix(struct MovieTracking *tracking, struct M
/* **** Clipboard **** */
void BKE_tracking_clipboard_free(void);
void BKE_tracking_clipboard_copy_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
-int BKE_tracking_clipboard_has_tracks(void);
+bool BKE_tracking_clipboard_has_tracks(void);
void BKE_tracking_clipboard_paste_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
/* **** Track **** */
@@ -77,8 +80,8 @@ void BKE_tracking_track_free(struct MovieTrackingTrack *track);
void BKE_tracking_track_flag_set(struct MovieTrackingTrack *track, int area, int flag);
void BKE_tracking_track_flag_clear(struct MovieTrackingTrack *track, int area, int flag);
-int BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr);
-int BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr);
+bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr);
+bool BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr);
void BKE_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action);
void BKE_tracking_tracks_join(struct MovieTracking *tracking, struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track);
@@ -95,8 +98,9 @@ float *BKE_tracking_track_get_mask(int frame_width, int frame_height, struct Mov
struct MovieTrackingMarker *marker);
/* selection */
-void BKE_tracking_track_select(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend);
+void BKE_tracking_track_select(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, bool extend);
void BKE_tracking_track_deselect(struct MovieTrackingTrack *track, int area);
+void BKE_tracking_tracks_deselect_all(struct ListBase *tracksbase);
/* **** Marker **** */
struct MovieTrackingMarker *BKE_tracking_marker_insert(struct MovieTrackingTrack *track,
@@ -113,9 +117,35 @@ void BKE_tracking_marker_pattern_minmax(const struct MovieTrackingMarker *marker
void BKE_tracking_marker_get_subframe_position(struct MovieTrackingTrack *track, float framenr, float pos[2]);
+/* **** Plane Track **** */
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(struct MovieTracking *tracking, struct ListBase *plane_tracks_base,
+ struct ListBase *tracks, int framenr);
+void BKE_tracking_plane_track_unique_name(struct ListBase *plane_tracks_base, struct MovieTrackingPlaneTrack *plane_track);
+void BKE_tracking_plane_track_free(struct MovieTrackingPlaneTrack *plane_track);
+
+bool BKE_tracking_plane_track_has_marker_at_frame(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+bool BKE_tracking_plane_track_has_enabled_marker_at_frame(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(struct MovieTracking *tracking,
+ struct MovieTrackingObject *object,
+ const char *name);
+
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking);
+
+void BKE_tracking_plane_tracks_deselect_all(struct ListBase *plane_tracks_base);
+
+/* **** Plane Marker **** */
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track,
+ struct MovieTrackingPlaneMarker *plane_marker);
+void BKE_tracking_plane_marker_delete(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
/* **** Object **** */
struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name);
-int BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object);
+bool BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object);
void BKE_tracking_object_unique_name(struct MovieTracking *tracking, struct MovieTrackingObject *object);
@@ -125,6 +155,7 @@ struct MovieTrackingObject *BKE_tracking_object_get_active(struct MovieTracking
struct MovieTrackingObject *BKE_tracking_object_get_camera(struct MovieTracking *tracking);
struct ListBase *BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
+struct ListBase *BKE_tracking_object_get_plane_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
struct MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(struct MovieTracking *tracking,
struct MovieTrackingObject *object);
@@ -147,7 +178,7 @@ void BKE_tracking_distortion_update(struct MovieDistortion *distortion, struct M
void BKE_tracking_distortion_set_threads(struct MovieDistortion *distortion, int threads);
struct MovieDistortion *BKE_tracking_distortion_copy(struct MovieDistortion *distortion);
struct ImBuf *BKE_tracking_distortion_exec(struct MovieDistortion *distortion, struct MovieTracking *tracking,
- struct ImBuf *ibuf, int width, int height, float overscan, int undistort);
+ struct ImBuf *ibuf, int width, int height, float overscan, bool undistort);
void BKE_tracking_distortion_free(struct MovieDistortion *distortion);
void BKE_tracking_distort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]);
@@ -163,15 +194,15 @@ void BKE_tracking_max_undistortion_delta_across_bound(struct MovieTracking *trac
/* **** Image sampling **** */
struct ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height,
struct ImBuf *struct_ibuf, struct MovieTrackingTrack *track,
- struct MovieTrackingMarker *marker, int from_anchor, int use_mask,
+ struct MovieTrackingMarker *marker, bool from_anchor, bool use_mask,
int num_samples_x, int num_samples_y, float pos[2]);
struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
- struct MovieTrackingMarker *marker, int anchored, int disable_channels);
+ struct MovieTrackingMarker *marker, bool anchored, bool disable_channels);
struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
- struct MovieTrackingMarker *marker, int anchored, int disable_channels);
+ struct MovieTrackingMarker *marker, bool anchored, bool disable_channels);
-void BKE_tracking_disable_channels(struct ImBuf *ibuf, int disable_red, int disable_green,
- int disable_blue, int grayscale);
+void BKE_tracking_disable_channels(struct ImBuf *ibuf, bool disable_red, bool disable_green,
+ bool disable_blue, bool grayscale);
/* **** 2D tracking **** */
struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user,
@@ -179,12 +210,20 @@ struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, st
void BKE_tracking_context_free(struct MovieTrackingContext *context);
void BKE_tracking_context_sync(struct MovieTrackingContext *context);
void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context, struct MovieClipUser *user);
-int BKE_tracking_context_step(struct MovieTrackingContext *context);
-void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int backwards);
+bool BKE_tracking_context_step(struct MovieTrackingContext *context);
+void BKE_tracking_context_finish(struct MovieTrackingContext *context);
+
+void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool backwards);
+
+/* **** Plane tracking **** */
+
+void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame);
+void BKE_tracking_retrack_plane_from_existing_motion_at_segment(struct MovieTrackingPlaneTrack *plane_track, int start_frame);
+void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners[4][2], /*const*/ float corners[4][2], float H[3][3]);
/* **** Camera solving **** */
-int BKE_tracking_reconstruction_check(struct MovieTracking *tracking, struct MovieTrackingObject *object,
- char *error_msg, int error_size);
+bool BKE_tracking_reconstruction_check(struct MovieTracking *tracking, struct MovieTrackingObject *object,
+ char *error_msg, int error_size);
struct MovieReconstructContext *BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking,
struct MovieTrackingObject *object,
@@ -193,14 +232,14 @@ struct MovieReconstructContext *BKE_tracking_reconstruction_context_new(struct M
void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context);
void BKE_tracking_reconstruction_solve(struct MovieReconstructContext *context, short *stop, short *do_update,
float *progress, char *stats_message, int message_size);
-int BKE_tracking_reconstruction_finish(struct MovieReconstructContext *context, struct MovieTracking *tracking);
+bool BKE_tracking_reconstruction_finish(struct MovieReconstructContext *context, struct MovieTracking *tracking);
void BKE_tracking_reconstruction_scale(struct MovieTracking *tracking, float scale[3]);
/* **** Feature detection **** */
void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ListBase *tracksbase, struct ImBuf *imbuf,
int framenr, int margin, int min_trackness, int min_distance, struct bGPDlayer *layer,
- int place_outside_layer);
+ bool place_outside_layer);
/* **** 2D stabilization **** */
void BKE_tracking_stabilization_data_get(struct MovieTracking *tracking, int framenr, int width, int height,
diff --git a/source/blender/blenkernel/BKE_treehash.h b/source/blender/blenkernel/BKE_treehash.h
new file mode 100644
index 00000000000..54deef1ce2f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_treehash.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.
+ *
+ * Contributor(s): Blender Foundation 2013
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_TREEHASH_H__
+#define __BKE_TREEHASH_H__
+
+/** \file BKE_treehash.h
+ * \ingroup bke
+ */
+
+struct ID;
+struct GHash;
+struct BLI_mempool;
+struct TreeStoreElem;
+
+/* create and fill hashtable with treestore elements */
+void *BKE_treehash_create_from_treestore(struct BLI_mempool *treestore);
+
+/* full rebuild for already allocated hashtable */
+void *BKE_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore);
+
+/* full rebuild for already allocated hashtable */
+void BKE_treehash_add_element(void *treehash, struct TreeStoreElem *elem);
+
+/* find first unused element with specific type, nr and id */
+struct TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id);
+
+/* find user or unused element with specific type, nr and id */
+struct TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id);
+
+/* free treehash structure */
+void BKE_treehash_free(void *treehash);
+
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 655e0d65133..0ac3737b6a2 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -45,6 +45,7 @@ set(INC
../../../intern/raskter
../../../intern/smoke/extern
../../../extern/libmv
+ ../../../intern/atomic
# XXX - BAD LEVEL CALL WM_api.h
../windowmanager
@@ -114,6 +115,7 @@ set(SRC
intern/material.c
intern/mball.c
intern/mesh.c
+ intern/mesh_evaluate.c
intern/mesh_validate.c
intern/modifier.c
intern/modifiers_bmesh.c
@@ -152,6 +154,7 @@ set(SRC
intern/text.c
intern/texture.c
intern/tracking.c
+ intern/treehash.c
intern/unit.c
intern/world.c
intern/writeavi.c
@@ -243,6 +246,7 @@ set(SRC
BKE_text.h
BKE_texture.h
BKE_tracking.h
+ BKE_treehash.h
BKE_unit.h
BKE_utildefines.h
BKE_world.h
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 6d080fea031..3c3ac61a3cb 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -52,6 +52,7 @@ incs = [
'#/intern/iksolver/extern',
'#/intern/opennl/extern',
'#/intern/smoke/extern',
+ '#/intern/atomic',
'../avi',
'../blenfont',
'../blenlib',
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index d4454a95a2d..ffb92788d4d 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -248,7 +248,7 @@ static CCGAllocatorIFC *_getStandardAllocatorIFC(void)
/***/
-int ccg_gridsize(int level)
+BLI_INLINE int ccg_gridsize(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
@@ -256,7 +256,12 @@ int ccg_gridsize(int level)
return (1 << (level - 1)) + 1;
}
-int ccg_factor(int low_level, int high_level)
+int BKE_ccg_gridsize(int level)
+{
+ return ccg_gridsize(level);
+}
+
+int BKE_ccg_factor(int low_level, int high_level)
{
BLI_assert(low_level > 0 && high_level > 0);
BLI_assert(low_level <= high_level);
@@ -264,7 +269,7 @@ int ccg_factor(int low_level, int high_level)
return 1 << (high_level - low_level);
}
-static int ccg_edgesize(int level)
+BLI_INLINE int ccg_edgesize(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
@@ -272,7 +277,7 @@ static int ccg_edgesize(int level)
return 1 + (1 << level);
}
-static int ccg_spacing(int high_level, int low_level)
+BLI_INLINE int ccg_spacing(int high_level, int low_level)
{
BLI_assert(high_level > 0 && low_level > 0);
BLI_assert(high_level >= low_level);
@@ -281,7 +286,7 @@ static int ccg_spacing(int high_level, int low_level)
return 1 << (high_level - low_level);
}
-static int ccg_edgebase(int level)
+BLI_INLINE int ccg_edgebase(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1);
@@ -742,7 +747,7 @@ BLI_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int le
byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize));
return (float *) &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing) + normalDataOffset];
}
-static int _face_getVertIndex(CCGFace *f, CCGVert *v)
+BLI_INLINE int _face_getVertIndex(CCGFace *f, CCGVert *v)
{
int i;
for (i = 0; i < f->numVerts; i++)
@@ -750,7 +755,7 @@ static int _face_getVertIndex(CCGFace *f, CCGVert *v)
return i;
return -1;
}
-static int _face_getEdgeIndex(CCGFace *f, CCGEdge *e)
+BLI_INLINE int _face_getEdgeIndex(CCGFace *f, CCGEdge *e)
{
int i;
for (i = 0; i < f->numVerts; i++)
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index d350d1f4280..fdf6d2df99f 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -18,6 +18,9 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef __CCGSUBSURF_H__
+#define __CCGSUBSURF_H__
+
/** \file blender/blenkernel/intern/CCGSubSurf.h
* \ingroup bke
*/
@@ -182,3 +185,5 @@ CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi);
int ccgFaceIterator_isStopped (CCGFaceIterator *fi);
void ccgFaceIterator_next (CCGFaceIterator *fi);
void ccgFaceIterator_free (CCGFaceIterator *fi);
+
+#endif /* __CCGSUBSURF_H__ */
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 2ece90183bd..368c1e517ef 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -82,11 +82,20 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
#include "GPU_extensions.h"
#include "GPU_material.h"
+/* very slow! enable for testing only! */
+// #define USE_MODIFIER_VALIDATE
+
+#ifdef USE_MODIFIER_VALIDATE
+# define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true)))
+#else
+# define ASSERT_IS_VALID_DM(dm)
+#endif
+
static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob);
static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid);
-///////////////////////////////////
-///////////////////////////////////
+
+/* -------------------------------------------------------------------- */
static MVert *dm_getVertArray(DerivedMesh *dm)
{
@@ -429,9 +438,9 @@ void DM_update_tessface_data(DerivedMesh *dm)
int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
- int mf_idx,
- totface = dm->getNumTessFaces(dm),
- ml_idx[4];
+ const int totface = dm->getNumTessFaces(dm);
+ int mf_idx;
+ int ml_idx[4];
/* Should never occure, but better abort than segfault! */
if (!polyindex)
@@ -879,6 +888,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob,
add_shapekey_layers(tdm, me, ob);
dm = modwrap_applyModifier(md, ob, tdm, 0);
+ ASSERT_IS_VALID_DM(dm);
if (tdm != dm) tdm->release(tdm);
}
@@ -1440,6 +1450,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
/* XXX Same as above... For now, only weights preview in WPaint mode. */
const int do_mod_wmcol = do_init_wmcol;
+ VirtualModifierData virtualModifierData;
+
ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0;
ModifierApplyFlag deform_app_flags = app_flags;
if (useCache)
@@ -1451,7 +1463,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
has_multires = 0;
if (!skipVirtualArmature) {
- firstmd = modifiers_getVirtualModifierList(ob);
+ firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
}
else {
/* game engine exception */
@@ -1648,6 +1660,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
else {
dm = CDDM_from_mesh(me, ob);
+ ASSERT_IS_VALID_DM(dm);
if (build_shapekey_layers)
add_shapekey_layers(dm, me, ob);
@@ -1672,7 +1685,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
-#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= DM_OMP_LIMIT)
+#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= BKE_MESH_OMP_LIMIT)
{
#pragma omp section
{ range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); }
@@ -1705,6 +1718,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
ndm = modwrap_applyModifier(md, ob, dm, app_flags);
+ ASSERT_IS_VALID_DM(ndm);
if (ndm) {
/* if the modifier returned a new dm, release the old one */
@@ -1731,6 +1745,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
mti->requiredDataMask(ob, md) : 0));
ndm = modwrap_applyModifier(md, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+ ASSERT_IS_VALID_DM(ndm);
if (ndm) {
/* if the modifier returned a new dm, release the old one */
@@ -1748,6 +1763,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX);
ndm = modwrap_applyModifier(md, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+ ASSERT_IS_VALID_DM(ndm);
if (ndm) {
/* if the modifier returned a new dm, release the old one */
@@ -1961,6 +1977,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
int do_init_wmcol = ((((Mesh *)ob->data)->drawflag & ME_DRAWEIGHT) && !do_final_wmcol);
int do_init_statvis = ((((Mesh *)ob->data)->drawflag & ME_DRAW_STATVIS) && !do_init_wmcol);
const int do_mod_wmcol = do_init_wmcol;
+ VirtualModifierData virtualModifierData;
modifiers_clearErrors(ob);
@@ -1969,7 +1986,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
}
dm = NULL;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* copied from mesh_calc_modifiers */
if (do_mod_wmcol) {
@@ -2049,6 +2066,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
}
else {
dm = CDDM_from_editbmesh(em, FALSE, FALSE);
+ ASSERT_IS_VALID_DM(dm);
if (deformedVerts) {
CDDM_apply_vert_coords(dm, deformedVerts);
@@ -2068,10 +2086,13 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
mask &= ~CD_MASK_ORCO;
DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX);
- if (mti->applyModifierEM)
+ if (mti->applyModifierEM) {
ndm = modwrap_applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO);
- else
+ }
+ else {
ndm = modwrap_applyModifier(md, ob, orcodm, MOD_APPLY_ORCO);
+ }
+ ASSERT_IS_VALID_DM(ndm);
if (ndm) {
/* if the modifier returned a new dm, release the old one */
@@ -2097,6 +2118,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE);
else
ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE);
+ ASSERT_IS_VALID_DM(ndm);
if (ndm) {
if (dm && dm != ndm)
@@ -2738,11 +2760,9 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
int offs = 0; /* initial triangulation is 0,1,2 and 0, 2, 3 */
if (nr_verts == 4) {
float pos_len_diag0, pos_len_diag1;
- float vtmp[3];
- sub_v3_v3v3(vtmp, verts[2], verts[0]);
- pos_len_diag0 = dot_v3v3(vtmp, vtmp);
- sub_v3_v3v3(vtmp, verts[3], verts[1]);
- pos_len_diag1 = dot_v3v3(vtmp, vtmp);
+
+ pos_len_diag0 = len_squared_v3v3(verts[2], verts[0]);
+ pos_len_diag1 = len_squared_v3v3(verts[3], verts[1]);
if (pos_len_diag1 < pos_len_diag0) {
offs = 1; // alter split
@@ -2750,10 +2770,8 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
else if (pos_len_diag0 == pos_len_diag1) { /* do UV check instead */
float tex_len_diag0, tex_len_diag1;
- sub_v2_v2v2(vtmp, tex_coords[2], tex_coords[0]);
- tex_len_diag0 = dot_v2v2(vtmp, vtmp);
- sub_v2_v2v2(vtmp, tex_coords[3], tex_coords[1]);
- tex_len_diag1 = dot_v2v2(vtmp, vtmp);
+ tex_len_diag0 = len_squared_v2v2(tex_coords[2], tex_coords[0]);
+ tex_len_diag1 = len_squared_v2v2(tex_coords[3], tex_coords[1]);
if (tex_len_diag1 < tex_len_diag0) {
offs = 1; /* alter split */
@@ -2762,7 +2780,7 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
}
nr_tris_to_pile = nr_verts - 2;
if (nr_tris_to_pile == 1 || nr_tris_to_pile == 2) {
- const int indices[] = {offs + 0, offs + 1, offs + 2, offs + 0, offs + 2, (offs + 3) & 0x3 };
+ const int indices[6] = {offs + 0, offs + 1, offs + 2, offs + 0, offs + 2, (offs + 3) & 0x3 };
int t;
for (t = 0; t < nr_tris_to_pile; t++) {
float f2x_area_uv;
@@ -2782,7 +2800,7 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm)
cross_v3_v3v3(norm, v0, v1);
f2x_surf_area = len_v3(norm);
- fsurf_ratio = f2x_surf_area / f2x_area_uv; // tri area divided by texture area
+ fsurf_ratio = f2x_surf_area / f2x_area_uv; /* tri area divided by texture area */
nr_accumulated++;
dsum += (double)(fsurf_ratio);
@@ -3262,4 +3280,35 @@ void DM_debug_print_cdlayers(CustomData *data)
printf("}\n");
}
+bool DM_is_valid(DerivedMesh *dm)
+{
+ const bool do_verbose = true;
+ const bool do_fixes = false;
+
+ bool is_valid = true;
+ bool is_change = true;
+
+ is_valid &= BKE_mesh_validate_all_customdata(
+ dm->getVertDataLayout(dm),
+ dm->getEdgeDataLayout(dm),
+ dm->getLoopDataLayout(dm),
+ dm->getPolyDataLayout(dm),
+ 0, /* setting mask here isn't useful, gives false positives */
+ do_verbose, do_fixes, &is_change);
+
+ is_valid &= BKE_mesh_validate_arrays(
+ NULL,
+ dm->getVertArray(dm), dm->getNumVerts(dm),
+ dm->getEdgeArray(dm), dm->getNumEdges(dm),
+ dm->getTessFaceArray(dm), dm->getNumTessFaces(dm),
+ dm->getLoopArray(dm), dm->getNumLoops(dm),
+ dm->getPolyArray(dm), dm->getNumPolys(dm),
+ dm->getVertDataArray(dm, CD_MDEFORMVERT),
+ do_verbose, do_fixes, &is_change);
+
+ BLI_assert(is_change == false);
+
+ return is_valid;
+}
+
#endif /* NDEBUG */
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index bfef3542c45..b0644da4598 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -489,6 +489,22 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name)
return chan;
}
+#ifndef NDEBUG
+bool BKE_pose_channels_is_valid(const bPose *pose)
+{
+ if (pose->chanhash) {
+ bPoseChannel *pchan;
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (BLI_ghash_lookup(pose->chanhash, pchan->name) != pchan) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+#endif
/* Find the active posechannel for an object (we can't just use pose, as layer info is in armature) */
bPoseChannel *BKE_pose_channel_active(Object *ob)
{
@@ -594,11 +610,43 @@ void BKE_pose_ikparam_init(bPose *pose)
}
}
+
+/* only for real IK, not for auto-IK */
+static bool pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
+{
+ bConstraint *con;
+ Bone *bone;
+
+ /* No need to check if constraint is active (has influence),
+ * since all constraints with CONSTRAINT_IK_AUTO are active */
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = con->data;
+ if ((data->rootbone == 0) || (data->rootbone > level)) {
+ if ((data->flag & CONSTRAINT_IK_AUTO) == 0)
+ return true;
+ }
+ }
+ }
+ for (bone = pchan->bone->childbase.first; bone; bone = bone->next) {
+ pchan = BKE_pose_channel_find_name(ob->pose, bone->name);
+ if (pchan && pose_channel_in_IK_chain(ob, pchan, level + 1))
+ return true;
+ }
+ return false;
+}
+
+bool BKE_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
+{
+ return pose_channel_in_IK_chain(ob, pchan, 0);
+}
+
+
void BKE_pose_channels_hash_make(bPose *pose)
{
if (!pose->chanhash) {
bPoseChannel *pchan;
-
+
pose->chanhash = BLI_ghash_str_new("make_pose_chan gh");
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next)
BLI_ghash_insert(pose->chanhash, pchan->name, pchan);
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
index ae6ec7cd7e1..129bc4657b4 100644
--- a/source/blender/blenkernel/intern/addon.c
+++ b/source/blender/blenkernel/intern/addon.c
@@ -20,6 +20,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenkernel/intern/addon.c
+ * \ingroup bke
+ */
+
#include <stddef.h>
#include <stdlib.h>
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index ba680147201..5c3f67d8959 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -488,18 +488,16 @@ void free_path(Path *path)
/* calculate a curve-deform path for a curve
* - only called from displist.c -> do_makeDispListCurveTypes
*/
-void calc_curvepath(Object *ob)
+void calc_curvepath(Object *ob, ListBase *nurbs)
{
BevList *bl;
BevPoint *bevp, *bevpn, *bevpfirst, *bevplast;
PathPoint *pp;
- Curve *cu;
Nurb *nu;
Path *path;
float *fp, *dist, *maxdist, xyz[3];
float fac, d = 0, fac1, fac2;
int a, tot, cycl = 0;
- ListBase *nurbs;
/* in a path vertices are with equal differences: path->len = number of verts */
/* NOW WITH BEVELCURVE!!! */
@@ -507,21 +505,19 @@ void calc_curvepath(Object *ob)
if (ob == NULL || ob->type != OB_CURVE) {
return;
}
- cu = ob->data;
- if (cu->path) free_path(cu->path);
- cu->path = NULL;
+ if (ob->curve_cache->path) free_path(ob->curve_cache->path);
+ ob->curve_cache->path = NULL;
/* weak! can only use first curve */
- bl = cu->bev.first;
+ bl = ob->curve_cache->bev.first;
if (bl == NULL || !bl->nr) {
return;
}
- nurbs = BKE_curve_nurbs_get(cu);
nu = nurbs->first;
- cu->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
+ ob->curve_cache->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
/* if POLY: last vertice != first vertice */
cycl = (bl->poly != -1);
@@ -598,8 +594,7 @@ void calc_curvepath(Object *ob)
static int interval_test(const int min, const int max, int p1, const int cycl)
{
if (cycl) {
- if (p1 < min) p1 = ((p1 - min) % (max - min + 1)) + max + 1;
- else if (p1 > max) p1 = ((p1 - min) % (max - min + 1)) + min;
+ p1 = mod_i(p1 - min, (max - min + 1)) + min;
}
else {
if (p1 < min) p1 = min;
@@ -630,15 +625,15 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
if (ob == NULL || ob->type != OB_CURVE) return 0;
cu = ob->data;
- if (cu->path == NULL || cu->path->data == NULL) {
+ if (ob->curve_cache == NULL || ob->curve_cache->path == NULL || ob->curve_cache->path->data == NULL) {
printf("no path!\n");
return 0;
}
- path = cu->path;
+ path = ob->curve_cache->path;
pp = path->data;
/* test for cyclic */
- bl = cu->bev.first;
+ bl = ob->curve_cache->bev.first;
if (!bl) return 0;
if (!bl->nr) return 0;
if (bl->poly > -1) cycl = 1;
@@ -756,14 +751,24 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste
DupliObject *dob;
Group *group;
GroupObject *go;
- float mat[4][4], tmat[4][4], id;
-
+ float mat[4][4], ob_obmat_ofs[4][4], id;
+
if (ob->dup_group == NULL) return;
group = ob->dup_group;
/* simple preventing of too deep nested groups */
if (level > MAX_DUPLI_RECUR) return;
+ /* don't access 'ob->obmat' from now on. */
+ copy_m4_m4(ob_obmat_ofs, ob->obmat);
+
+ if (!is_zero_v3(group->dupli_ofs)) {
+ float tvec[3];
+ copy_v3_v3(tvec, group->dupli_ofs);
+ mul_mat3_m4_v3(ob_obmat_ofs, tvec);
+ sub_v3_v3(ob_obmat_ofs[3], tvec);
+ }
+
/* handles animated groups, and */
/* we need to check update for objects that are not in scene... */
@@ -781,14 +786,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste
if (go->ob != ob) {
/* group dupli offset, should apply after everything else */
- if (!is_zero_v3(group->dupli_ofs)) {
- copy_m4_m4(tmat, go->ob->obmat);
- sub_v3_v3v3(tmat[3], tmat[3], group->dupli_ofs);
- mul_m4_m4m4(mat, ob->obmat, tmat);
- }
- else {
- mul_m4_m4m4(mat, ob->obmat, go->ob->obmat);
- }
+ mul_m4_m4m4(mat, ob_obmat_ofs, go->ob->obmat);
dob = new_dupli_object(lb, go->ob, mat, ob->lay, persistent_id, level, id, OB_DUPLIGROUP, flag);
@@ -802,7 +800,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste
if (go->ob->transflag & OB_DUPLI) {
copy_m4_m4(dob->ob->obmat, dob->mat);
- object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, persistent_id, level + 1, id, flag);
+ object_duplilist_recursive(&group->id, scene, go->ob, lb, ob_obmat_ofs, persistent_id, level + 1, id, flag);
copy_m4_m4(dob->ob->obmat, dob->omat);
}
}
@@ -1332,7 +1330,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
psys_check_group_weights(part);
- psys->lattice = psys_get_lattice(&sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
/* gather list of objects or single object */
if (part->ren_as == PART_DRAW_GR) {
@@ -1569,9 +1567,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
if (obcopylist)
MEM_freeN(obcopylist);
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice = NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 4b05b0800a5..74578266c63 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -42,6 +42,7 @@
#include "BLI_blenlib.h"
#include "BLI_alloca.h"
#include "BLI_dynstr.h"
+#include "BLI_listbase.h"
#include "BLF_translation.h"
@@ -759,6 +760,76 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, AnimData *adt, ID *ref_id, cons
MEM_freeN(newN);
}
+/* *************************** */
+/* remove of individual paths */
+
+/* Check RNA-Paths for a list of F-Curves */
+static void fcurves_path_remove_fix(const char *prefix, ListBase *curves)
+{
+ FCurve *fcu, *fcn;
+ if (!prefix) return;
+
+ /* we need to check every curve... */
+ for (fcu = curves->first; fcu; fcu = fcn) {
+ fcn = fcu->next;
+
+ if (fcu->rna_path) {
+ if (STRPREFIX(fcu->rna_path, prefix)) {
+ BLI_remlink(curves, fcu);
+ free_fcurve(fcu);
+ }
+ }
+ }
+}
+
+/* Check RNA-Paths for a list of F-Curves */
+static void nlastrips_path_remove_fix(const char *prefix, ListBase *strips)
+{
+ NlaStrip *strip;
+
+ /* recursively check strips, fixing only actions... */
+ for (strip = strips->first; strip; strip = strip->next) {
+
+ /* fix strip's action */
+ if (strip->act)
+ fcurves_path_remove_fix(prefix, &strip->act->curves);
+
+ /* check sub-strips (if metas) */
+ nlastrips_path_remove_fix(prefix, &strip->strips);
+ }
+}
+
+void BKE_animdata_fix_paths_remove(ID *id, const char *prefix)
+{
+ /* Only some ID-blocks have this info for now, so we cast the
+ * types that do to be of type IdAdtTemplate
+ */
+ NlaTrack *nlt;
+
+ if (id_type_can_have_animdata(id)) {
+ IdAdtTemplate *iat = (IdAdtTemplate *)id;
+ AnimData *adt = iat->adt;
+
+ /* check if there's any AnimData to start with */
+ if (adt) {
+
+ /* free fcurves */
+ if (adt->action)
+ fcurves_path_remove_fix(prefix, &adt->action->curves);
+
+ if (adt->tmpact)
+ fcurves_path_remove_fix(prefix, &adt->tmpact->curves);
+
+ /* free drivers - stored as a list of F-Curves */
+ fcurves_path_remove_fix(prefix, &adt->drivers);
+
+ /* NLA Data - Animation Data for Strips */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next)
+ nlastrips_path_remove_fix(prefix, &nlt->strips);
+ }
+ }
+}
+
/* Whole Database Ops -------------------------------------------- */
/* apply the given callback function on all data in main database */
@@ -1652,19 +1723,19 @@ static void nlaevalchan_value_init(NlaEvalChannel *nec)
*/
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
nec->value = (float)RNA_property_boolean_get_default_index(ptr, prop, index);
else
nec->value = (float)RNA_property_boolean_get_default(ptr, prop);
break;
case PROP_INT:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
nec->value = (float)RNA_property_int_get_default_index(ptr, prop, index);
else
nec->value = (float)RNA_property_int_get_default(ptr, prop);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
nec->value = RNA_property_float_get_default_index(ptr, prop, index);
else
nec->value = RNA_property_float_get_default(ptr, prop);
@@ -2071,19 +2142,19 @@ void nladata_flush_channels(ListBase *channels)
/* write values - see animsys_write_rna_setting() to sync the code */
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
RNA_property_boolean_set_index(ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value));
else
RNA_property_boolean_set(ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value));
break;
case PROP_INT:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
RNA_property_int_set_index(ptr, prop, array_index, (int)value);
else
RNA_property_int_set(ptr, prop, (int)value);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
RNA_property_float_set_index(ptr, prop, array_index, value);
else
RNA_property_float_set(ptr, prop, value);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index f006710dc21..6b2b782717d 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -381,8 +381,6 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a
/* ************* B-Bone support ******************* */
-#define MAX_BBONE_SUBDIV 32
-
/* data has MAX_BBONE_SUBDIV+1 interpolated points, will become desired amount with equal distances */
static void equalize_bezier(float *data, int desired)
{
@@ -426,11 +424,8 @@ static void equalize_bezier(float *data, int desired)
/* returns pointer to static array, filled with desired amount of bone->segments elements */
/* this calculation is done within unit bone space */
-Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
+void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV])
{
- static Mat4 bbone_array[MAX_BBONE_SUBDIV];
- static Mat4 bbone_rest_array[MAX_BBONE_SUBDIV];
- Mat4 *result_array = (rest) ? bbone_rest_array : bbone_array;
bPoseChannel *next, *prev;
Bone *bone = pchan->bone;
float h1[3], h2[3], scale[3], length, hlength1, hlength2, roll1 = 0.0f, roll2;
@@ -587,8 +582,6 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL);
}
}
-
- return result_array;
}
/* ************ Armature Deform ******************* */
@@ -602,13 +595,15 @@ typedef struct bPoseChanDeform {
static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, int use_quaternion)
{
Bone *bone = pchan->bone;
- Mat4 *b_bone = b_bone_spline_setup(pchan, 0);
- Mat4 *b_bone_rest = b_bone_spline_setup(pchan, 1);
+ Mat4 b_bone[MAX_BBONE_SUBDIV], b_bone_rest[MAX_BBONE_SUBDIV];
Mat4 *b_bone_mats;
DualQuat *b_bone_dual_quats = NULL;
float tmat[4][4] = MAT4_UNITY;
int a;
+ b_bone_spline_setup(pchan, 0, b_bone);
+ b_bone_spline_setup(pchan, 1, b_bone_rest);
+
/* allocate b_bone matrices and dual quats */
b_bone_mats = MEM_mallocN((1 + bone->segments) * sizeof(Mat4), "BBone defmats");
pdef_info->b_bone_mats = b_bone_mats;
@@ -1826,18 +1821,16 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
* - this is a workaround for a depsgraph bug...
*/
if (ikData->tar) {
- Curve *cu = ikData->tar->data;
-
/* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
/* only happens on reload file, but violates depsgraph still... fix! */
- if (ELEM(NULL, cu->path, cu->path->data)) {
+ if (ELEM3(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
BKE_displist_make_curveTypes(scene, ikData->tar, 0);
/* path building may fail in EditMode after removing verts [#33268]*/
- if (ELEM(NULL, cu->path, cu->path->data)) {
+ if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
/* BLI_assert(cu->path != NULL); */
return;
}
@@ -1901,7 +1894,6 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
* since it's easier to determine the positions of all the joints beforehand this way
*/
if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) {
- Curve *cu = (Curve *)ikData->tar->data;
float splineLen, maxScale;
int i;
@@ -1914,7 +1906,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
/* get the current length of the curve */
/* NOTE: this is assumed to be correct even after the curve was resized */
- splineLen = cu->path->totdist;
+ splineLen = ikData->tar->curve_cache->path->totdist;
/* calculate the scale factor to multiply all the path values by so that the
* bone chain retains its current length, such that
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 26f481e5341..5ef39e8d48e 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -462,13 +462,16 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
return (bfd ? retval : BKE_READ_FILE_FAIL);
}
-int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports)
+int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports, int update_defaults)
{
BlendFileData *bfd;
bfd = BLO_read_from_memory(filebuf, filelength, reports);
- if (bfd)
+ if (bfd) {
+ if (update_defaults)
+ BLO_update_defaults_startup_blend(bfd->main);
setup_app_data(C, bfd, "<memory2>");
+ }
else
BKE_reports_prepend(reports, "Loading failed: ");
@@ -924,9 +927,7 @@ int BKE_copybuffer_save(const char *filename, ReportList *reports)
ID *id;
ListBase *lb1 = lbarray[a], *lb2 = fromarray[a];
- while (lb2->first) {
- id = lb2->first;
- BLI_remlink(lb2, id);
+ while ((id = BLI_pophead(lb2))) {
BLI_addtail(lb1, id);
id_sort_by_name(lb1, id);
}
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index cf761bf3dab..a8d64ea9fb6 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -206,6 +206,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
BVHTreeRayHit hit;
float radius = val->personal_space * pa->size, ray_dir[3];
+ memset(&col, 0, sizeof(ParticleCollision));
+
copy_v3_v3(col.co1, pa->prev_state.co);
add_v3_v3v3(col.co2, pa->prev_state.co, pa->prev_state.vel);
sub_v3_v3v3(ray_dir, col.co2, col.co1);
@@ -253,7 +255,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
//check boids in own system
if (acbr->options & BRULE_ACOLL_WITH_BOIDS) {
- neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, acbr->look_ahead * len_v3(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn);
+ neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, pa->prev_state.co, pa->prev_state.ave,
+ &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel));
if (neighbors > 1) for (n=1; n<neighbors; n++) {
copy_v3_v3(co1, pa->prev_state.co);
copy_v3_v3(vel1, pa->prev_state.vel);
@@ -299,7 +302,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
if (epsys) {
- neighbors = BLI_kdtree_range_search(epsys->tree, acbr->look_ahead * len_v3(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn);
+ neighbors = BLI_kdtree_range_search(epsys->tree, pa->prev_state.co, pa->prev_state.ave,
+ &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel));
if (neighbors > 0) for (n=0; n<neighbors; n++) {
copy_v3_v3(co1, pa->prev_state.co);
copy_v3_v3(vel1, pa->prev_state.vel);
@@ -354,7 +358,8 @@ static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues
ParticleTarget *pt;
float len = 2.0f * val->personal_space * pa->size + 1.0f;
float vec[3] = {0.0f, 0.0f, 0.0f};
- int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn);
+ int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, pa->prev_state.co, NULL,
+ &ptn, 2.0f * val->personal_space * pa->size);
int ret = 0;
if (neighbors > 1 && ptn[1].dist!=0.0f) {
@@ -372,7 +377,8 @@ static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues
ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
if (epsys) {
- neighbors = BLI_kdtree_range_search(epsys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn);
+ neighbors = BLI_kdtree_range_search(epsys->tree, pa->prev_state.co, NULL,
+ &ptn, 2.0f * val->personal_space * pa->size);
if (neighbors > 0 && ptn[0].dist < len) {
sub_v3_v3v3(vec, pa->prev_state.co, ptn[0].co);
@@ -392,7 +398,7 @@ static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UN
{
KDTreeNearest ptn[11];
float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
- int neighbors = BLI_kdtree_find_n_nearest(bbd->sim->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn);
+ int neighbors = BLI_kdtree_find_nearest_n(bbd->sim->psys->tree, pa->state.co, pa->prev_state.ave, ptn, 11);
int n;
int ret = 0;
@@ -619,7 +625,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
int n, ret = 0;
/* calculate own group strength */
- int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn);
+ int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, pa->prev_state.co, NULL,
+ &ptn, fbr->distance);
for (n=0; n<neighbors; n++) {
bpa = bbd->sim->psys->particles[ptn[n].index].boid;
health += bpa->data.health;
@@ -635,7 +642,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
if (epsys) {
epars = epsys->particles;
- neighbors = BLI_kdtree_range_search(epsys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn);
+ neighbors = BLI_kdtree_range_search(epsys->tree, pa->prev_state.co, NULL,
+ &ptn, fbr->distance);
health = 0.0f;
@@ -771,6 +779,8 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float grou
if (!bbd->sim->colliders)
return NULL;
+ memset(&col, 0, sizeof(ParticleCollision));
+
/* first try to find below boid */
copy_v3_v3(col.co1, pa->state.co);
sub_v3_v3v3(col.co2, pa->state.co, zvec);
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 4018b757559..b7a6cf4153a 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -76,7 +76,7 @@
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_sequencer.h"
-#include "BKE_image.h" /* so we can check the image's type */
+#include "BKE_image.h"
#include "BKE_bpath.h" /* own include */
@@ -297,7 +297,14 @@ static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char
return false;
}
else {
+ bool was_relative = BLI_path_is_rel(path_dst);
+
BLI_strncpy(path_dst, filename_new, FILE_MAX);
+
+ /* keep path relative if the previous one was relative */
+ if (was_relative)
+ BLI_path_rel(path_dst, data->basedir);
+
return true;
}
}
@@ -307,6 +314,7 @@ void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportLis
{
struct BPathFind_Data data = {NULL};
+ data.basedir = bmain->name;
data.reports = reports;
data.searchdir = searchpath;
data.find_all = find_all;
@@ -330,6 +338,9 @@ static bool rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *ab
path_src = path;
}
+ /* so functions can check old value */
+ BLI_strncpy(path_dst, path, FILE_MAX);
+
if (visit_cb(userdata, path_dst, path_src)) {
BLI_strncpy(path, path_dst, FILE_MAX);
return true;
@@ -388,6 +399,13 @@ static bool rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *a
}
}
+/* fix the image user "ok" tag after updating paths, so ImBufs get loaded */
+static void bpath_traverse_image_user_cb(Image *ima, ImageUser *iuser, void *customdata)
+{
+ if (ima == customdata)
+ iuser->ok = 1;
+}
+
/* Run visitor function 'visit' on all paths contained in 'id'. */
void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
{
@@ -404,7 +422,12 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
ima = (Image *)id;
if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
- rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data);
+ if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
+ if (!ima->packedfile) {
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+ BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb);
+ }
+ }
}
}
break;
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 70b5d90120d..790c1f09ff0 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -951,7 +951,6 @@ float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len)
if (p >= len) return 0;
else p = p / len;
- curvemapping_initialize(br->curve);
strength = curvemapping_evaluateF(br->curve, 0, p);
CLAMP(strength, 0.0f, 1.0f);
@@ -967,15 +966,14 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len)
else
p = p / len;
- curvemapping_initialize(br->curve);
return curvemapping_evaluateF(br->curve, 0, p);
}
/* TODO: should probably be unified with BrushPainter stuff? */
-unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
+unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_secondary)
{
unsigned int *texcache = NULL;
- MTex *mtex = &br->mtex;
+ MTex *mtex = (use_secondary) ? &br->mask_mtex : &br->mtex;
TexResult texres = {0};
int hasrgb, ix, iy;
int side = half_side * 2;
@@ -1016,7 +1014,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
/**** Radial Control ****/
-struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br)
+struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary)
{
ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture");
unsigned int *texcache;
@@ -1024,7 +1022,8 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br)
int half = side / 2;
int i, j;
- texcache = BKE_brush_gen_texture_cache(br, half);
+ curvemapping_initialize(br->curve);
+ texcache = BKE_brush_gen_texture_cache(br, half, secondary);
im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect");
im->x = im->y = side;
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 5b66b8b4cd4..370dbc62ef8 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -355,7 +355,7 @@ float nearest_point_in_tri_surface(const float v0[3], const float v1[3], const f
/*
- * BVH from meshs callbacks
+ * BVH from meshes callbacks
*/
/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index f9444ca2cf9..536ec95e3d1 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -456,9 +456,10 @@ void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
typedef struct CameraViewFrameData {
+ float plane_tx[4][4]; /* 4 planes (not 4x4 matrix)*/
float frame_tx[4][3];
float normal_tx[4][3];
- float dist_vals[4];
+ float dist_vals_sq[4]; /* distance squared (signed) */
unsigned int tot;
} CameraViewFrameData;
@@ -468,9 +469,9 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
unsigned int i;
for (i = 0; i < 4; i++) {
- float nd = dist_to_plane_v3(co, data->frame_tx[i], data->normal_tx[i]);
- if (nd < data->dist_vals[i]) {
- data->dist_vals[i] = nd;
+ float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]);
+ if (nd < data->dist_vals_sq[i]) {
+ data->dist_vals_sq[i] = nd;
}
}
@@ -514,15 +515,12 @@ int BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
}
for (i = 0; i < 4; i++) {
- normal_tri_v3(data_cb.normal_tx[i],
- zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
+ normal_tri_v3(data_cb.normal_tx[i], zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
+ plane_from_point_normal_v3(data_cb.plane_tx[i], data_cb.frame_tx[i], data_cb.normal_tx[i]);
}
/* initialize callback data */
- data_cb.dist_vals[0] =
- data_cb.dist_vals[1] =
- data_cb.dist_vals[2] =
- data_cb.dist_vals[3] = FLT_MAX;
+ copy_v4_fl(data_cb.dist_vals_sq, FLT_MAX);
data_cb.tot = 0;
/* run callback on all visible points */
BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
@@ -537,11 +535,16 @@ int BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
float plane_isect_pt_1[3], plane_isect_pt_2[3];
+ /* could make a generic macro */
+#define SQRT_SIGNED(f) copysign(sqrtf(fabsf(f)), f)
+
/* apply the dist-from-plane's to the transformed plane points */
for (i = 0; i < 4; i++) {
- mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]);
+ mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], SQRT_SIGNED(data_cb.dist_vals_sq[i]));
}
+#undef SQRT_SIGNED
+
isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
plane_tx[0], data_cb.normal_tx[0],
plane_tx[2], data_cb.normal_tx[2]);
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 6205c8016b6..1bc12cffe7b 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1814,7 +1814,13 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
DerivedMesh *CDDM_from_curve(Object *ob)
{
- return CDDM_from_curve_displist(ob, &ob->disp);
+ ListBase disp = {NULL, NULL};
+
+ if (ob->curve_cache) {
+ disp = ob->curve_cache->disp;
+ }
+
+ return CDDM_from_curve_displist(ob, &disp);
}
DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
@@ -2399,7 +2405,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
STACK_DECLARE(mpoly);
STACK_DECLARE(oldp);
- EdgeHash *ehash = BLI_edgehash_new();
+ EdgeHash *ehash = BLI_edgehash_new_ex(__func__, totedge);
int i, j, c;
@@ -2601,10 +2607,12 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm)
EdgeHashIterator *ehi;
MFace *mf = cddm->mface;
MEdge *med;
- EdgeHash *eh = BLI_edgehash_new();
- int i, *index, numEdges, maxFaces = dm->numTessFaceData;
+ EdgeHash *eh;
+ int i, *index, numEdges, numFaces = dm->numTessFaceData;
+
+ eh = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(numFaces));
- for (i = 0; i < maxFaces; i++, mf++) {
+ for (i = 0; i < numFaces; i++, mf++) {
if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
@@ -2634,7 +2642,7 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm)
for (ehi = BLI_edgehashIterator_new(eh), i = 0;
BLI_edgehashIterator_isDone(ehi) == FALSE;
- BLI_edgehashIterator_step(ehi), ++i, ++med, ++index)
+ BLI_edgehashIterator_step(ehi), i++, med++, index++)
{
BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
@@ -2662,21 +2670,27 @@ void CDDM_calc_edges(DerivedMesh *dm)
MPoly *mp = cddm->mpoly;
MLoop *ml;
MEdge *med, *origmed;
- EdgeHash *eh = BLI_edgehash_new();
+ EdgeHash *eh;
+ unsigned int eh_reserve;
int v1, v2;
int *eindex;
- int i, j, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
+ int i, j, *index;
+ const int numFaces = dm->numPolyData;
+ const int numLoops = dm->numLoopData;
+ int numEdges = dm->numEdgeData;
eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
-
med = cddm->medge;
+
+ eh_reserve = max_ii(med ? numEdges : 0, BLI_EDGEHASH_SIZE_GUESS_FROM_LOOPS(numLoops));
+ eh = BLI_edgehash_new_ex(__func__, eh_reserve);
if (med) {
for (i = 0; i < numEdges; i++, med++) {
BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i + 1));
}
}
- for (i = 0; i < maxFaces; i++, mp++) {
+ for (i = 0; i < numFaces; i++, mp++) {
ml = cddm->mloop + mp->loopstart;
for (j = 0; j < mp->totloop; j++, ml++) {
v1 = ml->v;
@@ -2726,7 +2740,7 @@ void CDDM_calc_edges(DerivedMesh *dm)
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
mp = cddm->mpoly;
- for (i = 0; i < maxFaces; i++, mp++) {
+ for (i = 0; i < numFaces; i++, mp++) {
ml = cddm->mloop + mp->loopstart;
for (j = 0; j < mp->totloop; j++, ml++) {
v1 = ml->v;
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 05ffd4a6265..e4c6f7790d7 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -332,11 +332,13 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
if (clmd->clothObject == NULL) {
if (!cloth_from_object(ob, clmd, result, framenr, 1)) {
BKE_ptcache_invalidate(cache);
+ modifier_setError(&(clmd->modifier), "Can't initialize cloth");
return 0;
}
if (clmd->clothObject == NULL) {
BKE_ptcache_invalidate(cache);
+ modifier_setError(&(clmd->modifier), "Null cloth object");
return 0;
}
@@ -973,6 +975,18 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm )
* SPRING NETWORK BUILDING IMPLEMENTATION BEGIN
***************************************************************************************/
+BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1)
+{
+ if (v0 < v1) {
+ spring->ij = v0;
+ spring->kl = v1;
+ }
+ else {
+ spring->ij = v1;
+ spring->kl = v0;
+ }
+}
+
// be careful: implicit solver has to be resettet when using this one!
// --> only for implicit handling of this spring!
int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type)
@@ -1004,10 +1018,20 @@ int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int
return 0;
}
-static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *UNUSED(edgehash), LinkNode **edgelist)
+static void cloth_free_edgelist(LinkNode **edgelist, unsigned int numverts)
+{
+ if (edgelist) {
+ unsigned int i;
+ for (i = 0; i < numverts; i++) {
+ BLI_linklist_free(edgelist[i], NULL);
+ }
+
+ MEM_freeN(edgelist);
+ }
+}
+
+static void cloth_free_errorsprings(Cloth *cloth, LinkNode **edgelist)
{
- unsigned int i = 0;
-
if ( cloth->springs != NULL ) {
LinkNode *search = cloth->springs;
while (search) {
@@ -1020,17 +1044,13 @@ static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *UNUSED(edgehash), Li
cloth->springs = NULL;
}
-
- if (edgelist) {
- for ( i = 0; i < cloth->numverts; i++ ) {
- BLI_linklist_free ( edgelist[i], NULL );
- }
- MEM_freeN ( edgelist );
- }
+ cloth_free_edgelist(edgelist, cloth->numverts);
- if (cloth->edgehash)
- BLI_edgehash_free ( cloth->edgehash, NULL );
+ if (cloth->edgehash) {
+ BLI_edgehash_free(cloth->edgehash, NULL);
+ cloth->edgehash = NULL;
+ }
}
/* update stiffness if vertex group values are changing from frame to frame */
@@ -1094,30 +1114,25 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
if ( numedges==0 )
return 0;
+ /* NOTE: handling ownership of sptings and edgehash is quite sloppy
+ * currenlty they are never initialized but assert just to be sure */
+ BLI_assert(cloth->springs == NULL);
+ BLI_assert(cloth->edgehash == NULL);
+
cloth->springs = NULL;
+ cloth->edgehash = NULL;
edgelist = MEM_callocN ( sizeof (LinkNode *) * numverts, "cloth_edgelist_alloc" );
if (!edgelist)
return 0;
-
- for ( i = 0; i < numverts; i++ ) {
- edgelist[i] = NULL;
- }
-
- if ( cloth->springs )
- MEM_freeN ( cloth->springs );
-
- // create spring network hash
- edgehash = BLI_edgehash_new();
// structural springs
for ( i = 0; i < numedges; i++ ) {
spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
if ( spring ) {
- spring->ij = MIN2(medge[i].v1, medge[i].v2);
- spring->kl = MAX2(medge[i].v2, medge[i].v1);
+ spring_verts_ordered_set(spring, medge[i].v1, medge[i].v2);
spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest);
clmd->sim_parms->avg_spring_len += spring->restlen;
cloth->verts[spring->ij].avg_spring_len += spring->restlen;
@@ -1132,11 +1147,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
BLI_linklist_prepend ( &cloth->springs, spring );
}
else {
- cloth_free_errorsprings(cloth, edgehash, edgelist);
+ cloth_free_errorsprings(cloth, edgelist);
return 0;
}
}
-
+
if (struct_springs > 0)
clmd->sim_parms->avg_spring_len /= struct_springs;
@@ -1153,12 +1168,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
if (!spring) {
- cloth_free_errorsprings(cloth, edgehash, edgelist);
+ cloth_free_errorsprings(cloth, edgelist);
return 0;
}
- spring->ij = MIN2(mface[i].v1, mface[i].v3);
- spring->kl = MAX2(mface[i].v3, mface[i].v1);
+ spring_verts_ordered_set(spring, mface[i].v1, mface[i].v3);
spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest);
spring->type = CLOTH_SPRING_TYPE_SHEAR;
spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f;
@@ -1174,12 +1188,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
if (!spring) {
- cloth_free_errorsprings(cloth, edgehash, edgelist);
+ cloth_free_errorsprings(cloth, edgelist);
return 0;
}
- spring->ij = MIN2(mface[i].v2, mface[i].v4);
- spring->kl = MAX2(mface[i].v4, mface[i].v2);
+ spring_verts_ordered_set(spring, mface[i].v2, mface[i].v4);
spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest);
spring->type = CLOTH_SPRING_TYPE_SHEAR;
spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f;
@@ -1191,6 +1204,9 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
BLI_linklist_prepend ( &cloth->springs, spring );
}
+ edgehash = BLI_edgehash_new_ex(__func__, numedges);
+ cloth->edgehash = edgehash;
+
if (numfaces) {
// bending springs
search2 = cloth->springs;
@@ -1206,18 +1222,17 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
// check for existing spring
// check also if startpoint is equal to endpoint
- if (!BLI_edgehash_haskey(edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2)) &&
- (index2 != tspring2->ij))
+ if ((index2 != tspring2->ij) &&
+ !BLI_edgehash_haskey(edgehash, tspring2->ij, index2))
{
spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
if (!spring) {
- cloth_free_errorsprings(cloth, edgehash, edgelist);
+ cloth_free_errorsprings(cloth, edgelist);
return 0;
}
- spring->ij = MIN2(tspring2->ij, index2);
- spring->kl = MAX2(tspring2->ij, index2);
+ spring_verts_ordered_set(spring, tspring2->ij, index2);
spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest);
spring->type = CLOTH_SPRING_TYPE_BENDING;
spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f;
@@ -1249,7 +1264,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
if (!spring) {
- cloth_free_errorsprings(cloth, edgehash, edgelist);
+ cloth_free_errorsprings(cloth, edgelist);
return 0;
}
@@ -1268,34 +1283,30 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
}
}
+ /* note: the edges may already exist so run reinsert */
+
/* insert other near springs in edgehash AFTER bending springs are calculated (for selfcolls) */
for (i = 0; i < numedges; i++) { /* struct springs */
- BLI_edgehash_insert(edgehash, MIN2(medge[i].v1, medge[i].v2), MAX2(medge[i].v2, medge[i].v1), NULL);
+ BLI_edgehash_reinsert(edgehash, medge[i].v1, medge[i].v2, NULL);
}
for (i = 0; i < numfaces; i++) { /* edge springs */
if (mface[i].v4) {
- BLI_edgehash_insert(edgehash, MIN2(mface[i].v1, mface[i].v3), MAX2(mface[i].v3, mface[i].v1), NULL);
+ BLI_edgehash_reinsert(edgehash, mface[i].v1, mface[i].v3, NULL);
- BLI_edgehash_insert(edgehash, MIN2(mface[i].v2, mface[i].v4), MAX2(mface[i].v2, mface[i].v4), NULL);
+ BLI_edgehash_reinsert(edgehash, mface[i].v2, mface[i].v4, NULL);
}
}
cloth->numsprings = struct_springs + shear_springs + bend_springs;
- if ( edgelist ) {
- for ( i = 0; i < numverts; i++ ) {
- BLI_linklist_free ( edgelist[i], NULL );
- }
-
- MEM_freeN ( edgelist );
- }
-
- cloth->edgehash = edgehash;
-
+ cloth_free_edgelist(edgelist, numverts);
+
+#if 0
if (G.debug_value > 0)
printf("avg_len: %f\n", clmd->sim_parms->avg_spring_len);
+#endif
return 1;
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 91a09bb8554..e3081b9e670 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -281,7 +281,7 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM
/* Decrease in magnitude of relative tangential velocity due to coulomb friction
* in original formula "magrelVel" should be the "change of relative velocity in normal direction" */
- magtangent = min_ff(clmd->coll_parms->friction * 0.01f * magrelVel, sqrtf(dot_v3v3(vrel_t_pre, vrel_t_pre)));
+ magtangent = min_ff(clmd->coll_parms->friction * 0.01f * magrelVel, len_v3(vrel_t_pre));
/* Apply friction impulse. */
if ( magtangent > ALMOST_ZERO ) {
@@ -865,8 +865,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
- // check for adjacent points (i must be smaller j)
- if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) {
+ if (BLI_edgehash_haskey(cloth->edgehash, i, j)) {
continue;
}
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 7e878e86c1e..578fa5d348d 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -972,9 +972,6 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
if (ibuf->rect_float)
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
- /* persistent draw */
- hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */
-
for (i = 0; i < 256; i++) {
x = (int)(0.5f + x1 + (float)i * (x2 - x1) / 255.0f);
y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f);
@@ -1260,6 +1257,7 @@ void BKE_color_managed_view_settings_init(ColorManagedViewSettings *settings)
* for now use NONE to be compatible with all current files
*/
BLI_strncpy(settings->view_transform, "Default", sizeof(settings->view_transform));
+ BLI_strncpy(settings->look, "None", sizeof(settings->look));
settings->gamma = 1.0f;
settings->exposure = 0.0f;
@@ -1268,6 +1266,7 @@ void BKE_color_managed_view_settings_init(ColorManagedViewSettings *settings)
void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings,
const ColorManagedViewSettings *settings)
{
+ BLI_strncpy(new_settings->look, settings->look, sizeof(new_settings->look));
BLI_strncpy(new_settings->view_transform, settings->view_transform, sizeof(new_settings->view_transform));
new_settings->flag = settings->flag;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index eda770ddf30..1f892432d80 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -69,6 +69,7 @@
#include "BKE_bvhutils.h"
#include "BKE_camera.h"
#include "BKE_constraint.h"
+#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h" /* for geometry targets */
@@ -448,7 +449,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
{
Lattice *lt = (Lattice *)ob->data;
- DispList *dl = BKE_displist_find(&ob->disp, DL_VERTS);
+ DispList *dl = ob->curve_cache ? BKE_displist_find(&ob->curve_cache->disp, DL_VERTS) : NULL;
float *co = dl ? dl->verts : NULL;
BPoint *bp = lt->def;
@@ -1163,10 +1164,10 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
*/
/* only happens on reload file, but violates depsgraph still... fix! */
- if (cu->path == NULL || cu->path->data == NULL)
+ if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
- if (cu->path && cu->path->data) {
+ if (ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
float quat[4];
if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
/* animated position along curve depending on time */
@@ -1933,10 +1934,8 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa
if (VALID_CONS_TARGET(ct)) {
/* special exception for curves - depsgraph issues */
if (ct->tar->type == OB_CURVE) {
- Curve *cu = ct->tar->data;
-
/* this check is to make sure curve objects get updated on file load correctly.*/
- if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+ if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
}
@@ -3009,14 +3008,12 @@ static void clampto_flush_tars(bConstraint *con, ListBase *list, short nocopy)
static void clampto_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
if (VALID_CONS_TARGET(ct)) {
- Curve *cu = ct->tar->data;
-
/* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
/* only happens on reload file, but violates depsgraph still... fix! */
- if (cu->path == NULL || cu->path->data == NULL)
+ if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
}
@@ -3034,7 +3031,6 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
/* only evaluate if there is a target and it is a curve */
if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) {
- Curve *cu = data->tar->data;
float obmat[4][4], ownLoc[3];
float curveMin[3], curveMax[3];
float targetMatrix[4][4] = MAT4_UNITY;
@@ -3047,7 +3043,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
BKE_object_minmax(ct->tar, curveMin, curveMax, TRUE);
/* get targetmatrix */
- if (cu->path && cu->path->data) {
+ if (data->tar->curve_cache && data->tar->curve_cache->path && data->tar->curve_cache->path->data) {
float vec[4], dir[3], totmat[4][4];
float curvetime;
short clamp_axis;
@@ -3312,6 +3308,14 @@ static void shrinkwrap_id_looper(bConstraint *con, ConstraintIDFunc func, void *
func(con, (ID **)&data->target, FALSE, userdata);
}
+static void shrinkwrap_new_data(void *cdata)
+{
+ bShrinkwrapConstraint *data = (bShrinkwrapConstraint *)cdata;
+
+ data->projAxis = OB_POSZ;
+ data->projAxisSpace = CONSTRAINT_SPACE_LOCAL;
+}
+
static int shrinkwrap_get_tars(bConstraint *con, ListBase *list)
{
if (con && list) {
@@ -3343,24 +3347,14 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) ) {
- int fail = FALSE;
+ bool fail = false;
float co[3] = {0.0f, 0.0f, 0.0f};
- float no[3] = {0.0f, 0.0f, 0.0f};
- float dist;
SpaceTransform transform;
DerivedMesh *target = object_get_derived_final(ct->tar);
- BVHTreeRayHit hit;
- BVHTreeNearest nearest;
BVHTreeFromMesh treeData = {NULL};
- nearest.index = -1;
- nearest.dist = FLT_MAX;
-
- hit.index = -1;
- hit.dist = 100000.0f; //TODO should use FLT_MAX.. but normal projection doenst yet supports it
-
unit_m4(ct->matrix);
if (target != NULL) {
@@ -3369,7 +3363,13 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
switch (scon->shrinkType) {
case MOD_SHRINKWRAP_NEAREST_SURFACE:
case MOD_SHRINKWRAP_NEAREST_VERTEX:
-
+ {
+ BVHTreeNearest nearest;
+ float dist;
+
+ nearest.index = -1;
+ nearest.dist = FLT_MAX;
+
if (scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX)
bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6);
else
@@ -3390,32 +3390,54 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
}
space_transform_invert(&transform, co);
break;
-
+ }
case MOD_SHRINKWRAP_PROJECT:
- if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) no[0] = 1.0f;
- if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f;
- if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) no[2] = 1.0f;
+ {
+ BVHTreeRayHit hit;
+
+ float mat[4][4];
+ float no[3] = {0.0f, 0.0f, 0.0f};
+
+ /* TODO should use FLT_MAX.. but normal projection doenst yet supports it */
+ hit.index = -1;
+ hit.dist = (scon->projLimit == 0.0f) ? 100000.0f : scon->projLimit;
+
+ switch (scon->projAxis) {
+ case OB_POSX: case OB_POSY: case OB_POSZ:
+ no[scon->projAxis - OB_POSX] = 1.0f;
+ break;
+ case OB_NEGX: case OB_NEGY: case OB_NEGZ:
+ no[scon->projAxis - OB_NEGX] = -1.0f;
+ break;
+ }
- if (dot_v3v3(no, no) < FLT_EPSILON) {
+ /* transform normal into requested space */
+ unit_m4(mat);
+ BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace);
+ invert_m4(mat);
+ mul_mat3_m4_v3(mat, no);
+
+ if (normalize_v3(no) < FLT_EPSILON) {
fail = TRUE;
break;
}
-
- normalize_v3(no);
-
-
+
bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6);
if (treeData.tree == NULL) {
fail = TRUE;
break;
}
+
- if (normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE) {
+ if (BKE_shrinkwrap_project_normal(0, co, no, &transform, treeData.tree, &hit,
+ treeData.raycast_callback, &treeData) == false)
+ {
fail = TRUE;
break;
}
copy_v3_v3(co, hit.co);
break;
+ }
}
free_bvhtree_from_mesh(&treeData);
@@ -3452,7 +3474,7 @@ static bConstraintTypeInfo CTI_SHRINKWRAP = {
NULL, /* free data */
shrinkwrap_id_looper, /* id looper */
NULL, /* copy data */
- NULL, /* new data */
+ shrinkwrap_new_data, /* new data */
shrinkwrap_get_tars, /* get constraint targets */
shrinkwrap_flush_tars, /* flush constraint targets */
shrinkwrap_get_tarmat, /* get a target matrix */
@@ -3650,14 +3672,12 @@ static void splineik_flush_tars(bConstraint *con, ListBase *list, short nocopy)
static void splineik_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
if (VALID_CONS_TARGET(ct)) {
- Curve *cu = ct->tar->data;
-
/* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
/* only happens on reload file, but violates depsgraph still... fix! */
- if (cu->path == NULL || cu->path->data == NULL)
+ if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
}
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 622b4f6df5a..2eb763831e4 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -198,8 +198,7 @@ void CTX_store_free_list(ListBase *contexts)
{
bContextStore *ctx;
- while ((ctx = contexts->first)) {
- BLI_remlink(contexts, ctx);
+ while ((ctx = BLI_pophead(contexts))) {
CTX_store_free(ctx);
}
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 2285d7d8dc0..e255732d3fb 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -145,7 +145,6 @@ void BKE_curve_editNurb_free(Curve *cu)
void BKE_curve_free(Curve *cu)
{
BKE_nurbList_free(&cu->nurb);
- BLI_freelistN(&cu->bev);
BKE_displist_free(&cu->disp);
BKE_curve_editfont_free(cu);
@@ -161,8 +160,6 @@ void BKE_curve_free(Curve *cu)
MEM_freeN(cu->strinfo);
if (cu->bb)
MEM_freeN(cu->bb);
- if (cu->path)
- free_path(cu->path);
if (cu->tb)
MEM_freeN(cu->tb);
}
@@ -229,8 +226,6 @@ Curve *BKE_curve_copy(Curve *cu)
if (cun->key) cun->key->from = (ID *)cun;
cun->disp.first = cun->disp.last = NULL;
- cun->bev.first = cun->bev.last = NULL;
- cun->path = NULL;
cun->editnurb = NULL;
cun->editfont = NULL;
@@ -372,62 +367,76 @@ void BKE_curve_type_test(Object *ob)
BKE_curve_curve_dimension_update((Curve *)ob->data);
}
-void BKE_curve_texspace_calc(Curve *cu)
+void BKE_curve_boundbox_calc(Curve *cu, float r_loc[3], float r_size[3])
{
- DispList *dl;
BoundBox *bb;
- float *fp, min[3], max[3];
- int tot, do_it = FALSE;
+ float min[3], max[3];
+ float mloc[3], msize[3];
- if (cu->bb == NULL)
- cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+ if (cu->bb == NULL) cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
bb = cu->bb;
+ if (!r_loc) r_loc = mloc;
+ if (!r_size) r_size = msize;
+
INIT_MINMAX(min, max);
+ BKE_displist_minmax(&cu->disp, min, max);
+ mid_v3_v3v3(r_loc, min, max);
- dl = cu->disp.first;
- while (dl) {
- tot = ELEM(dl->type, DL_INDEX3, DL_INDEX4) ? dl->nr : dl->nr * dl->parts;
+ r_size[0] = (max[0] - min[0]) / 2.0f;
+ r_size[1] = (max[1] - min[1]) / 2.0f;
+ r_size[2] = (max[2] - min[2]) / 2.0f;
- if (tot) do_it = TRUE;
- fp = dl->verts;
- while (tot--) {
- minmax_v3v3_v3(min, max, fp);
- fp += 3;
- }
- dl = dl->next;
- }
+ BKE_boundbox_init_from_minmax(bb, min, max);
- if (do_it == FALSE) {
- min[0] = min[1] = min[2] = -1.0f;
- max[0] = max[1] = max[2] = 1.0f;
- }
+ bb->flag &= ~BOUNDBOX_DIRTY;
+}
- BKE_boundbox_init_from_minmax(bb, min, max);
+BoundBox *BKE_curve_boundbox_get(Object *ob)
+{
+ Curve *cu = ob->data;
- if (cu->texflag & CU_AUTOSPACE) {
- mid_v3_v3v3(cu->loc, min, max);
- cu->size[0] = (max[0] - min[0]) / 2.0f;
- cu->size[1] = (max[1] - min[1]) / 2.0f;
- cu->size[2] = (max[2] - min[2]) / 2.0f;
+ if (ob->bb)
+ return ob->bb;
- zero_v3(cu->rot);
+ if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_curve_texspace_calc(cu);
+ }
- if (cu->size[0] == 0.0f) cu->size[0] = 1.0f;
- else if (cu->size[0] > 0.0f && cu->size[0] < 0.00001f) cu->size[0] = 0.00001f;
- else if (cu->size[0] < 0.0f && cu->size[0] > -0.00001f) cu->size[0] = -0.00001f;
+ return cu->bb;
+}
- if (cu->size[1] == 0.0f) cu->size[1] = 1.0f;
- else if (cu->size[1] > 0.0f && cu->size[1] < 0.00001f) cu->size[1] = 0.00001f;
- else if (cu->size[1] < 0.0f && cu->size[1] > -0.00001f) cu->size[1] = -0.00001f;
+void BKE_curve_texspace_calc(Curve *cu)
+{
+ float loc[3], size[3];
+ int a;
- if (cu->size[2] == 0.0f) cu->size[2] = 1.0f;
- else if (cu->size[2] > 0.0f && cu->size[2] < 0.00001f) cu->size[2] = 0.00001f;
- else if (cu->size[2] < 0.0f && cu->size[2] > -0.00001f) cu->size[2] = -0.00001f;
+ BKE_curve_boundbox_calc(cu, loc, size);
+ if (cu->texflag & CU_AUTOSPACE) {
+ for (a = 0; a < 3; a++) {
+ if (size[a] == 0.0f) size[a] = 1.0f;
+ else if (size[a] > 0.0f && size[a] < 0.00001f) size[a] = 0.00001f;
+ else if (size[a] < 0.0f && size[a] > -0.00001f) size[a] = -0.00001f;
+ }
+
+ copy_v3_v3(cu->loc, loc);
+ copy_v3_v3(cu->size, size);
+ zero_v3(cu->rot);
}
}
+void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_rot[3], float r_size[3])
+{
+ if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_curve_texspace_calc(cu);
+ }
+
+ if (r_loc) copy_v3_v3(r_loc, cu->loc);
+ if (r_rot) copy_v3_v3(r_rot, cu->rot);
+ if (r_size) copy_v3_v3(r_size, cu->size);
+}
+
int BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
{
Nurb *nu;
@@ -1586,10 +1595,10 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, int forRende
dl = bevdisp.first;
}
else {
- dl = cu->bevobj->disp.first;
+ dl = cu->bevobj->curve_cache ? cu->bevobj->curve_cache->disp.first : NULL;
if (dl == NULL) {
BKE_displist_make_curveTypes(scene, cu->bevobj, 0);
- dl = cu->bevobj->disp.first;
+ dl = cu->bevobj->curve_cache->disp.first;
}
}
@@ -1845,15 +1854,15 @@ static bool bevelinside(BevList *bl1, BevList *bl2)
}
-struct bevelsort {
- float left;
+struct BevelSort {
BevList *bl;
+ float left;
int dir;
};
static int vergxcobev(const void *a1, const void *a2)
{
- const struct bevelsort *x1 = a1, *x2 = a2;
+ const struct BevelSort *x1 = a1, *x2 = a2;
if (x1->left > x2->left)
return 1;
@@ -2372,12 +2381,23 @@ static void make_bevel_list_2D(BevList *bl)
/* note: bevp->dir and bevp->quat are not needed for beveling but are
* used when making a path from a 2D curve, therefor they need to be set - Campbell */
- BevPoint *bevp2 = (BevPoint *)(bl + 1);
- BevPoint *bevp1 = bevp2 + (bl->nr - 1);
- BevPoint *bevp0 = bevp1 - 1;
+ BevPoint *bevp0, *bevp1, *bevp2;
int nr;
- nr = bl->nr;
+ if (bl->poly != -1) {
+ bevp2 = (BevPoint *)(bl + 1);
+ bevp1 = bevp2 + (bl->nr - 1);
+ bevp0 = bevp1 - 1;
+ nr = bl->nr;
+ }
+ else {
+ bevp0 = (BevPoint *)(bl + 1);
+ bevp1 = bevp0 + 1;
+ bevp2 = bevp1 + 1;
+
+ nr = bl->nr - 2;
+ }
+
while (nr--) {
const float x1 = bevp1->vec[0] - bevp0->vec[0];
const float x2 = bevp1->vec[0] - bevp2->vec[0];
@@ -2399,15 +2419,23 @@ static void make_bevel_list_2D(BevList *bl)
/* correct non-cyclic cases */
if (bl->poly == -1) {
- BevPoint *bevp = (BevPoint *)(bl + 1);
- bevp1 = bevp + 1;
- bevp->sina = bevp1->sina;
- bevp->cosa = bevp1->cosa;
+ BevPoint *bevp;
+ float angle;
+
+ /* first */
+ bevp = (BevPoint *)(bl + 1);
+ angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+ bevp->sina = sinf(angle);
+ bevp->cosa = cosf(angle);
+ vec_to_quat(bevp->quat, bevp->dir, 5, 1);
+
+ /* last */
bevp = (BevPoint *)(bl + 1);
bevp += (bl->nr - 1);
- bevp1 = bevp - 1;
- bevp->sina = bevp1->sina;
- bevp->cosa = bevp1->cosa;
+ angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+ bevp->sina = sinf(angle);
+ bevp->cosa = cosf(angle);
+ vec_to_quat(bevp->quat, bevp->dir, 5, 1);
}
}
@@ -2428,7 +2456,7 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl)
}
}
-void BKE_curve_bevelList_make(Object *ob)
+void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
{
/*
* - convert all curves to polys, with indication of resol and flags for double-vertices
@@ -2443,28 +2471,27 @@ void BKE_curve_bevelList_make(Object *ob)
BevList *bl, *blnew, *blnext;
BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
float min, inp;
- struct bevelsort *sortdata, *sd, *sd1;
+ struct BevelSort *sortdata, *sd, *sd1;
int a, b, nr, poly, resolu = 0, len = 0;
int do_tilt, do_radius, do_weight;
int is_editmode = 0;
+ ListBase *bev;
/* this function needs an object, because of tflag and upflag */
cu = ob->data;
+ bev = &ob->curve_cache->bev;
+
/* do we need to calculate the radius for each point? */
/* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */
/* STEP 1: MAKE POLYS */
- BLI_freelistN(&(cu->bev));
+ BLI_freelistN(&(ob->curve_cache->bev));
+ nu = nurbs->first;
if (cu->editnurb && ob->type != OB_FONT) {
- ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- nu = nurbs->first;
is_editmode = 1;
}
- else {
- nu = cu->nurb.first;
- }
for (; nu; nu = nu->next) {
@@ -2480,12 +2507,12 @@ void BKE_curve_bevelList_make(Object *ob)
* enforced in the UI but can go wrong possibly */
if (!BKE_nurb_check_valid_u(nu)) {
bl = MEM_callocN(sizeof(BevList) + 1 * sizeof(BevPoint), "makeBevelList1");
- BLI_addtail(&(cu->bev), bl);
+ BLI_addtail(bev, bl);
bl->nr = 0;
bl->charidx = nu->charidx;
}
else {
- if (G.is_rendering && cu->resolu_ren != 0)
+ if (for_render && cu->resolu_ren != 0)
resolu = cu->resolu_ren;
else
resolu = nu->resolu;
@@ -2493,7 +2520,7 @@ void BKE_curve_bevelList_make(Object *ob)
if (nu->type == CU_POLY) {
len = nu->pntsu;
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2");
- BLI_addtail(&(cu->bev), bl);
+ BLI_addtail(bev, bl);
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
bl->nr = len;
@@ -2520,7 +2547,7 @@ void BKE_curve_bevelList_make(Object *ob)
/* in case last point is not cyclic */
len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1;
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints");
- BLI_addtail(&(cu->bev), bl);
+ BLI_addtail(bev, bl);
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
bl->charidx = nu->charidx;
@@ -2613,7 +2640,7 @@ void BKE_curve_bevelList_make(Object *ob)
len = (resolu * SEGMENTSU(nu));
bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3");
- BLI_addtail(&(cu->bev), bl);
+ BLI_addtail(bev, bl);
bl->nr = len;
bl->dupe_nr = 0;
bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1;
@@ -2635,12 +2662,19 @@ void BKE_curve_bevelList_make(Object *ob)
}
/* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */
- bl = cu->bev.first;
+ bl = bev->first;
while (bl) {
if (bl->nr) { /* null bevel items come from single points */
+ bool is_cyclic = bl->poly != -1;
nr = bl->nr;
- bevp1 = (BevPoint *)(bl + 1);
- bevp0 = bevp1 + (nr - 1);
+ if (is_cyclic) {
+ bevp1 = (BevPoint *)(bl + 1);
+ bevp0 = bevp1 + (nr - 1);
+ }
+ else {
+ bevp0 = (BevPoint *)(bl + 1);
+ bevp1 = bevp0 + 1;
+ }
nr--;
while (nr--) {
if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) {
@@ -2657,7 +2691,7 @@ void BKE_curve_bevelList_make(Object *ob)
}
bl = bl->next;
}
- bl = cu->bev.first;
+ bl = bev->first;
while (bl) {
blnext = bl->next;
if (bl->nr && bl->dupe_nr) {
@@ -2665,8 +2699,8 @@ void BKE_curve_bevelList_make(Object *ob)
blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4");
memcpy(blnew, bl, sizeof(BevList));
blnew->nr = 0;
- BLI_remlink(&(cu->bev), bl);
- BLI_insertlinkbefore(&(cu->bev), blnext, blnew); /* to make sure bevlijst is tuned with nurblist */
+ BLI_remlink(bev, bl);
+ BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */
bevp0 = (BevPoint *)(bl + 1);
bevp1 = (BevPoint *)(blnew + 1);
nr = bl->nr;
@@ -2685,7 +2719,7 @@ void BKE_curve_bevelList_make(Object *ob)
}
/* STEP 3: POLYS COUNT AND AUTOHOLE */
- bl = cu->bev.first;
+ bl = bev->first;
poly = 0;
while (bl) {
if (bl->nr && bl->poly >= 0) {
@@ -2698,8 +2732,8 @@ void BKE_curve_bevelList_make(Object *ob)
/* find extreme left points, also test (turning) direction */
if (poly > 0) {
- sd = sortdata = MEM_mallocN(sizeof(struct bevelsort) * poly, "makeBevelList5");
- bl = cu->bev.first;
+ sd = sortdata = MEM_mallocN(sizeof(struct BevelSort) * poly, "makeBevelList5");
+ bl = bev->first;
while (bl) {
if (bl->poly > 0) {
@@ -2740,7 +2774,7 @@ void BKE_curve_bevelList_make(Object *ob)
bl = bl->next;
}
- qsort(sortdata, poly, sizeof(struct bevelsort), vergxcobev);
+ qsort(sortdata, poly, sizeof(struct BevelSort), vergxcobev);
sd = sortdata + 1;
for (a = 1; a < poly; a++, sd++) {
@@ -2779,7 +2813,7 @@ void BKE_curve_bevelList_make(Object *ob)
/* STEP 4: 2D-COSINES or 3D ORIENTATION */
if ((cu->flag & CU_3D) == 0) {
/* 2D Curves */
- for (bl = cu->bev.first; bl; bl = bl->next) {
+ for (bl = bev->first; bl; bl = bl->next) {
if (bl->nr < 2) {
/* do nothing */
}
@@ -2793,7 +2827,7 @@ void BKE_curve_bevelList_make(Object *ob)
}
else {
/* 3D Curves */
- for (bl = cu->bev.first; bl; bl = bl->next) {
+ for (bl = bev->first; bl; bl = bl->next) {
if (bl->nr < 2) {
/* do nothing */
}
@@ -3057,47 +3091,78 @@ void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */
calchandlesNurb_intern(nu, FALSE);
}
+/* similar to BKE_nurb_handle_calc but for curves and
+ * figures out the previous and next for us */
+void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
+{
+ if (nu->pntsu > 1) {
+ BezTriple *prev = BKE_nurb_bezt_get_prev(nu, bezt);
+ BezTriple *next = BKE_nurb_bezt_get_next(nu, bezt);
+ BKE_nurb_handle_calc(bezt, prev, next, 0);
+ }
+}
-void BKE_nurb_handles_test(Nurb *nu)
+/**
+ * Use when something has changed handle positions.
+ *
+ * The caller needs to recalculate handles.
+ */
+void BKE_nurb_bezt_handle_test(BezTriple *bezt, const bool use_handle)
{
- /* use when something has changed with handles.
- * it treats all BezTriples with the following rules:
- * PHASE 1: do types have to be altered?
- * Auto handles: become aligned when selection status is NOT(000 || 111)
- * Vector handles: become 'nothing' when (one half selected AND other not)
- * PHASE 2: recalculate handles
- */
- BezTriple *bezt;
- short flag, a;
+ short flag = 0;
- if (nu->type != CU_BEZIER) return;
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- flag = 0;
- if (bezt->f1 & SELECT)
- flag++;
- if (bezt->f2 & SELECT)
- flag += 2;
- if (bezt->f3 & SELECT)
- flag += 4;
+ if (use_handle) {
+ if (bezt->f1 & SELECT) flag |= SEL_F1;
+ if (bezt->f2 & SELECT) flag |= SEL_F2;
+ if (bezt->f3 & SELECT) flag |= SEL_F3;
+ }
+ else {
+ flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
+ }
- if (!(flag == 0 || flag == 7) ) {
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) { /* auto */
- bezt->h1 = HD_ALIGN;
- }
- if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { /* auto */
- bezt->h2 = HD_ALIGN;
- }
+ /* check for partial selection */
+ if (!ELEM(flag, 0, SEL_F1 | SEL_F2 | SEL_F3)) {
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
+ bezt->h1 = HD_ALIGN;
+ }
+ if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
+ bezt->h2 = HD_ALIGN;
+ }
- if (bezt->h1 == HD_VECT) { /* vector */
- if (flag < 4) bezt->h1 = 0;
+ if (bezt->h1 == HD_VECT) {
+ if ((!(flag & SEL_F1)) != (!(flag & SEL_F2))) {
+ bezt->h1 = HD_FREE;
}
- if (bezt->h2 == HD_VECT) { /* vector */
- if (flag > 3) bezt->h2 = 0;
+ }
+ if (bezt->h2 == HD_VECT) {
+ if ((!(flag & SEL_F3)) != (!(flag & SEL_F2))) {
+ bezt->h2 = HD_FREE;
}
}
+ }
+
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
+
+}
+
+void BKE_nurb_handles_test(Nurb *nu, const bool use_handle)
+{
+ BezTriple *bezt;
+ short a;
+
+ if (nu->type != CU_BEZIER)
+ return;
+
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ BKE_nurb_bezt_handle_test(bezt, use_handle);
bezt++;
}
@@ -3107,9 +3172,11 @@ void BKE_nurb_handles_test(Nurb *nu)
void BKE_nurb_handles_autocalc(Nurb *nu, int flag)
{
/* checks handle coordinates and calculates type */
+ const float eps = 0.0001f;
+ const float eps_sq = eps * eps;
BezTriple *bezt2, *bezt1, *bezt0;
- int i, align, leftsmall, rightsmall;
+ int i;
if (nu == NULL || nu->bezt == NULL)
return;
@@ -3120,54 +3187,54 @@ void BKE_nurb_handles_autocalc(Nurb *nu, int flag)
i = nu->pntsu;
while (i--) {
- align = leftsmall = rightsmall = 0;
+ bool align = false, leftsmall = false, rightsmall = false;
/* left handle: */
if (flag == 0 || (bezt1->f1 & flag) ) {
- bezt1->h1 = 0;
+ bezt1->h1 = HD_FREE;
/* distance too short: vectorhandle */
- if (len_v3v3(bezt1->vec[1], bezt0->vec[1]) < 0.0001f) {
+ if (len_squared_v3v3(bezt1->vec[1], bezt0->vec[1]) < eps_sq) {
bezt1->h1 = HD_VECT;
- leftsmall = 1;
+ leftsmall = true;
}
else {
/* aligned handle? */
- if (dist_to_line_v2(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001f) {
- align = 1;
+ if (dist_to_line_v2(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < eps) {
+ align = true;
bezt1->h1 = HD_ALIGN;
}
/* or vector handle? */
- if (dist_to_line_v2(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001f)
+ if (dist_to_line_v2(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < eps)
bezt1->h1 = HD_VECT;
}
}
/* right handle: */
if (flag == 0 || (bezt1->f3 & flag) ) {
- bezt1->h2 = 0;
+ bezt1->h2 = HD_FREE;
/* distance too short: vectorhandle */
- if (len_v3v3(bezt1->vec[1], bezt2->vec[1]) < 0.0001f) {
+ if (len_squared_v3v3(bezt1->vec[1], bezt2->vec[1]) < eps_sq) {
bezt1->h2 = HD_VECT;
- rightsmall = 1;
+ rightsmall = true;
}
else {
/* aligned handle? */
if (align) bezt1->h2 = HD_ALIGN;
/* or vector handle? */
- if (dist_to_line_v2(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001f)
+ if (dist_to_line_v2(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < eps)
bezt1->h2 = HD_VECT;
}
}
if (leftsmall && bezt1->h2 == HD_ALIGN)
- bezt1->h2 = 0;
+ bezt1->h2 = HD_FREE;
if (rightsmall && bezt1->h1 == HD_ALIGN)
- bezt1->h1 = 0;
+ bezt1->h1 = HD_FREE;
/* undesired combination: */
if (bezt1->h1 == HD_ALIGN && bezt1->h2 == HD_VECT)
- bezt1->h1 = 0;
+ bezt1->h1 = HD_FREE;
if (bezt1->h2 == HD_ALIGN && bezt1->h1 == HD_VECT)
- bezt1->h2 = 0;
+ bezt1->h2 = HD_FREE;
bezt0 = bezt1;
bezt1 = bezt2;
@@ -3271,6 +3338,33 @@ void BKE_nurbList_handles_set(ListBase *editnurb, short code)
}
}
+void BKE_nurbList_flag_set(ListBase *editnurb, short flag)
+{
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ while (a--) {
+ bezt->f1 = bezt->f2 = bezt->f3 = flag;
+ bezt++;
+ }
+ }
+ else {
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ bp->f1 = flag;
+ bp++;
+ }
+ }
+ }
+}
+
void BKE_nurb_direction_switch(Nurb *nu)
{
BezTriple *bezt1, *bezt2;
@@ -3382,7 +3476,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
}
-float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3]
+float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *numVerts_r))[3]
{
int i, numVerts = *numVerts_r = BKE_nurbList_verts_count(lb);
float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3411,7 +3505,7 @@ float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r
return cos;
}
-void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3])
+void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3])
{
float *co = vertexCos[0];
Nurb *nu;
@@ -3439,7 +3533,7 @@ void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos
}
}
-float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))[3]
+float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3]
{
int i, numVerts = BKE_nurbList_verts_count(lb);
float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3470,7 +3564,7 @@ float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))
return cos;
}
-void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key)
+void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key)
{
Nurb *nu;
int i;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index d69ec6a9597..8a74f4719d5 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -45,11 +45,12 @@
#include "DNA_ID.h"
#include "BLI_utildefines.h"
-#include "BLI_blenlib.h"
-#include "BLI_linklist.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
#include "BLI_math.h"
#include "BLI_mempool.h"
#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
#include "BLF_translation.h"
@@ -256,7 +257,7 @@ static void layerInterp_mdeformvert(void **sources, const float *weights,
/* if this def_nr is not in the list, add it */
if (!node) {
- struct MDeformWeight_Link *tmp_dwlink = MEM_mallocN(sizeof(*tmp_dwlink), __func__);
+ struct MDeformWeight_Link *tmp_dwlink = alloca(sizeof(*tmp_dwlink));
tmp_dwlink->dw.def_nr = dw->def_nr;
tmp_dwlink->dw.weight = weight;
@@ -286,12 +287,9 @@ static void layerInterp_mdeformvert(void **sources, const float *weights,
}
if (totweight) {
- struct MDeformWeight_Link *node_next;
dvert->totweight = totweight;
- for (i = 0, node = dest_dwlink; node; node = node_next, i++) {
- node_next = node->next;
+ for (i = 0, node = dest_dwlink; node; node = node->next, i++) {
dvert->dw[i] = node->dw;
- MEM_freeN(node);
}
}
else {
@@ -973,6 +971,11 @@ static void layerDefault_mcol(void *data, int count)
}
}
+static void layerDefault_origindex(void *data, int count)
+{
+ fill_vn_i((int *)data, count, ORIGINDEX_NONE);
+}
+
static void layerInterp_bweight(void **sources, const float *weights,
const float *UNUSED(sub_weights), int count, void *dest)
{
@@ -1079,7 +1082,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MCol) * 4, "MCol", 4, N_("Col"), NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
/* 7: CD_ORIGINDEX */
- {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_origindex},
/* 8: CD_NORMAL */
/* 3 floats per normal vector */
{sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@@ -1217,6 +1220,16 @@ const CustomDataMask CD_MASK_BMESH =
const CustomDataMask CD_MASK_FACECORNERS =
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL;
+const CustomDataMask CD_MASK_EVERYTHING =
+ CD_MASK_MVERT | CD_MASK_MSTICKY /* DEPRECATED */ | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
+ CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT |
+ CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_MLOOPCOL | CD_MASK_TANGENT | CD_MASK_MDISPS | CD_MASK_PREVIEW_MCOL | CD_MASK_CLOTH_ORCO | CD_MASK_RECAST |
+ /* BMESH ONLY START */
+ CD_MASK_MPOLY | CD_MASK_MLOOP | CD_MASK_SHAPE_KEYINDEX | CD_MASK_SHAPEKEY | CD_MASK_BWEIGHT | CD_MASK_CREASE |
+ CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_BM_ELEM_PYPTR |
+ /* BMESH ONLY END */
+ CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
static const LayerTypeInfo *layerType_getInfo(int type)
{
@@ -1305,7 +1318,7 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest,
if (lastflag & CD_FLAG_NOCOPY) continue;
else if (!(mask & CD_TYPE_AS_MASK(type))) continue;
- else if (number < CustomData_number_of_layers(dest, type)) continue;
+ else if (CustomData_get_layer_named(dest, type, layer->name)) continue;
switch (alloctype) {
case CD_ASSIGN:
@@ -1449,8 +1462,9 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha
int i;
for (i = 0; i < data->totlayer; ++i)
- if (data->layers[i].type == type && strcmp(data->layers[i].name, name) == 0)
- return i;
+ if (data->layers[i].type == type)
+ if (strcmp(data->layers[i].name, name) == 0)
+ return i;
return -1;
}
@@ -1939,13 +1953,61 @@ void CustomData_copy_elements(int type, void *source, void *dest, int count)
memcpy(dest, source, typeInfo->size * count);
}
+static void CustomData_copy_data_layer(const CustomData *source, CustomData *dest,
+ int src_i, int dest_i,
+ int source_index, int dest_index, int count) {
+ const LayerTypeInfo *typeInfo;
+ int src_offset;
+ int dest_offset;
+
+ char *src_data = source->layers[src_i].data;
+ char *dest_data = dest->layers[dest_i].data;
+
+ typeInfo = layerType_getInfo(source->layers[src_i].type);
+
+ src_offset = source_index * typeInfo->size;
+ dest_offset = dest_index * typeInfo->size;
+
+ if (!src_data || !dest_data) {
+ if (!(src_data == NULL && dest_data == NULL)) {
+ printf("%s: warning null data for %s type (%p --> %p), skipping\n",
+ __func__, layerType_getName(source->layers[src_i].type),
+ (void *)src_data, (void *)dest_data);
+ }
+ return;
+ }
+
+ if (typeInfo->copy)
+ typeInfo->copy(src_data + src_offset,
+ dest_data + dest_offset,
+ count);
+ else
+ memcpy(dest_data + dest_offset,
+ src_data + src_offset,
+ count * typeInfo->size);
+}
+
+void CustomData_copy_data_named(const CustomData *source, CustomData *dest,
+ int source_index, int dest_index, int count)
+{
+ int src_i, dest_i;
+
+ /* copies a layer at a time */
+ for (src_i = 0; src_i < source->totlayer; ++src_i) {
+
+ dest_i = CustomData_get_named_layer_index(dest, source->layers[src_i].type, source->layers[src_i].name);
+
+ /* if we found a matching layer, copy the data */
+ if (dest_i > -1) {
+ CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
+ }
+ }
+}
+
void CustomData_copy_data(const CustomData *source, CustomData *dest,
int source_index, int dest_index, int count)
{
- const LayerTypeInfo *typeInfo;
int src_i, dest_i;
- int src_offset;
- int dest_offset;
/* copies a layer at a time */
dest_i = 0;
@@ -1963,32 +2025,8 @@ void CustomData_copy_data(const CustomData *source, CustomData *dest,
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
- char *src_data = source->layers[src_i].data;
- char *dest_data = dest->layers[dest_i].data;
-
- typeInfo = layerType_getInfo(source->layers[src_i].type);
-
- src_offset = source_index * typeInfo->size;
- dest_offset = dest_index * typeInfo->size;
-
- if (!src_data || !dest_data) {
- if (src_data != NULL && dest_data != NULL) {
- printf("%s: warning null data for %s type (%p --> %p), skipping\n",
- __func__, layerType_getName(source->layers[src_i].type),
- (void *)src_data, (void *)dest_data);
- }
- continue;
- }
+ CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
- if (typeInfo->copy)
- typeInfo->copy(src_data + src_offset,
- dest_data + dest_offset,
- count);
- else
- memcpy(dest_data + dest_offset,
- src_data + src_offset,
- count * typeInfo->size);
-
/* if there are multiple source & dest layers of the same type,
* we don't want to copy all source layers to the same dest, so
* increment dest_i
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 4ce06623bae..cb7b4a32feb 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -29,6 +29,7 @@
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -819,12 +820,26 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
}
+static void build_dag_group(DagForest *dag, DagNode *scenenode, Scene *scene, Group *group, short mask)
+{
+ GroupObject *go;
+
+ if (group->id.flag & LIB_DOIT)
+ return;
+
+ group->id.flag |= LIB_DOIT;
+
+ for (go = group->gobject.first; go; go = go->next) {
+ build_dag_object(dag, scenenode, scene, go->ob, mask);
+ if (go->ob->dup_group)
+ build_dag_group(dag, scenenode, scene, go->ob->dup_group, mask);
+ }
+}
+
DagForest *build_dag(Main *bmain, Scene *sce, short mask)
{
Base *base;
Object *ob;
- Group *group;
- GroupObject *go;
DagNode *node;
DagNode *scenenode;
DagForest *dag;
@@ -841,6 +856,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
/* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */
tag_main_idcode(bmain, ID_MA, FALSE);
tag_main_idcode(bmain, ID_LA, FALSE);
+ tag_main_idcode(bmain, ID_GR, FALSE);
/* add base node for scene. scene is always the first node in DAG */
scenenode = dag_add_node(dag, sce);
@@ -852,21 +868,11 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
build_dag_object(dag, scenenode, sce, ob, mask);
if (ob->proxy)
build_dag_object(dag, scenenode, sce, ob->proxy, mask);
-
- /* handled in next loop */
if (ob->dup_group)
- ob->dup_group->id.flag |= LIB_DOIT;
+ build_dag_group(dag, scenenode, sce, ob->dup_group, mask);
}
- /* add groups used in current scene objects */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (group->id.flag & LIB_DOIT) {
- for (go = group->gobject.first; go; go = go->next) {
- build_dag_object(dag, scenenode, sce, go->ob, mask);
- }
- group->id.flag &= ~LIB_DOIT;
- }
- }
+ tag_main_idcode(bmain, ID_GR, FALSE);
/* Now all relations were built, but we need to solve 1 exceptional case;
* When objects have multiple "parents" (for example parent + constraint working on same object)
@@ -1927,6 +1933,25 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
lib_id_recalc_data_tag(bmain, &ob->id);
}
+
+/* recursively update objects in groups, each group is done at most once */
+static void dag_group_update_flags(Main *bmain, Scene *scene, Group *group, const short do_time)
+{
+ GroupObject *go;
+
+ if (group->id.flag & LIB_DOIT)
+ return;
+
+ group->id.flag |= LIB_DOIT;
+
+ for (go = group->gobject.first; go; go = go->next) {
+ if (do_time)
+ dag_object_time_update_flags(bmain, scene, go->ob);
+ if (go->ob->dup_group)
+ dag_group_update_flags(bmain, scene, go->ob->dup_group, do_time);
+ }
+}
+
/* flag all objects that need recalc, for changes in time for example */
/* do_time: make this optional because undo resets objects to their animated locations without this */
void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const short do_time)
@@ -1937,6 +1962,8 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
GroupObject *go;
Scene *sce_iter;
+ tag_main_idcode(bmain, ID_GR, FALSE);
+
/* set ob flags where animated systems are */
for (SETLOOPER(scene, sce_iter, base)) {
ob = base->object;
@@ -1951,20 +1978,9 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
dag_object_time_update_flags(bmain, sce_iter, ob);
}
- /* handled in next loop */
+ /* recursively tag groups with LIB_DOIT, and update flags for objects */
if (ob->dup_group)
- ob->dup_group->id.flag |= LIB_DOIT;
- }
-
- if (do_time) {
- /* we do groups each once */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (group->id.flag & LIB_DOIT) {
- for (go = group->gobject.first; go; go = go->next) {
- dag_object_time_update_flags(bmain, scene, go->ob);
- }
- }
- }
+ dag_group_update_flags(bmain, scene, ob->dup_group, do_time);
}
for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
@@ -2048,6 +2064,26 @@ static void dag_current_scene_layers(Main *bmain, ListBase *lb)
}
}
+static void dag_group_on_visible_update(Group *group)
+{
+ GroupObject *go;
+
+ if (group->id.flag & LIB_DOIT)
+ return;
+
+ group->id.flag |= LIB_DOIT;
+
+ for (go = group->gobject.first; go; go = go->next) {
+ if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
+ go->ob->recalc |= OB_RECALC_DATA;
+ if (go->ob->proxy_from)
+ go->ob->recalc |= OB_RECALC_OB;
+
+ if (go->ob->dup_group)
+ dag_group_on_visible_update(go->ob->dup_group);
+ }
+}
+
void DAG_on_visible_update(Main *bmain, const short do_time)
{
ListBase listbase;
@@ -2061,8 +2097,6 @@ void DAG_on_visible_update(Main *bmain, const short do_time)
Scene *sce_iter;
Base *base;
Object *ob;
- Group *group;
- GroupObject *go;
DagNode *node;
unsigned int lay = dsl->layer, oblay;
@@ -2071,6 +2105,7 @@ void DAG_on_visible_update(Main *bmain, const short do_time)
* note armature poses or object matrices are preserved and do not
* require updates, so we skip those */
dag_scene_flush_layers(scene, lay);
+ tag_main_idcode(bmain, ID_GR, FALSE);
for (SETLOOPER(scene, sce_iter, base)) {
ob = base->object;
@@ -2080,23 +2115,14 @@ void DAG_on_visible_update(Main *bmain, const short do_time)
if ((oblay & lay) & ~scene->lay_updated) {
if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
ob->recalc |= OB_RECALC_DATA;
+ if (ob->proxy && (ob->proxy_group == NULL))
+ ob->proxy->recalc |= OB_RECALC_DATA;
if (ob->dup_group)
- ob->dup_group->id.flag |= LIB_DOIT;
+ dag_group_on_visible_update(ob->dup_group);
}
}
- for (group = bmain->group.first; group; group = group->id.next) {
- if (group->id.flag & LIB_DOIT) {
- for (go = group->gobject.first; go; go = go->next) {
- if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
- go->ob->recalc |= OB_RECALC_DATA;
- if (go->ob->proxy_from)
- go->ob->recalc |= OB_RECALC_OB;
- }
-
- group->id.flag &= ~LIB_DOIT;
- }
- }
+ tag_main_idcode(bmain, ID_GR, FALSE);
/* now tag update flags, to ensure deformers get calculated on redraw */
DAG_scene_update_flags(bmain, scene, lay, do_time);
@@ -2274,7 +2300,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
* so it should happen tracking-related constraints recalculation
* when camera is changing (sergey) */
if (sce->camera && &sce->camera->id == id) {
- MovieClip *clip = BKE_object_movieclip_get(sce, sce->camera, 1);
+ MovieClip *clip = BKE_object_movieclip_get(sce, sce->camera, true);
if (clip)
dag_id_flush_update(bmain, sce, &clip->id);
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 38a0b848339..6a89ca2cb84 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -43,6 +43,7 @@
#include "DNA_material_types.h"
#include "BLI_blenlib.h"
+#include "BLI_memarena.h"
#include "BLI_math.h"
#include "BLI_scanfill.h"
#include "BLI_utildefines.h"
@@ -62,8 +63,7 @@
#include "BLI_sys_types.h" // for intptr_t support
-static void boundbox_displist(Object *ob);
-static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase);
+static void boundbox_displist_object(Object *ob);
void BKE_displist_elem_free(DispList *dl)
{
@@ -82,11 +82,8 @@ void BKE_displist_free(ListBase *lb)
{
DispList *dl;
- dl = lb->first;
- while (dl) {
- BLI_remlink(lb, dl);
+ while ((dl = BLI_pophead(lb))) {
BKE_displist_elem_free(dl);
- dl = lb->first;
}
}
@@ -454,6 +451,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
ScanFillContext sf_ctx;
ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last;
ScanFillFace *sf_tri;
+ MemArena *sf_arena;
DispList *dlnew = NULL, *dl;
float *f1;
int colnr = 0, charidx = 0, cont = 1, tot, a, *index, nextcol = 0;
@@ -464,12 +462,14 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
if (dispbase->first == NULL)
return;
+ sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+
while (cont) {
cont = 0;
totvert = 0;
nextcol = 0;
- BLI_scanfill_begin(&sf_ctx);
+ BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
dl = dispbase->first;
while (dl) {
@@ -557,7 +557,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
BLI_addhead(to, dlnew);
}
- BLI_scanfill_end(&sf_ctx);
+ BLI_scanfill_end_arena(&sf_ctx, sf_arena);
if (nextcol) {
/* stay at current char but fill polys with next material */
@@ -570,6 +570,8 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
}
}
+ BLI_memarena_free(sf_arena);
+
/* do not free polys, needed for wireframe display */
}
@@ -667,10 +669,10 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
if (taperobj == NULL || taperobj->type != OB_CURVE)
return 1.0;
- dl = taperobj->disp.first;
+ dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL;
if (dl == NULL) {
BKE_displist_make_curveTypes(scene, taperobj, 0);
- dl = taperobj->disp.first;
+ dl = taperobj->curve_cache->disp.first;
}
if (dl) {
float minx, dx, *fp;
@@ -712,29 +714,28 @@ void BKE_displist_make_mball(Scene *scene, Object *ob)
if (!ob || ob->type != OB_MBALL)
return;
- /* XXX: mball stuff uses plenty of global variables
- * while this is unchanged updating during render is unsafe
- */
- if (G.is_rendering)
- return;
-
- BKE_displist_free(&(ob->disp));
+ if (ob->curve_cache) {
+ BKE_displist_free(&(ob->curve_cache->disp));
+ }
+ else {
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ }
if (ob->type == OB_MBALL) {
if (ob == BKE_mball_basis_find(scene, ob)) {
- BKE_mball_polygonize(scene, ob, &ob->disp);
+ BKE_mball_polygonize(scene, ob, &ob->curve_cache->disp, false);
BKE_mball_texspace_calc(ob);
- object_deform_mball(ob, &ob->disp);
+ object_deform_mball(ob, &ob->curve_cache->disp);
}
- }
- boundbox_displist(ob);
+ boundbox_displist_object(ob);
+ }
}
void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispbase)
{
- BKE_mball_polygonize(scene, ob, dispbase);
+ BKE_mball_polygonize(scene, ob, dispbase, true);
BKE_mball_texspace_calc(ob);
object_deform_mball(ob, dispbase);
@@ -742,7 +743,8 @@ void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispb
static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int renderResolution, int editmode)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
ModifierData *pretessellatePoint;
int required_mode;
@@ -780,18 +782,16 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int re
return pretessellatePoint;
}
-static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, int renderResolution,
- float (**originalVerts_r)[3],
- float (**deformedVerts_r)[3], int *numVerts_r)
+static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
+ int forRender, int renderResolution)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
ModifierData *pretessellatePoint;
Curve *cu = ob->data;
- ListBase *nurb = BKE_curve_nurbs_get(cu);
int numVerts = 0;
const int editmode = (!forRender && (cu->editnurb || cu->editfont));
ModifierApplyFlag app_flag = 0;
- float (*originalVerts)[3] = NULL;
float (*deformedVerts)[3] = NULL;
float *keyVerts = NULL;
int required_mode;
@@ -818,8 +818,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
* tilts, which is passed through in the modifier stack.
* this is also the reason curves do not use a virtual
* shape key modifier yet. */
- deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts);
- originalVerts = MEM_dupallocN(deformedVerts);
+ deformedVerts = BKE_curve_nurbs_keyVertexCos_get(nurb, keyVerts);
BLI_assert(BKE_nurbList_verts_count(nurb) == numVerts);
}
}
@@ -836,8 +835,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
continue;
if (!deformedVerts) {
- deformedVerts = BKE_curve_vertexCos_get(cu, nurb, &numVerts);
- originalVerts = MEM_dupallocN(deformedVerts);
+ deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts);
}
mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag);
@@ -847,17 +845,15 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
}
}
- if (deformedVerts)
- BK_curve_vertexCos_apply(cu, nurb, deformedVerts);
+ if (deformedVerts) {
+ BK_curve_nurbs_vertexCos_apply(nurb, deformedVerts);
+ MEM_freeN(deformedVerts);
+ }
if (keyVerts) /* these are not passed through modifier stack */
- BKE_curve_keyVertexTilts_apply(cu, nurb, keyVerts);
+ BKE_curve_nurbs_keyVertexTilts_apply(nurb, keyVerts);
if (keyVerts)
MEM_freeN(keyVerts);
-
- *originalVerts_r = originalVerts;
- *deformedVerts_r = deformedVerts;
- *numVerts_r = numVerts;
}
static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3]
@@ -894,14 +890,14 @@ static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
}
}
-static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal,
- int forRender, int renderResolution,
- float (*originalVerts)[3], float (*deformedVerts)[3])
+static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
+ ListBase *dispbase, DerivedMesh **derivedFinal,
+ int forRender, int renderResolution)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
ModifierData *pretessellatePoint;
Curve *cu = ob->data;
- ListBase *nurb = BKE_curve_nurbs_get(cu);
int required_mode = 0, totvert = 0;
int editmode = (!forRender && (cu->editnurb || cu->editfont));
DerivedMesh *dm = NULL, *ndm;
@@ -1046,12 +1042,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
}
(*derivedFinal) = dm;
}
-
- if (deformedVerts) {
- BK_curve_vertexCos_apply(ob->data, nurb, originalVerts);
- MEM_freeN(originalVerts);
- MEM_freeN(deformedVerts);
- }
}
static void displist_surf_indices(DispList *dl)
@@ -1142,8 +1132,8 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
/* this function represents logic of mesh's orcodm calculation
* for displist-based objects
*/
-
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
ModifierData *pretessellatePoint;
Curve *cu = ob->data;
int required_mode;
@@ -1201,25 +1191,24 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
DerivedMesh **derivedFinal, int forRender, int forOrco, int renderResolution)
{
- ListBase *nubase;
+ ListBase nubase = {NULL, NULL};
Nurb *nu;
Curve *cu = ob->data;
DispList *dl;
float *data;
int len;
- int numVerts;
- float (*originalVerts)[3];
- float (*deformedVerts)[3];
- if (!forRender && cu->editnurb)
- nubase = BKE_curve_editNurbs_get(cu);
- else
- nubase = &cu->nurb;
+ if (!forRender && cu->editnurb) {
+ BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(cu));
+ }
+ else {
+ BKE_nurbList_duplicate(&nubase, &cu->nurb);
+ }
if (!forOrco)
- curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts);
+ curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution);
- for (nu = nubase->first; nu; nu = nu->next) {
+ for (nu = nubase.first; nu; nu = nu->next) {
if (forRender || nu->hide == 0) {
int resolu = nu->resolu, resolv = nu->resolv;
@@ -1287,15 +1276,12 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
* already applied, thats how it worked for years, so keep for compatibility (sergey) */
BKE_displist_copy(&cu->disp, dispbase);
- if (!forRender) {
- BKE_curve_texspace_calc(cu);
- }
-
if (!forOrco) {
- curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal,
- forRender, renderResolution,
- originalVerts, deformedVerts);
+ curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal,
+ forRender, renderResolution);
}
+
+ BKE_nurbList_free(&nubase);
}
static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r)
@@ -1389,37 +1375,34 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
ListBase dlbev;
- ListBase *nubase;
- float (*originalVerts)[3];
- float (*deformedVerts)[3];
- int numVerts;
+ ListBase nubase = {NULL, NULL};
- nubase = BKE_curve_nurbs_get(cu);
+ BLI_freelistN(&(ob->curve_cache->bev));
- BLI_freelistN(&(cu->bev));
-
- if (cu->path) free_path(cu->path);
- cu->path = NULL;
+ if (ob->curve_cache->path) free_path(ob->curve_cache->path);
+ ob->curve_cache->path = NULL;
if (ob->type == OB_FONT)
BKE_vfont_to_curve(G.main, scene, ob, 0);
+ BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(cu));
+
if (!forOrco)
- curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts);
+ curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution);
- BKE_curve_bevelList_make(ob);
+ BKE_curve_bevelList_make(ob, &nubase, forRender != FALSE);
/* If curve has no bevel will return nothing */
BKE_curve_bevel_make(scene, ob, &dlbev, forRender, renderResolution);
/* no bevel or extrude, and no width correction? */
if (!dlbev.first && cu->width == 1.0f) {
- curve_to_displist(cu, nubase, dispbase, forRender, renderResolution);
+ curve_to_displist(cu, &nubase, dispbase, forRender, renderResolution);
}
else {
float widfac = cu->width - 1.0f;
- BevList *bl = cu->bev.first;
- Nurb *nu = nubase->first;
+ BevList *bl = ob->curve_cache->bev.first;
+ Nurb *nu = nubase.first;
for (; bl && nu; bl = bl->next, nu = nu->next) {
DispList *dl;
@@ -1586,27 +1569,25 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
if (!(cu->flag & CU_DEFORM_FILL)) {
- curve_to_filledpoly(cu, nubase, dispbase);
+ curve_to_filledpoly(cu, &nubase, dispbase);
}
if ((cu->flag & CU_PATH) && !forOrco)
- calc_curvepath(ob);
+ calc_curvepath(ob, &nubase);
/* make copy of 'undeformed" displist for texture space calculation
* actually, it's not totally undeformed -- pre-tessellation modifiers are
* already applied, thats how it worked for years, so keep for compatibility (sergey) */
BKE_displist_copy(&cu->disp, dispbase);
- if (!forRender) {
- BKE_curve_texspace_calc(cu);
- }
-
if (!forOrco)
- curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, renderResolution, originalVerts, deformedVerts);
+ curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal, forRender, renderResolution);
if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
- curve_to_filledpoly(cu, nubase, dispbase);
+ curve_to_filledpoly(cu, &nubase, dispbase);
}
+
+ BKE_nurbList_free(&nubase);
}
}
@@ -1621,37 +1602,36 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
return;
- BKE_displist_free(&(ob->disp));
- dispbase = &(ob->disp);
- BKE_displist_free(dispbase);
-
- /* free displist used for textspace */
BKE_displist_free(&cu->disp);
+ BKE_object_free_derived_caches(ob);
- do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco, 0);
+ if (!ob->curve_cache) {
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+ }
- if (ob->derivedFinal) {
- DM_set_object_boundbox(ob, ob->derivedFinal);
+ dispbase = &(ob->curve_cache->disp);
- /* always keep curve's BB in sync with non-deformed displist */
- if (cu->bb == NULL)
- cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+ do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco, 0);
- boundbox_dispbase(cu->bb, &cu->disp);
- }
- else {
- boundbox_displist(ob);
- }
+ boundbox_displist_object(ob);
}
void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
DerivedMesh **derivedFinal, int forOrco, int renderResolution)
{
+ if (ob->curve_cache == NULL) {
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ }
+
do_makeDispListCurveTypes(scene, ob, dispbase, derivedFinal, 1, forOrco, renderResolution);
}
void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
{
+ if (ob->curve_cache == NULL) {
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+ }
+
do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1);
}
@@ -1676,16 +1656,13 @@ float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *derivedFina
return orco;
}
-static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase)
+void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
{
- float min[3], max[3];
DispList *dl;
float *vert;
int a, tot = 0;
int doit = 0;
- INIT_MINMAX(min, max);
-
for (dl = dispbase->first; dl; dl = dl->next) {
tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
vert = dl->verts;
@@ -1700,26 +1677,29 @@ static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase)
zero_v3(min);
zero_v3(max);
}
-
- BKE_boundbox_init_from_minmax(bb, min, max);
}
/* this is confusing, there's also min_max_object, appplying the obmat... */
-static void boundbox_displist(Object *ob)
+static void boundbox_displist_object(Object *ob)
{
if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- Curve *cu = ob->data;
-
- /* calculate curve's BB based on non-deformed displist */
- if (cu->bb == NULL)
- cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
-
- boundbox_dispbase(cu->bb, &cu->disp);
+ /* Curver's BB is already calculated as a part of modifier stack,
+ * here we only calculate object BB based on final display list.
+ */
/* object's BB is calculated from final displist */
if (ob->bb == NULL)
ob->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
- boundbox_dispbase(ob->bb, &ob->disp);
+ if (ob->derivedFinal) {
+ DM_set_object_boundbox(ob, ob->derivedFinal);
+ }
+ else {
+ float min[3], max[3];
+
+ INIT_MINMAX(min, max);
+ BKE_displist_minmax(&ob->curve_cache->disp, min, max);
+ BKE_boundbox_init_from_minmax(ob->bb, min, max);
+ }
}
}
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index a62ca530bf9..580172bcccd 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -20,6 +20,9 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenkernel/intern/dynamicpaint.c
+ * \ingroup bke
+ */
#include "MEM_guardedalloc.h"
@@ -3802,14 +3805,15 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
*/
KDTreeNearest *nearest;
- int n, particles = 0;
+ int n, particles;
float smooth_range = smooth * (1.0f - strength), dist;
/* calculate max range that can have particles with higher influence than the nearest one */
float max_range = smooth - strength * smooth + solidradius;
/* Make gcc happy! */
dist = max_range;
- particles = BLI_kdtree_range_search(tree, max_range, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest);
+ particles = BLI_kdtree_range_search(tree, bData->realCoord[bData->s_pos[index]].v, NULL,
+ &nearest, max_range);
/* Find particle that produces highest influence */
for (n = 0; n < particles; n++) {
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index e8e56c6f17b..caa5bf90584 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -1872,7 +1872,7 @@ static void statvis_calc_thickness(
normal_tri_v3(ray_no, cos[2], cos[1], cos[0]);
#define FACE_RAY_TEST_ANGLE \
- f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, \
+ f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, \
&dist, NULL, NULL); \
if (f_hit && dist < face_dists[index]) { \
float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 74cd8834d5d..6a89d16d7bf 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -36,6 +36,7 @@
#include "DNA_mesh_types.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_scanfill.h"
#include "BKE_editmesh.h"
@@ -123,6 +124,7 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
int i = 0;
ScanFillContext sf_ctx;
+ MemArena *sf_arena = NULL;
#if 0
/* note, we could be clever and re-use this array but would need to ensure
@@ -217,7 +219,11 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
ScanFillFace *sf_tri;
int totfilltri;
- BLI_scanfill_begin(&sf_ctx);
+ if (UNLIKELY(sf_arena == NULL)) {
+ sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+ }
+
+ BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
/* scanfill time */
j = 0;
@@ -262,10 +268,15 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
l_ptr[2] = l3;
}
- BLI_scanfill_end(&sf_ctx);
+ BLI_scanfill_end_arena(&sf_ctx, sf_arena);
}
}
+ if (sf_arena) {
+ BLI_memarena_free(sf_arena);
+ sf_arena = NULL;
+ }
+
em->tottri = i;
em->looptris = looptris;
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index fced3472566..cb65fd80fc4 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -193,12 +193,17 @@ static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray,
const BMLoop **ltri = bmcb_data->looptris[index];
float dist, uv[2];
const float *tri_cos[3];
+ bool isect;
bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage);
- if (isect_ray_tri_v3(ray->origin, ray->direction, tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv) &&
- (dist < hit->dist))
- {
+ isect = (ray->radius > 0.0f ?
+ isect_ray_tri_epsilon_v3(ray->origin, ray->direction,
+ tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv, ray->radius) :
+ isect_ray_tri_v3(ray->origin, ray->direction,
+ tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv));
+
+ if (isect && dist < hit->dist) {
hit->dist = dist;
hit->index = index;
@@ -213,14 +218,14 @@ static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray,
}
}
-BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir[3],
+BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir[3], const float radius,
float *r_dist, float r_hitout[3], float r_cagehit[3])
{
BVHTreeRayHit hit;
struct RayCastUserData bmcb_data;
const float dist = r_dist ? *r_dist : FLT_MAX;
- if (bmtree->cos_cage) BLI_assert(!(bmtree->em->bm->elem_index_dirty & BM_VERT));
+ if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT));
hit.dist = dist;
hit.index = -1;
@@ -229,7 +234,7 @@ BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir
bmcb_data.looptris = (const BMLoop *(*)[3])bmtree->em->looptris;
bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage;
- BLI_bvhtree_ray_cast(bmtree->tree, co, dir, 0.0f, &hit, bmbvh_ray_cast_cb, &bmcb_data);
+ BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb, &bmcb_data);
if (hit.index != -1 && hit.dist != dist) {
if (r_hitout) {
if (bmtree->flag & BMBVH_RETURN_ORIG) {
@@ -314,7 +319,7 @@ BMFace *BKE_bmbvh_find_face_segment(BMBVHTree *bmtree, const float co_a[3], cons
const float dist = len_v3v3(co_a, co_b);
float dir[3];
- if (bmtree->cos_cage) BLI_assert(!(bmtree->em->bm->elem_index_dirty & BM_VERT));
+ if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT));
sub_v3_v3v3(dir, co_b, co_a);
@@ -400,7 +405,7 @@ BMVert *BKE_bmbvh_find_vert_closest(BMBVHTree *bmtree, const float co[3], const
struct VertSearchUserData bmcb_data;
const float maxdist_sq = maxdist * maxdist;
- if (bmtree->cos_cage) BLI_assert(!(bmtree->em->bm->elem_index_dirty & BM_VERT));
+ if (bmtree->cos_cage) BLI_assert(!(bmtree->bm->elem_index_dirty & BM_VERT));
hit.dist = maxdist_sq;
hit.index = -1;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 0df8684044a..81b0de9fd32 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -67,6 +67,7 @@
#include "BKE_blender.h"
#include "BKE_collision.h"
#include "BKE_constraint.h"
+#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
@@ -176,10 +177,10 @@ static void precalculate_effector(EffectorCache *eff)
if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
Curve *cu= eff->ob->data;
if (cu->flag & CU_PATH) {
- if (cu->path==NULL || cu->path->data==NULL)
+ if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);
- if (cu->path && cu->path->data) {
+ if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
mul_m4_v3(eff->ob->obmat, eff->guide_loc);
mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 791c47cc551..dbdf30ea63d 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -688,21 +688,27 @@ short fcurve_are_keyframes_usable(FCurve *fcu)
return 1;
}
+bool BKE_fcurve_is_protected(FCurve *fcu)
+{
+ return ((fcu->flag & FCURVE_PROTECTED) ||
+ ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)));
+}
+
/* Can keyframes be added to F-Curve?
* Keyframes can only be added if they are already visible
*/
-short fcurve_is_keyframable(FCurve *fcu)
+bool fcurve_is_keyframable(FCurve *fcu)
{
/* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
if (fcurve_are_keyframes_usable(fcu) == 0)
- return 0;
+ return false;
/* F-Curve must currently be editable too */
- if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) )
- return 0;
+ if (BKE_fcurve_is_protected(fcu))
+ return false;
/* F-Curve is keyframable */
- return 1;
+ return true;
}
/* ***************************** Keyframe Column Tools ********************************* */
@@ -841,14 +847,7 @@ void calchandles_fcurve(FCurve *fcu)
}
}
-/* Use when F-Curve with handles has changed
- * It treats all BezTriples with the following rules:
- * - PHASE 1: do types have to be altered?
- * -> Auto handles: become aligned when selection status is NOT(000 || 111)
- * -> Vector handles: become 'nothing' when (one half selected AND other not)
- * - PHASE 2: recalculate handles
- */
-void testhandles_fcurve(FCurve *fcu, const short use_handle)
+void testhandles_fcurve(FCurve *fcu, const bool use_handle)
{
BezTriple *bezt;
unsigned int a;
@@ -856,45 +855,10 @@ void testhandles_fcurve(FCurve *fcu, const short use_handle)
/* only beztriples have handles (bpoints don't though) */
if (ELEM(NULL, fcu, fcu->bezt))
return;
-
+
/* loop over beztriples */
for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
- short flag = 0;
-
- /* flag is initialized as selection status
- * of beztriple control-points (labelled 0, 1, 2)
- */
- if (bezt->f2 & SELECT) flag |= (1 << 1); // == 2
- if (use_handle == FALSE) {
- if (flag & 2) {
- flag |= (1 << 0) | (1 << 2);
- }
- }
- else {
- if (bezt->f1 & SELECT) flag |= (1 << 0); // == 1
- if (bezt->f3 & SELECT) flag |= (1 << 2); // == 4
- }
-
- /* one or two handles selected only */
- if (ELEM(flag, 0, 7) == 0) {
- /* auto handles become aligned */
- if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM))
- bezt->h1 = HD_ALIGN;
- if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM))
- bezt->h2 = HD_ALIGN;
-
- /* vector handles become 'free' when only one half selected */
- if (bezt->h1 == HD_VECT) {
- /* only left half (1 or 2 or 1+2) */
- if (flag < 4)
- bezt->h1 = 0;
- }
- if (bezt->h2 == HD_VECT) {
- /* only right half (4 or 2+4) */
- if (flag > 3)
- bezt->h2 = 0;
- }
- }
+ BKE_nurb_bezt_handle_test(bezt, use_handle);
}
/* recalculate handles */
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 7c23438f93d..f24d84df2e8 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -41,6 +41,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_threads.h"
#include "BLI_vfontdata.h"
#include "BLI_utildefines.h"
@@ -59,6 +60,7 @@
#include "BKE_curve.h"
#include "BKE_displist.h"
+static ThreadMutex vfont_mutex = BLI_MUTEX_INITIALIZER;
/* The vfont code */
void BKE_vfont_free_data(struct VFont *vfont)
@@ -138,6 +140,18 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
if (!vfont->data) {
PackedFile *pf;
+ BLI_mutex_lock(&vfont_mutex);
+
+ if (vfont->data) {
+ /* Check data again, since it might have been already
+ * initialized from other thread (previous check is
+ * not accurate or threading, just prevents unneeded
+ * lock if all the data is here for sure).
+ */
+ BLI_mutex_unlock(&vfont_mutex);
+ return vfont->data;
+ }
+
if (BKE_vfont_is_builtin(vfont)) {
pf = get_builtin_packedfile();
}
@@ -175,8 +189,10 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
freePackedFile(pf);
}
}
+
+ BLI_mutex_unlock(&vfont_mutex);
}
-
+
return vfont->data;
}
@@ -819,8 +835,10 @@ makebreak:
cucu->flag |= (CU_PATH + CU_FOLLOW);
- if (cucu->path == NULL) BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
- if (cucu->path) {
+ if (cu->textoncurve->curve_cache == NULL || cu->textoncurve->curve_cache->path == NULL) {
+ BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
+ }
+ if (cu->textoncurve->curve_cache->path) {
float distfac, imat[4][4], imat3[3][3], cmat[3][3];
float minx, maxx, miny, maxy;
float timeofs, sizefac;
@@ -845,7 +863,7 @@ makebreak:
/* we put the x-coordinaat exact at the curve, the y is rotated */
/* length correction */
- distfac = sizefac * cucu->path->totdist / (maxx - minx);
+ distfac = sizefac * cu->textoncurve->curve_cache->path->totdist / (maxx - minx);
timeofs = 0.0f;
if (distfac > 1.0f) {
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 32fe4ac4ba6..d87c93310c8 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -52,7 +52,7 @@ void BKE_freestyle_config_init(FreestyleConfig *config)
config->modules.first = config->modules.last = NULL;
config->flags = 0;
- config->sphere_radius = 1.0f;
+ config->sphere_radius = 0.1f;
config->dkr_epsilon = 0.0f;
config->crease_angle = DEG2RADF(134.43f);
@@ -107,7 +107,8 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con
static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset)
{
new_lineset->linestyle = lineset->linestyle;
- new_lineset->linestyle->id.us++;
+ if (new_lineset->linestyle)
+ new_lineset->linestyle->id.us++;
new_lineset->flags = lineset->flags;
new_lineset->selection = lineset->selection;
new_lineset->qi = lineset->qi;
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 31dd79e7623..4d17bd286b4 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -42,6 +42,7 @@
#include "BLF_translation.h"
#include "DNA_gpencil_types.h"
+#include "DNA_userdef_types.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
@@ -125,8 +126,8 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
bGPDframe *gpf, *gf;
short state = 0;
- /* error checking */
- if ((gpl == NULL) || (cframe <= 0))
+ /* error checking (neg frame only if they are not allowed in Blender!) */
+ if ((gpl == NULL) || ((U.flag & USER_NONEGFRAMES) && (cframe <= 0)))
return NULL;
/* allocate memory for this frame */
@@ -349,7 +350,8 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew)
/* error checking */
if (gpl == NULL) return NULL;
- if (cframe <= 0) cframe = 1;
+ /* No reason to forbid negative frames when they are allowed in Blender! */
+ if ((U.flag & USER_NONEGFRAMES) && cframe <= 0) cframe = 1;
/* check if there is already an active frame */
if (gpl->actframe) {
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index ad0aed4691a..a5cbf064bc2 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -65,9 +65,7 @@ void BKE_group_free(Group *group)
/* don't free group itself */
GroupObject *go;
- while (group->gobject.first) {
- go = group->gobject.first;
- BLI_remlink(&group->gobject, go);
+ while ((go = BLI_pophead(&group->gobject))) {
free_group_object(go);
}
}
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index f20506af967..6f275e4ec75 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -56,7 +56,13 @@ static char idp_size_table[] = {
sizeof(double)
};
-/* ------------Property Array Type ----------- */
+
+/* -------------------------------------------------------------------- */
+/* Array Functions */
+
+/** \name IDP Array API
+ * \{ */
+
#define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i))
/* --------- property array type -------------*/
@@ -78,9 +84,12 @@ IDProperty *IDP_NewIDPArray(const char *name)
IDProperty *IDP_CopyIDPArray(IDProperty *array)
{
/* don't use MEM_dupallocN because this may be part of an array */
- IDProperty *narray = MEM_mallocN(sizeof(IDProperty), "IDP_CopyIDPArray"), *tmp;
+ IDProperty *narray, *tmp;
int i;
+ BLI_assert(array->type == IDP_IDPARRAY);
+
+ narray = MEM_mallocN(sizeof(IDProperty), __func__);
*narray = *array;
narray->data.pointer = MEM_dupallocN(array->data.pointer);
@@ -103,6 +112,8 @@ void IDP_FreeIDPArray(IDProperty *prop)
{
int i;
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
for (i = 0; i < prop->len; i++)
IDP_FreeProperty(GETPROP(prop, i));
@@ -113,7 +124,11 @@ void IDP_FreeIDPArray(IDProperty *prop)
/*shallow copies item*/
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
{
- IDProperty *old = GETPROP(prop, index);
+ IDProperty *old;
+
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
+ old = GETPROP(prop, index);
if (index >= prop->len || index < 0) return;
if (item != old) IDP_FreeProperty(old);
@@ -122,22 +137,27 @@ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
IDProperty *IDP_GetIndexArray(IDProperty *prop, int index)
{
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
return GETPROP(prop, index);
}
void IDP_AppendArray(IDProperty *prop, IDProperty *item)
{
+ BLI_assert(prop->type == IDP_IDPARRAY);
+
IDP_ResizeIDPArray(prop, prop->len + 1);
IDP_SetIndexArray(prop, prop->len - 1, item);
}
void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
{
- void *newarr;
- int newsize = newlen;
+ int newsize;
+
+ BLI_assert(prop->type == IDP_IDPARRAY);
- /*first check if the array buffer size has room*/
- /*if newlen is 200 chars less then totallen, reallocate anyway*/
+ /* first check if the array buffer size has room */
+ /* if newlen is 200 items less then totallen, reallocate anyway */
if (newlen <= prop->totallen) {
if (newlen < prop->len && prop->totallen - newlen < 200) {
int i;
@@ -154,6 +174,15 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
}
}
+ /* free trailing items */
+ if (newlen < prop->len) {
+ /* newlen is smaller */
+ int i;
+ for (i = newlen; i < prop->len; i++) {
+ IDP_FreeProperty(GETPROP(prop, i));
+ }
+ }
+
/* - Note: This code comes from python, here's the corresponding comment. - */
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
@@ -162,25 +191,9 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
+ newsize = newlen;
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
-
- newarr = MEM_callocN(sizeof(IDProperty) * newsize, "idproperty array resized");
- if (newlen >= prop->len) {
- /* newlen is bigger */
- memcpy(newarr, prop->data.pointer, prop->len * sizeof(IDProperty));
- }
- else {
- int i;
- /* newlen is smaller */
- for (i = newlen; i < prop->len; i++) {
- IDP_FreeProperty(GETPROP(prop, i));
- }
- memcpy(newarr, prop->data.pointer, newlen * sizeof(IDProperty));
- }
-
- if (prop->data.pointer)
- MEM_freeN(prop->data.pointer);
- prop->data.pointer = newarr;
+ prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * newsize);
prop->len = newlen;
prop->totallen = newsize;
}
@@ -217,11 +230,11 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
/*this function works for strings too!*/
void IDP_ResizeArray(IDProperty *prop, int newlen)
{
- void *newarr;
- int newsize = newlen;
+ int newsize;
+ const bool is_grow = newlen >= prop->len;
- /*first check if the array buffer size has room*/
- /*if newlen is 200 chars less then totallen, reallocate anyway*/
+ /* first check if the array buffer size has room */
+ /* if newlen is 200 chars less then totallen, reallocate anyway */
if (newlen <= prop->totallen && prop->totallen - newlen < 200) {
idp_resize_group_array(prop, newlen, prop->data.pointer);
prop->len = newlen;
@@ -236,22 +249,17 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
- newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
+ newsize = newlen;
+ newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;\
- newarr = MEM_callocN(idp_size_table[(int)prop->subtype] * newsize, "idproperty array resized");
- if (newlen >= prop->len) {
- /* newlen is bigger */
- memcpy(newarr, prop->data.pointer, prop->len * idp_size_table[(int)prop->subtype]);
- idp_resize_group_array(prop, newlen, newarr);
- }
- else {
- /* newlen is smaller */
- idp_resize_group_array(prop, newlen, newarr);
- memcpy(newarr, prop->data.pointer, newlen * idp_size_table[(int)prop->subtype]);
- }
+ if (is_grow == false)
+ idp_resize_group_array(prop, newlen, prop->data.pointer);
+
+ prop->data.pointer = MEM_recallocN(prop->data.pointer, idp_size_table[(int)prop->subtype] * newsize);
+
+ if (is_grow == true)
+ idp_resize_group_array(prop, newlen, prop->data.pointer);
- MEM_freeN(prop->data.pointer);
- prop->data.pointer = newarr;
prop->len = newlen;
prop->totallen = newsize;
}
@@ -299,16 +307,31 @@ static IDProperty *IDP_CopyArray(IDProperty *prop)
return newp;
}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* String Functions */
-/* ---------- String Type ------------ */
+/** \name IDProperty String API
+ * \{ */
+
+/**
+ *
+ * \param st The string to assign.
+ * \param name The property name.
+ * \param maxlen The size of the new string (including the \0 terminator)
+ * \return
+ */
IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
{
IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty string");
if (st == NULL) {
- prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
+ prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
+ *IDP_String(prop) = '\0';
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
- prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/
+ prop->len = 1; /* NULL string, has len of 1 to account for null byte. */
}
else {
int stlen = strlen(st);
@@ -318,7 +341,7 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
stlen++; /* null terminator '\0' */
- prop->data.pointer = MEM_callocN(stlen, "id property string 2");
+ prop->data.pointer = MEM_mallocN(stlen, "id property string 2");
prop->len = prop->totallen = stlen;
BLI_strncpy(prop->data.pointer, st, stlen);
}
@@ -331,9 +354,13 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
static IDProperty *IDP_CopyString(IDProperty *prop)
{
- IDProperty *newp = idp_generic_copy(prop);
+ IDProperty *newp;
- if (prop->data.pointer) newp->data.pointer = MEM_dupallocN(prop->data.pointer);
+ BLI_assert(prop->type == IDP_STRING);
+ newp = idp_generic_copy(prop);
+
+ if (prop->data.pointer)
+ newp->data.pointer = MEM_dupallocN(prop->data.pointer);
newp->len = prop->len;
newp->subtype = prop->subtype;
newp->totallen = prop->totallen;
@@ -344,8 +371,10 @@ static IDProperty *IDP_CopyString(IDProperty *prop)
void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
{
- int stlen = strlen(st);
+ int stlen;
+ BLI_assert(prop->type == IDP_STRING);
+ stlen = strlen(st);
if (maxlen > 0 && maxlen < stlen)
stlen = maxlen;
@@ -354,7 +383,7 @@ void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
memcpy(prop->data.pointer, st, stlen);
}
else {
- stlen++; /* make room for null byte */
+ stlen++;
IDP_ResizeArray(prop, stlen);
BLI_strncpy(prop->data.pointer, st, stlen);
}
@@ -364,6 +393,8 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st)
{
int newlen;
+ BLI_assert(prop->type == IDP_STRING);
+
newlen = prop->len + strlen(st);
/* we have to remember that prop->len includes the null byte for strings.
* so there's no need to add +1 to the resize function.*/
@@ -375,6 +406,8 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append)
{
int newlen;
+ BLI_assert(append->type == IDP_STRING);
+
/* since ->len for strings includes the NULL byte, we have to subtract one or
* we'll get an extra null byte after each concatenation operation.*/
newlen = str1->len + append->len - 1;
@@ -384,13 +417,19 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append)
void IDP_FreeString(IDProperty *prop)
{
+ BLI_assert(prop->type == IDP_STRING);
+
if (prop->data.pointer)
MEM_freeN(prop->data.pointer);
}
+/** \} */
-/*-------- ID Type, not in use yet -------*/
+/* -------------------------------------------------------------------- */
+/* ID Type (not in use yet) */
+/** \name IDProperty ID API (unused)
+ * \{ */
void IDP_LinkID(IDProperty *prop, ID *id)
{
if (prop->data.pointer) ((ID *)prop->data.pointer)->us--;
@@ -402,15 +441,26 @@ void IDP_UnlinkID(IDProperty *prop)
{
((ID *)prop->data.pointer)->us--;
}
+/** \} */
+
-/*-------- Group Functions -------*/
+/* -------------------------------------------------------------------- */
+/* Group Functions */
-/*checks if a property with the same name as prop exists, and if so replaces it.*/
+/** \name IDProperty Group API
+ * \{ */
+
+/**
+ * Checks if a property with the same name as prop exists, and if so replaces it.
+ */
static IDProperty *IDP_CopyGroup(IDProperty *prop)
{
- IDProperty *newp = idp_generic_copy(prop), *link;
- newp->len = prop->len;
+ IDProperty *newp, *link;
+ BLI_assert(prop->type == IDP_GROUP);
+ newp = idp_generic_copy(prop);
+ newp->len = prop->len;
+
for (link = prop->data.group.first; link; link = link->next) {
BLI_addtail(&newp->data.group, IDP_CopyProperty(link));
}
@@ -423,6 +473,10 @@ static IDProperty *IDP_CopyGroup(IDProperty *prop)
void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
{
IDProperty *other, *prop;
+
+ BLI_assert(dest->type == IDP_GROUP);
+ BLI_assert(src->type == IDP_GROUP);
+
for (prop = src->data.group.first; prop; prop = prop->next) {
other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name));
if (other && prop->type == other->type) {
@@ -458,6 +512,10 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src)
{
IDProperty *loop, *prop;
+
+ BLI_assert(dest->type == IDP_GROUP);
+ BLI_assert(src->type == IDP_GROUP);
+
for (prop = src->data.group.first; prop; prop = prop->next) {
for (loop = dest->data.group.first; loop; loop = loop->next) {
if (STREQ(loop->name, prop->name)) {
@@ -488,6 +546,9 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src)
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
{
IDProperty *loop;
+
+ BLI_assert(group->type == IDP_GROUP);
+
if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) {
BLI_insertlinkafter(&group->data.group, loop, prop);
@@ -501,13 +562,16 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
}
}
-/*
+/**
* If a property is missing in \a dest, add it.
*/
void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite)
{
IDProperty *prop;
+ BLI_assert(dest->type == IDP_GROUP);
+ BLI_assert(src->type == IDP_GROUP);
+
if (do_overwrite) {
for (prop = src->data.group.first; prop; prop = prop->next) {
IDProperty *copy = IDP_CopyProperty(prop);
@@ -542,6 +606,8 @@ void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite)
*/
int IDP_AddToGroup(IDProperty *group, IDProperty *prop)
{
+ BLI_assert(group->type == IDP_GROUP);
+
if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) {
group->len++;
BLI_addtail(&group->data.group, prop);
@@ -557,6 +623,8 @@ int IDP_AddToGroup(IDProperty *group, IDProperty *prop)
*/
int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
{
+ BLI_assert(group->type == IDP_GROUP);
+
if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) {
group->len++;
BLI_insertlinkafter(&group->data.group, previous, pnew);
@@ -575,12 +643,16 @@ int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
*/
void IDP_RemFromGroup(IDProperty *group, IDProperty *prop)
{
+ BLI_assert(group->type == IDP_GROUP);
+
group->len--;
BLI_remlink(&group->data.group, prop);
}
IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name)
{
+ BLI_assert(prop->type == IDP_GROUP);
+
return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name));
}
/** same as above but ensure type match */
@@ -603,7 +675,10 @@ typedef struct IDPIter {
*/
void *IDP_GetGroupIterator(IDProperty *prop)
{
- IDPIter *iter = MEM_callocN(sizeof(IDPIter), "IDPIter");
+ IDPIter *iter;
+
+ BLI_assert(prop->type == IDP_GROUP);
+ iter = MEM_mallocN(sizeof(IDPIter), "IDPIter");
iter->next = prop->data.group.first;
iter->parent = prop;
return (void *) iter;
@@ -644,14 +719,21 @@ void IDP_FreeIterBeforeEnd(void *vself)
static void IDP_FreeGroup(IDProperty *prop)
{
IDProperty *loop;
+
+ BLI_assert(prop->type == IDP_GROUP);
for (loop = prop->data.group.first; loop; loop = loop->next) {
IDP_FreeProperty(loop);
}
BLI_freelistN(&prop->data.group);
}
+/** \} */
-/*-------- Main Functions --------*/
+/* -------------------------------------------------------------------- */
+/* Main Functions */
+
+/** \name IDProperty Main API
+ * \{ */
IDProperty *IDP_CopyProperty(IDProperty *prop)
{
switch (prop->type) {
@@ -822,7 +904,8 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
if (val->string.subtype == IDP_STRING_SUB_BYTE) {
/* note, intentionally not null terminated */
if (st == NULL) {
- prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
+ prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
+ *IDP_String(prop) = '\0';
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
prop->len = 0;
}
@@ -835,7 +918,8 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
}
else {
if (st == NULL) {
- prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
+ prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
+ *IDP_String(prop) = '\0';
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/
}
@@ -911,3 +995,5 @@ void IDP_UnlinkProperty(IDProperty *prop)
break;
}
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 86382c64ed3..2bf6304b04b 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -195,9 +195,7 @@ static void image_free_buffers(Image *ima)
{
ImBuf *ibuf;
- while ((ibuf = ima->ibufs.first)) {
- BLI_remlink(&ima->ibufs, ibuf);
-
+ while ((ibuf = BLI_pophead(&ima->ibufs))) {
if (ibuf->userdata) {
MEM_freeN(ibuf->userdata);
ibuf->userdata = NULL;
@@ -524,8 +522,7 @@ void BKE_image_merge(Image *dest, Image *source)
/* sanity check */
if (dest && source && dest != source) {
- while ((ibuf = source->ibufs.first)) {
- BLI_remlink(&source->ibufs, ibuf);
+ while ((ibuf = BLI_pophead(&source->ibufs))) {
image_assign_ibuf(dest, ibuf, IMA_INDEX_PASS(ibuf->index), IMA_INDEX_FRAME(ibuf->index));
}
@@ -1329,7 +1326,7 @@ int BKE_add_image_extension_from_type(char *string, const char imtype)
void BKE_imformat_defaults(ImageFormatData *im_format)
{
memset(im_format, 0, sizeof(*im_format));
- im_format->planes = R_IMF_PLANES_RGB;
+ im_format->planes = R_IMF_PLANES_RGBA;
im_format->imtype = R_IMF_IMTYPE_PNG;
im_format->depth = R_IMF_CHAN_DEPTH_8;
im_format->quality = 90;
@@ -2152,9 +2149,7 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
/* texture users */
for (tex = mainp->tex.first; tex; tex = tex->id.next) {
if (tex->type == TEX_IMAGE && tex->ima) {
- if (ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
- callback(tex->ima, &tex->iuser, customdata);
- }
+ callback(tex->ima, &tex->iuser, customdata);
}
}
@@ -2196,7 +2191,7 @@ static void image_tag_frame_recalc(Image *ima, ImageUser *iuser, void *customdat
{
Image *changed_image = customdata;
- if (ima == changed_image) {
+ if (ima == changed_image && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
iuser->flag |= IMA_NEED_FRAME_RECALC;
}
}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index d2d2cb1c2d0..7b73dee73fc 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -85,29 +85,23 @@ void BKE_key_free(Key *key)
KeyBlock *kb;
BKE_free_animdata((ID *)key);
-
- while ( (kb = key->block.first) ) {
-
- if (kb->data) MEM_freeN(kb->data);
-
- BLI_remlink(&key->block, kb);
+
+ while ((kb = BLI_pophead(&key->block))) {
+ if (kb->data)
+ MEM_freeN(kb->data);
MEM_freeN(kb);
}
-
}
void BKE_key_free_nolib(Key *key)
{
KeyBlock *kb;
-
- while ( (kb = key->block.first) ) {
-
- if (kb->data) MEM_freeN(kb->data);
-
- BLI_remlink(&key->block, kb);
+
+ while ((kb = BLI_pophead(&key->block))) {
+ if (kb->data)
+ MEM_freeN(kb->data);
MEM_freeN(kb);
}
-
}
Key *BKE_key_add(ID *id) /* common function */
@@ -734,12 +728,13 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const
}
}
-void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode)
+void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb,
+ float **per_keyblock_weights, const int mode)
{
KeyBlock *kb;
int *ofsp, ofs[3], elemsize, b;
char *cp, *poin, *reffrom, *from, elemstr[8];
- int poinsize;
+ int poinsize, keyblock_index;
/* currently always 0, in future key_pointer_size may assign */
ofs[1] = 0;
@@ -763,14 +758,14 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba
/* step 2: do it */
- for (kb = key->block.first; kb; kb = kb->next) {
+ for (kb = key->block.first, keyblock_index = 0; kb; kb = kb->next, keyblock_index++) {
if (kb != key->refkey) {
float icuval = kb->curval;
/* only with value, and no difference allowed */
if (!(kb->flag & KEYBLOCK_MUTE) && icuval != 0.0f && kb->totelem == tot) {
KeyBlock *refb;
- float weight, *weights = kb->weights;
+ float weight, *weights = per_keyblock_weights ? per_keyblock_weights[keyblock_index] : NULL;
char *freefrom = NULL, *freereffrom = NULL;
/* reference now can be any block */
@@ -1058,7 +1053,7 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
if (freek4) MEM_freeN(freek4);
}
-static float *get_weights_array(Object *ob, char *vgroup)
+static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cache)
{
MDeformVert *dvert = NULL;
BMEditMesh *em = NULL;
@@ -1091,7 +1086,21 @@ static float *get_weights_array(Object *ob, char *vgroup)
if (defgrp_index != -1) {
float *weights;
int i;
-
+
+ if (cache) {
+ if (cache->defgroup_weights == NULL) {
+ int num_defgroup = BLI_countlist(&ob->defbase);
+ cache->defgroup_weights =
+ MEM_callocN(sizeof(*cache->defgroup_weights) * num_defgroup,
+ "cached defgroup weights");
+ cache->num_defgroup_weights = num_defgroup;
+ }
+
+ if (cache->defgroup_weights[defgrp_index]) {
+ return cache->defgroup_weights[defgrp_index];
+ }
+ }
+
weights = MEM_mallocN(totvert * sizeof(float), "weights");
if (em) {
@@ -1107,11 +1116,61 @@ static float *get_weights_array(Object *ob, char *vgroup)
}
}
+ if (cache) {
+ cache->defgroup_weights[defgrp_index] = weights;
+ }
+
return weights;
}
return NULL;
}
+float **BKE_keyblock_get_per_block_weights(Object *ob, Key *key, WeightsArrayCache *cache)
+{
+ KeyBlock *keyblock;
+ float **per_keyblock_weights;
+ int keyblock_index;
+
+ per_keyblock_weights =
+ MEM_mallocN(sizeof(*per_keyblock_weights) * key->totkey,
+ "per keyblock weights");
+
+ for (keyblock = key->block.first, keyblock_index = 0;
+ keyblock;
+ keyblock = keyblock->next, keyblock_index++)
+ {
+ per_keyblock_weights[keyblock_index] = get_weights_array(ob, keyblock->vgroup, cache);
+ }
+
+ return per_keyblock_weights;
+}
+
+void BKE_keyblock_free_per_block_weights(Key *key, float **per_keyblock_weights, WeightsArrayCache *cache)
+{
+ int a;
+
+ if (cache) {
+ if (cache->num_defgroup_weights) {
+ for (a = 0; a < cache->num_defgroup_weights; a++) {
+ if (cache->defgroup_weights[a]) {
+ MEM_freeN(cache->defgroup_weights[a]);
+ }
+ }
+ MEM_freeN(cache->defgroup_weights);
+ }
+ cache->defgroup_weights = NULL;
+ }
+ else {
+ for (a = 0; a < key->totkey; a++) {
+ if (per_keyblock_weights[a]) {
+ MEM_freeN(per_keyblock_weights[a]);
+ }
+ }
+ }
+
+ MEM_freeN(per_keyblock_weights);
+}
+
static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
{
KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
@@ -1144,17 +1203,11 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int
}
else {
if (key->type == KEY_RELATIVE) {
- KeyBlock *kb;
- for (kb = key->block.first; kb; kb = kb->next) {
- kb->weights = get_weights_array(ob, kb->vgroup);
- }
-
- BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY);
-
- for (kb = key->block.first; kb; kb = kb->next) {
- if (kb->weights) MEM_freeN(kb->weights);
- kb->weights = NULL;
- }
+ WeightsArrayCache cache = {0, NULL};
+ float **per_keyblock_weights;
+ per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, &cache);
+ BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+ BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
}
else {
const float ctime_scaled = key->ctime / 100.0f;
@@ -1197,11 +1250,11 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const
for (a = 0, nu = cu->nurb.first; nu; nu = nu->next, a += step) {
if (nu->bp) {
step = nu->pntsu * nu->pntsv;
- BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT);
+ BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, NULL, KEY_MODE_BPOINT);
}
else if (nu->bezt) {
step = 3 * nu->pntsu;
- BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE);
+ BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, NULL, KEY_MODE_BEZTRIPLE);
}
else {
step = 0;
@@ -1315,17 +1368,10 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
}
else {
if (key->type == KEY_RELATIVE) {
- KeyBlock *kb;
-
- for (kb = key->block.first; kb; kb = kb->next)
- kb->weights = get_weights_array(ob, kb->vgroup);
-
- BKE_key_evaluate_relative(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY);
-
- for (kb = key->block.first; kb; kb = kb->next) {
- if (kb->weights) MEM_freeN(kb->weights);
- kb->weights = NULL;
- }
+ float **per_keyblock_weights;
+ per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, NULL);
+ BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
+ BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, NULL);
}
else {
const float ctime_scaled = key->ctime / 100.0f;
@@ -1415,7 +1461,7 @@ float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem,
}
if (OB_TYPE_SUPPORT_VGROUP(ob->type)) {
- float *weights = get_weights_array(ob, kb->vgroup);
+ float *weights = get_weights_array(ob, kb->vgroup, NULL);
cp_key(0, tot, tot, out, key, actkb, kb, weights, 0);
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index a4892253c63..60b4db6aa9b 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -51,6 +51,7 @@
#include "BKE_animsys.h"
#include "BKE_anim.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -164,7 +165,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
lt->typeu = lt->typev = lt->typew = KEY_LINEAR;
/* prevent using deformed locations */
- BKE_displist_free(&ltOb->disp);
+ BKE_displist_free(&ltOb->curve_cache->disp);
copy_m4_m4(mat, ltOb->obmat);
unit_m4(ltOb->obmat);
@@ -306,37 +307,46 @@ void BKE_lattice_make_local(Lattice *lt)
}
}
-void init_latt_deform(Object *oblatt, Object *ob)
+typedef struct LatticeDeformData {
+ Object *object;
+ float *latticedata;
+ float latmat[4][4];
+} LatticeDeformData;
+
+LatticeDeformData *init_latt_deform(Object *oblatt, Object *ob)
{
/* we make an array with all differences */
Lattice *lt = oblatt->data;
BPoint *bp;
- DispList *dl = BKE_displist_find(&oblatt->disp, DL_VERTS);
+ DispList *dl = oblatt->curve_cache ? BKE_displist_find(&oblatt->curve_cache->disp, DL_VERTS) : NULL;
float *co = dl ? dl->verts : NULL;
float *fp, imat[4][4];
float fu, fv, fw;
int u, v, w;
+ float *latticedata;
+ float latmat[4][4];
+ LatticeDeformData *lattice_deform_data;
if (lt->editlatt) lt = lt->editlatt->latt;
bp = lt->def;
- fp = lt->latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw, "latticedata");
+ fp = latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw, "latticedata");
/* for example with a particle system: (ob == NULL) */
if (ob == NULL) {
/* in deformspace, calc matrix */
- invert_m4_m4(lt->latmat, oblatt->obmat);
+ invert_m4_m4(latmat, oblatt->obmat);
/* back: put in deform array */
- invert_m4_m4(imat, lt->latmat);
+ invert_m4_m4(imat, latmat);
}
else {
/* in deformspace, calc matrix */
invert_m4_m4(imat, oblatt->obmat);
- mul_m4_m4m4(lt->latmat, imat, ob->obmat);
+ mul_m4_m4m4(latmat, imat, ob->obmat);
/* back: put in deform array */
- invert_m4_m4(imat, lt->latmat);
+ invert_m4_m4(imat, latmat);
}
for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) {
@@ -357,10 +367,18 @@ void init_latt_deform(Object *oblatt, Object *ob)
}
}
}
+
+ lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data");
+ lattice_deform_data->latticedata = latticedata;
+ lattice_deform_data->object = oblatt;
+ copy_m4_m4(lattice_deform_data->latmat, latmat);
+
+ return lattice_deform_data;
}
-void calc_latt_deform(Object *ob, float co[3], float weight)
+void calc_latt_deform(LatticeDeformData *lattice_deform_data, float co[3], float weight)
{
+ Object *ob = lattice_deform_data->object;
Lattice *lt = ob->data;
float u, v, w, tu[4], tv[4], tw[4];
float vec[3];
@@ -374,7 +392,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
if (lt->editlatt) lt = lt->editlatt->latt;
- if (lt->latticedata == NULL) return;
+ if (lattice_deform_data->latticedata == NULL) return;
if (lt->vgroup[0] && dvert) {
defgrp_index = defgroup_name_index(ob, lt->vgroup);
@@ -382,7 +400,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
}
/* co is in local coords, treat with latmat */
- mul_v3_m4v3(vec, lt->latmat, co);
+ mul_v3_m4v3(vec, lattice_deform_data->latmat, co);
/* u v w coords */
@@ -455,7 +473,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
idx_u = idx_v;
}
- madd_v3_v3fl(co, &lt->latticedata[idx_u * 3], u);
+ madd_v3_v3fl(co, &lattice_deform_data->latticedata[idx_u * 3], u);
if (defgrp_index != -1)
weight_blend += (u * defvert_find_weight(dvert + idx_u, defgrp_index));
@@ -471,15 +489,12 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
}
-void end_latt_deform(Object *ob)
+void end_latt_deform(LatticeDeformData *lattice_deform_data)
{
- Lattice *lt = ob->data;
-
- if (lt->editlatt) lt = lt->editlatt->latt;
-
- if (lt->latticedata)
- MEM_freeN(lt->latticedata);
- lt->latticedata = NULL;
+ if (lattice_deform_data->latticedata)
+ MEM_freeN(lattice_deform_data->latticedata);
+
+ MEM_freeN(lattice_deform_data);
}
/* calculations is in local space of deformed object
@@ -506,13 +521,12 @@ static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
*/
static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius)
{
- Curve *cu = ob->data;
BevList *bl;
float ctime1;
int cycl = 0;
/* test for cyclic */
- bl = cu->bev.first;
+ bl = ob->curve_cache->bev.first;
if (!bl->nr) return 0;
if (bl->poly > -1) cycl = 1;
@@ -527,7 +541,7 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir
if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
if (cycl == 0) {
- Path *path = cu->path;
+ Path *path = ob->curve_cache->path;
float dvec[3];
if (ctime < 0.0f) {
@@ -565,9 +579,9 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3],
const int is_neg_axis = (axis > 2);
/* to be sure, mostly after file load */
- if (cu->path == NULL) {
+ if (ELEM(NULL, par->curve_cache, par->curve_cache->path)) {
BKE_displist_make_curveTypes(scene, par, 0);
- if (cu->path == NULL) return 0; // happens on append...
+ if (par->curve_cache->path == NULL) return 0; // happens on append...
}
/* options */
@@ -576,14 +590,14 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3],
if (cu->flag & CU_STRETCH)
fac = (-co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
else
- fac = -(co[index] - cd->dmax[index]) / (cu->path->totdist);
+ fac = -(co[index] - cd->dmax[index]) / (par->curve_cache->path->totdist);
}
else {
index = axis;
if (cu->flag & CU_STRETCH)
fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
else
- fac = +(co[index] - cd->dmin[index]) / (cu->path->totdist);
+ fac = +(co[index] - cd->dmin[index]) / (par->curve_cache->path->totdist);
}
if (where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */
@@ -815,13 +829,14 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target,
void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts, const char *vgroup, float fac)
{
+ LatticeDeformData *lattice_deform_data;
int a;
int use_vgroups;
if (laOb->type != OB_LATTICE)
return;
- init_latt_deform(laOb, target);
+ lattice_deform_data = init_latt_deform(laOb, target);
/* check whether to use vertex groups (only possible if target is a Mesh)
* we want either a Mesh with no derived data, or derived data with
@@ -855,16 +870,16 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
weight = defvert_find_weight(dvert, defgrp_index);
if (weight > 0.0f)
- calc_latt_deform(laOb, vertexCos[a], weight * fac);
+ calc_latt_deform(lattice_deform_data, vertexCos[a], weight * fac);
}
}
}
else {
for (a = 0; a < numVerts; a++) {
- calc_latt_deform(laOb, vertexCos[a], fac);
+ calc_latt_deform(lattice_deform_data, vertexCos[a], fac);
}
}
- end_latt_deform(laOb);
+ end_latt_deform(lattice_deform_data);
}
int object_deform_mball(Object *ob, ListBase *dispbase)
@@ -991,11 +1006,17 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3])
void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
{
Lattice *lt = ob->data;
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
float (*vertexCos)[3] = NULL;
int numVerts, editmode = (lt->editlatt != NULL);
- BKE_displist_free(&ob->disp);
+ if (ob->curve_cache) {
+ BKE_displist_free(&ob->curve_cache->disp);
+ }
+ else {
+ ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice");
+ }
for (; md; md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1021,7 +1042,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
dl->nr = numVerts;
dl->verts = (float *) vertexCos;
- BLI_addtail(&ob->disp, dl);
+ BLI_addtail(&ob->curve_cache->disp, dl);
}
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index c23fa097d3e..9b8d34e651d 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -269,7 +269,8 @@ bool id_make_local(ID *id, bool test)
if (!test) BKE_action_make_local((bAction *)id);
return true;
case ID_NT:
- return false; /* not implemented */
+ if (!test) ntreeMakeLocal((bNodeTree *)id);
+ return true;
case ID_BR:
if (!test) BKE_brush_make_local((Brush *)id);
return true;
@@ -1410,7 +1411,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname)
/* This was in 2.43 and previous releases
* however all data in blender should be sorted, not just duplicate names
- * sorting should not hurt, but noting just incause it alters the way other
+ * sorting should not hurt, but noting just incase it alters the way other
* functions work, so sort every time */
#if 0
if (result)
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 497554be113..d3c9250694c 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -81,6 +81,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle)
linestyle->thickness = 3.0f;
linestyle->thickness_position = LS_THICKNESS_CENTER;
linestyle->thickness_ratio = 0.5f;
+ linestyle->flag = LS_SAME_OBJECT;
linestyle->chaining = LS_CHAINING_PLAIN;
linestyle->rounds = 3;
linestyle->min_angle = DEG2RADF(0.0f);
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index e3f30bad5cf..c856d8cfea4 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -817,6 +817,19 @@ void BKE_mask_spline_free(MaskSpline *spline)
MEM_freeN(spline);
}
+void BKE_mask_spline_free_list(ListBase *splines)
+{
+ MaskSpline *spline = splines->first;
+ while (spline) {
+ MaskSpline *next_spline = spline->next;
+
+ BLI_remlink(splines, spline);
+ BKE_mask_spline_free(spline);
+
+ spline = next_spline;
+ }
+}
+
static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot_point)
{
MaskSplinePoint *npoints;
@@ -891,20 +904,30 @@ void BKE_mask_layer_free_shapes(MaskLayer *masklay)
}
}
-void BKE_mask_layer_free(MaskLayer *masklay)
+void BKE_mask_layer_free_deform(MaskLayer *mask_layer)
{
- MaskSpline *spline;
-
- /* free splines */
- spline = masklay->splines.first;
- while (spline) {
- MaskSpline *next_spline = spline->next;
+ MaskSpline *mask_spline;
- BLI_remlink(&masklay->splines, spline);
- BKE_mask_spline_free(spline);
-
- spline = next_spline;
+ for (mask_spline = mask_layer->splines.first;
+ mask_spline;
+ mask_spline = mask_spline->next)
+ {
+ if (mask_spline->points_deform) {
+ int i;
+ MaskSplinePoint *points_deform = mask_spline->points_deform;
+ for (i = 0; i < mask_spline->tot_point; i++) {
+ BKE_mask_point_free(&points_deform[i]);
+ }
+ MEM_freeN(points_deform);
+ mask_spline->points_deform = NULL;
+ }
}
+}
+
+void BKE_mask_layer_free(MaskLayer *masklay)
+{
+ /* free splines */
+ BKE_mask_spline_free_list(&masklay->splines);
/* free animation data */
BKE_mask_layer_free_shapes(masklay);
@@ -1072,10 +1095,15 @@ void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], cons
BKE_mask_coord_to_frame(r_co, co, frame_size);
}
-static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[2])
+void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float parent_matrix[3][3])
{
- if (!parent)
- return FALSE;
+ MaskParent *parent = &point->parent;
+
+ unit_m3(parent_matrix);
+
+ if (!parent) {
+ return;
+ }
if (parent->id_type == ID_MC) {
if (parent->id) {
@@ -1084,38 +1112,66 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[
MovieTrackingObject *ob = BKE_tracking_object_get_named(tracking, parent->parent);
if (ob) {
- MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, ob, parent->sub_parent);
+ MovieClipUser user = {0};
float clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
+ BKE_movieclip_user_set_frame(&user, ctime);
- MovieClipUser user = {0};
- user.framenr = ctime;
+ if (parent->type == MASK_PARENT_POINT_TRACK) {
+ MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, ob, parent->sub_parent);
+
+ if (track) {
+ float marker_position[2], parent_co[2];
+ BKE_tracking_marker_get_subframe_position(track, clip_framenr, marker_position);
+ BKE_mask_coord_from_movieclip(clip, &user, parent_co, marker_position);
+ sub_v2_v2v2(parent_matrix[2], parent_co, parent->parent_orig);
+ }
+ }
+ else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+ MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, ob, parent->sub_parent);
+
+ if (plane_track) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+ float aspx, aspy;
+ float frame_size[2], H[3][3], mask_from_clip_matrix[3][3], mask_to_clip_matrix[3][3];
+
+ BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, plane_marker->corners, H);
- if (track) {
- float marker_pos_ofs[2];
- BKE_tracking_marker_get_subframe_position(track, clip_framenr, marker_pos_ofs);
- BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs);
+ unit_m3(mask_from_clip_matrix);
- return TRUE;
+ BKE_movieclip_get_size_fl(clip, &user, frame_size);
+ BKE_movieclip_get_aspect(clip, &aspx, &aspy);
+
+ frame_size[1] *= (aspy / aspx);
+ if (frame_size[0] == frame_size[1]) {
+ /* pass */
+ }
+ else if (frame_size[0] < frame_size[1]) {
+ mask_from_clip_matrix[0][0] = frame_size[1] / frame_size[0];
+ mask_from_clip_matrix[2][0] = -0.5f * (frame_size[1] / frame_size[0]) + 0.5f;
+ }
+ else { /* (frame_size[0] > frame_size[1]) */
+ mask_from_clip_matrix[1][1] = frame_size[1] / frame_size[0];
+ mask_from_clip_matrix[2][1] = -0.5f * (frame_size[1] / frame_size[0]) + 0.5f;
+ }
+
+ invert_m3_m3(mask_to_clip_matrix, mask_from_clip_matrix);
+ mul_serie_m3(parent_matrix, mask_to_clip_matrix, H, mask_from_clip_matrix, NULL, NULL, NULL, NULL, NULL);
+ }
}
}
}
}
-
- return FALSE;
}
-/* could make external but for now its only used internally */
-static int mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2])
+static void mask_evaluate_apply_point_parent(MaskSplinePoint *point, float ctime)
{
- float parent_co[2];
+ float parent_matrix[3][3];
- if (BKE_mask_evaluate_parent(parent, ctime, parent_co)) {
- sub_v2_v2v2(r_delta, parent_co, parent->parent_orig);
- return TRUE;
- }
- else {
- return FALSE;
- }
+ BKE_mask_point_parent_matrix_get(point, ctime, parent_matrix);
+
+ mul_m3_v2(parent_matrix, point->bezt.vec[0]);
+ mul_m3_v2(parent_matrix, point->bezt.vec[1]);
+ mul_m3_v2(parent_matrix, point->bezt.vec[2]);
}
static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *point_prev, MaskSplinePoint *point_next)
@@ -1350,7 +1406,7 @@ void BKE_mask_update_deform(Mask *mask)
int j;
for (j = 0; j <= 2; j += 2) { /* (0, 2) */
- printf("--- %d %d, %d, %d\n", i, j, i_prev, i_next);
+ // printf("--- %d %d, %d, %d\n", i, j, i_prev, i_next);
barycentric_weights_v2(bezt_prev->vec[1], bezt->vec[1], bezt_next->vec[1],
bezt->vec[j], w_src);
interp_v3_v3v3v3(bezt_def->vec[j],
@@ -1438,18 +1494,13 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
MaskSplinePoint *point_deform = &spline->points_deform[i];
- float delta[2];
BKE_mask_point_free(point_deform);
*point_deform = *point;
point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL;
- if (mask_evaluate_parent_delta(&point->parent, ctime, delta)) {
- add_v2_v2(point_deform->bezt.vec[0], delta);
- add_v2_v2(point_deform->bezt.vec[1], delta);
- add_v2_v2(point_deform->bezt.vec[2], delta);
- }
+ mask_evaluate_apply_point_parent(point_deform, ctime);
if (ELEM(point->bezt.h1, HD_AUTO, HD_VECT)) {
need_handle_recalc = TRUE;
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index ac48eaa3185..874e60936d1 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -82,17 +82,10 @@
#include "BLI_rect.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
+#include "BLI_strict_flags.h"
#include "BKE_mask.h"
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
-# pragma GCC diagnostic error "-Wsign-compare"
-# pragma GCC diagnostic error "-Wconversion"
-# endif
-#endif
-
/* this is rather and annoying hack, use define to isolate it.
* problem is caused by scanfill removing edges on us. */
#define USE_SCANFILL_EDGE_WORKAROUND
@@ -575,11 +568,14 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
const float zvec[3] = {0.0f, 0.0f, 1.0f};
MaskLayer *masklay;
unsigned int masklay_index;
+ MemArena *sf_arena;
mr_handle->layers_tot = (unsigned int)BLI_countlist(&mask->masklayers);
mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, "MaskRasterLayer");
BLI_rctf_init_minmax(&mr_handle->bounds);
+ sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+
for (masklay = mask->masklayers.first, masklay_index = 0; masklay; masklay = masklay->next, masklay_index++) {
/* we need to store vertex ranges for open splines for filling */
@@ -613,7 +609,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
tot_splines = (unsigned int)BLI_countlist(&masklay->splines);
open_spline_ranges = MEM_callocN(sizeof(*open_spline_ranges) * tot_splines, __func__);
- BLI_scanfill_begin(&sf_ctx);
+ BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
for (spline = masklay->splines.first; spline; spline = spline->next) {
const unsigned int is_cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
@@ -1148,8 +1144,10 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
}
/* add trianges */
- BLI_scanfill_end(&sf_ctx);
+ BLI_scanfill_end_arena(&sf_ctx, sf_arena);
}
+
+ BLI_memarena_free(sf_arena);
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 1bda662a8b0..f3dc64a7279 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -573,6 +573,34 @@ static void material_data_index_clear_id(ID *id)
}
}
+void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user)
+{
+ Material ***matar = give_matarar_id(id);
+ short *totcolp = give_totcolp_id(id);
+
+ if (matar == NULL) {
+ return;
+ }
+
+ if (do_id_user && totcol < (*totcolp)) {
+ short i;
+ for (i = totcol; i < (*totcolp); i++) {
+ id_us_min((ID *)(*matar)[i]);
+ }
+ }
+
+ if (totcol == 0) {
+ if (*totcolp) {
+ MEM_freeN(*matar);
+ *matar = NULL;
+ }
+ }
+ else {
+ *matar = MEM_recallocN(*matar, sizeof(void *) * totcol);
+ }
+ *totcolp = totcol;
+}
+
void BKE_material_append_id(ID *id, Material *ma)
{
Material ***matar;
@@ -708,11 +736,18 @@ Material *give_node_material(Material *ma)
return NULL;
}
-void resize_object_material(Object *ob, const short totcol)
+void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user)
{
Material **newmatar;
char *newmatbits;
+ if (do_id_user && totcol < ob->totcol) {
+ short i;
+ for (i = totcol; i < ob->totcol; i++) {
+ id_us_min((ID *)ob->mat[i]);
+ }
+ }
+
if (totcol == 0) {
if (ob->totcol) {
MEM_freeN(ob->mat);
@@ -733,6 +768,8 @@ void resize_object_material(Object *ob, const short totcol)
ob->mat = newmatar;
ob->matbits = newmatbits;
}
+ /* XXX, why not realloc on shrink? - campbell */
+
ob->totcol = totcol;
if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
@@ -750,7 +787,7 @@ void test_object_materials(Main *bmain, ID *id)
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->data == id) {
- resize_object_material(ob, *totcol);
+ BKE_material_resize_object(ob, *totcol, false);
}
}
}
@@ -1254,7 +1291,9 @@ int object_remove_material_slot(Object *ob)
/* check indices from mesh */
if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
material_data_index_remove_id((ID *)ob->data, actcol - 1);
- BKE_displist_free(&ob->disp);
+ if (ob->curve_cache) {
+ BKE_displist_free(&ob->curve_cache->disp);
+ }
}
return TRUE;
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 173b193b752..a4b59153e2b 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -56,6 +56,7 @@
/* #include "BKE_object.h" */
#include "BKE_animsys.h"
+#include "BKE_curve.h"
#include "BKE_scene.h"
#include "BKE_library.h"
#include "BKE_displist.h"
@@ -199,7 +200,6 @@ void BKE_mball_free(MetaBall *mb)
mb->adt = NULL;
}
if (mb->mat) MEM_freeN(mb->mat);
- if (mb->bb) MEM_freeN(mb->bb);
BLI_freelistN(&mb->elems);
if (mb->disp.first) BKE_displist_free(&mb->disp);
}
@@ -233,7 +233,6 @@ MetaBall *BKE_mball_copy(MetaBall *mb)
for (a = 0; a < mbn->totcol; a++) {
id_us_plus((ID *)mbn->mat[a]);
}
- mbn->bb = MEM_dupallocN(mb->bb);
mbn->editelems = NULL;
mbn->lastelem = NULL;
@@ -366,7 +365,7 @@ void BKE_mball_texspace_calc(Object *ob)
(min)[0] = (min)[1] = (min)[2] = 1.0e30f;
(max)[0] = (max)[1] = (max)[2] = -1.0e30f;
- dl = ob->disp.first;
+ dl = ob->curve_cache->disp.first;
while (dl) {
tot = dl->nr;
if (tot) do_it = TRUE;
@@ -2281,7 +2280,7 @@ static void mball_count(PROCESS *process, Scene *scene, Object *basis)
}
}
-void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for_render)
{
MetaBall *mb;
DispList *dl;
@@ -2294,7 +2293,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
mball_count(&process, scene, ob);
if (process.totelem == 0) return;
- if ((G.is_rendering == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return;
+ if ((for_render == false) && (mb->flag == MB_UPDATE_NEVER)) return;
if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return;
process.thresh = mb->thresh;
@@ -2332,7 +2331,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
}
/* width is size per polygonize cube */
- if (G.is_rendering) {
+ if (for_render) {
width = mb->rendersize;
}
else {
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 0db1f92f70f..a77f768835a 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -27,12 +27,6 @@
* \ingroup bke
*/
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
@@ -40,22 +34,17 @@
#include "DNA_object_types.h"
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_ipo_types.h"
-#include "DNA_customdata_types.h"
#include "BLI_utildefines.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "BLI_edgehash.h"
-#include "BLI_bitmap.h"
-#include "BLI_scanfill.h"
-#include "BLI_array.h"
-#include "BLI_alloca.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string.h"
#include "BKE_animsys.h"
#include "BKE_main.h"
-#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -70,9 +59,7 @@
/* -- */
#include "BKE_object.h"
#include "BKE_editmesh.h"
-#include "BLI_edgehash.h"
-#include "bmesh.h"
enum {
MESHCMP_DVERT_WEIGHTMISMATCH = 1,
@@ -177,8 +164,8 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
if (l1->type == CD_MEDGE) {
MEdge *e1 = l1->data;
MEdge *e2 = l2->data;
- EdgeHash *eh = BLI_edgehash_new();
int etot = m1->totedge;
+ EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot);
for (j = 0; j < etot; j++, e1++) {
BLI_edgehash_insert(eh, e1->v1, e1->v2, e1);
@@ -274,7 +261,12 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
return 0;
}
-/*used for testing. returns an error string the two meshes don't match*/
+/**
+ * Used for unit testing; compares two meshes, checking only
+ * differences we care about. should be usable with leaf's
+ * testing framework I get RNA work done, will use hackish
+ * testing code for now.
+ */
const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
{
int c;
@@ -538,8 +530,9 @@ Mesh *BKE_mesh_copy(Mesh *me)
BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob)
{
BMesh *bm;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
- bm = BM_mesh_create(&bm_mesh_allocsize_default);
+ bm = BM_mesh_create(&allocsize);
BM_mesh_bm_from_me(bm, me, false, true, ob->shapenr);
@@ -632,6 +625,113 @@ void BKE_mesh_make_local(Mesh *me)
}
}
+bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int loop_index, const int face_index,
+ const char *new_name, const bool do_tessface)
+{
+ CustomData *pdata, *ldata, *fdata;
+ CustomDataLayer *cdlp, *cdlu, *cdlf;
+ const int step = do_tessface ? 3 : 2;
+ int i;
+
+ if (me->edit_btmesh) {
+ pdata = &me->edit_btmesh->bm->pdata;
+ ldata = &me->edit_btmesh->bm->ldata;
+ fdata = NULL; /* No tessellated data in BMesh! */
+ }
+ else {
+ pdata = &me->pdata;
+ ldata = &me->ldata;
+ fdata = &me->fdata;
+ }
+ cdlp = &pdata->layers[poly_index];
+ cdlu = &ldata->layers[loop_index];
+ cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL;
+
+ BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name));
+ CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+
+ /* Loop until we do have exactly the same name for all layers! */
+ for (i = 1; (strcmp(cdlp->name, cdlu->name) != 0 || (cdlf && strcmp(cdlp->name, cdlf->name) != 0)); i++) {
+ switch (i % step) {
+ case 0:
+ BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
+ CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+ break;
+ case 1:
+ BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name));
+ CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers);
+ break;
+ case 2:
+ if (cdlf) {
+ BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name));
+ CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers);
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface)
+{
+ CustomData *pdata, *ldata, *fdata;
+ if (me->edit_btmesh) {
+ pdata = &me->edit_btmesh->bm->pdata;
+ ldata = &me->edit_btmesh->bm->ldata;
+ /* No tessellated data in BMesh! */
+ fdata = NULL;
+ do_tessface = false;
+ }
+ else {
+ pdata = &me->pdata;
+ ldata = &me->ldata;
+ fdata = &me->fdata;
+ do_tessface = (do_tessface && fdata->totlayer);
+ }
+
+ {
+ const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY);
+ const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
+ const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
+ int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name);
+ int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
+ int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
+
+ /* None of those cases should happen, in theory!
+ * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
+ */
+ if (pidx == -1) {
+ if (lidx == -1) {
+ if (fidx == -1) {
+ /* No layer found with this name! */
+ return false;
+ }
+ else {
+ lidx = lidx_start + (fidx - fidx_start);
+ }
+ }
+ pidx = pidx_start + (lidx - lidx_start);
+ }
+ else {
+ if (lidx == -1) {
+ lidx = lidx_start + (pidx - pidx_start);
+ }
+ if (fidx == -1 && do_tessface) {
+ fidx = fidx_start + (pidx - pidx_start);
+ }
+ }
+#if 0
+ /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */
+ else if ((pidx - pidx_start) != (lidx - lidx_start)) {
+ lidx = lidx_start + (pidx - pidx_start);
+ }
+#endif
+
+ return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface);
+ }
+}
+
void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3])
{
BoundBox *bb;
@@ -657,6 +757,8 @@ void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3])
r_size[2] = (max[2] - min[2]) / 2.0f;
BKE_boundbox_init_from_minmax(bb, min, max);
+
+ bb->flag &= ~BOUNDBOX_DIRTY;
}
void BKE_mesh_texspace_calc(Mesh *me)
@@ -686,15 +788,16 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob)
if (ob->bb)
return ob->bb;
- if (!me->bb)
+ if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
BKE_mesh_texspace_calc(me);
+ }
return me->bb;
}
void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_size[3])
{
- if (!me->bb) {
+ if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
BKE_mesh_texspace_calc(me);
}
@@ -862,308 +965,6 @@ void BKE_mesh_assign_object(Object *ob, Mesh *me)
test_object_modifiers(ob);
}
-/* ************** make edges in a Mesh, for outside of editmode */
-
-struct EdgeSort {
- unsigned int v1, v2;
- char is_loose, is_draw;
-};
-
-/* edges have to be added with lowest index first for sorting */
-static void to_edgesort(struct EdgeSort *ed,
- unsigned int v1, unsigned int v2,
- char is_loose, short is_draw)
-{
- if (v1 < v2) {
- ed->v1 = v1; ed->v2 = v2;
- }
- else {
- ed->v1 = v2; ed->v2 = v1;
- }
- ed->is_loose = is_loose;
- ed->is_draw = is_draw;
-}
-
-static int vergedgesort(const void *v1, const void *v2)
-{
- const struct EdgeSort *x1 = v1, *x2 = v2;
-
- if (x1->v1 > x2->v1) return 1;
- else if (x1->v1 < x2->v1) return -1;
- else if (x1->v2 > x2->v2) return 1;
- else if (x1->v2 < x2->v2) return -1;
-
- return 0;
-}
-
-
-/* Create edges based on known verts and faces,
- * this function is only used when loading very old blend files */
-
-static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *allloop,
- MPoly *allpoly, int UNUSED(totvert), int totface, int UNUSED(totloop), int totpoly,
- const bool use_old,
- MEdge **r_medge, int *r_totedge)
-{
- MPoly *mpoly;
- MFace *mface;
- MEdge *medge, *med;
- EdgeHash *hash = BLI_edgehash_new();
- struct EdgeSort *edsort, *ed;
- int a, totedge = 0;
- unsigned int totedge_final = 0;
- unsigned int edge_index;
-
- /* we put all edges in array, sort them, and detect doubles that way */
-
- for (a = totface, mface = allface; a > 0; a--, mface++) {
- if (mface->v4) totedge += 4;
- else if (mface->v3) totedge += 3;
- else totedge += 1;
- }
-
- if (totedge == 0) {
- /* flag that mesh has edges */
- (*r_medge) = MEM_callocN(0, __func__);
- (*r_totedge) = 0;
- return;
- }
-
- ed = edsort = MEM_mallocN(totedge * sizeof(struct EdgeSort), "EdgeSort");
-
- for (a = totface, mface = allface; a > 0; a--, mface++) {
- to_edgesort(ed++, mface->v1, mface->v2, !mface->v3, mface->edcode & ME_V1V2);
- if (mface->v4) {
- to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3);
- to_edgesort(ed++, mface->v3, mface->v4, 0, mface->edcode & ME_V3V4);
- to_edgesort(ed++, mface->v4, mface->v1, 0, mface->edcode & ME_V4V1);
- }
- else if (mface->v3) {
- to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3);
- to_edgesort(ed++, mface->v3, mface->v1, 0, mface->edcode & ME_V3V1);
- }
- }
-
- qsort(edsort, totedge, sizeof(struct EdgeSort), vergedgesort);
-
- /* count final amount */
- for (a = totedge, ed = edsort; a > 1; a--, ed++) {
- /* edge is unique when it differs from next edge, or is last */
- if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) totedge_final++;
- }
- totedge_final++;
-
- medge = MEM_callocN(sizeof(MEdge) * totedge_final, __func__);
-
- for (a = totedge, med = medge, ed = edsort; a > 1; a--, ed++) {
- /* edge is unique when it differs from next edge, or is last */
- if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) {
- med->v1 = ed->v1;
- med->v2 = ed->v2;
- if (use_old == false || ed->is_draw) med->flag = ME_EDGEDRAW | ME_EDGERENDER;
- if (ed->is_loose) med->flag |= ME_LOOSEEDGE;
-
- /* order is swapped so extruding this edge as a surface wont flip face normals
- * with cyclic curves */
- if (ed->v1 + 1 != ed->v2) {
- SWAP(unsigned int, med->v1, med->v2);
- }
- med++;
- }
- else {
- /* equal edge, we merge the drawflag */
- (ed + 1)->is_draw |= ed->is_draw;
- }
- }
- /* last edge */
- med->v1 = ed->v1;
- med->v2 = ed->v2;
- med->flag = ME_EDGEDRAW;
- if (ed->is_loose) med->flag |= ME_LOOSEEDGE;
- med->flag |= ME_EDGERENDER;
-
- MEM_freeN(edsort);
-
- /* set edge members of mloops */
- for (edge_index = 0, med = medge; edge_index < totedge_final; edge_index++, med++) {
- BLI_edgehash_insert(hash, med->v1, med->v2, SET_UINT_IN_POINTER(edge_index));
- }
-
- mpoly = allpoly;
- for (a = 0; a < totpoly; a++, mpoly++) {
- MLoop *ml, *ml_next;
- int i = mpoly->totloop;
-
- ml_next = allloop + mpoly->loopstart; /* first loop */
- ml = &ml_next[i - 1]; /* last loop */
-
- while (i-- != 0) {
- ml->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(hash, ml->v, ml_next->v));
- ml = ml_next;
- ml_next++;
- }
- }
-
- BLI_edgehash_free(hash, NULL);
-
- *r_medge = medge;
- *r_totedge = totedge_final;
-}
-
-void BKE_mesh_make_edges(Mesh *me, const bool use_old)
-{
- MEdge *medge;
- int totedge = 0;
-
- make_edges_mdata(me->mvert, me->mface, me->mloop, me->mpoly,
- me->totvert, me->totface, me->totloop, me->totpoly,
- use_old, &medge, &totedge);
-
- if (totedge == 0) {
- /* flag that mesh has edges */
- me->medge = medge;
- me->totedge = 0;
- return;
- }
-
- medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge);
- me->medge = medge;
- me->totedge = totedge;
-
- BKE_mesh_strip_loose_faces(me);
-}
-
-/* We need to keep this for edge creation (for now?), and some old readfile code... */
-void BKE_mesh_strip_loose_faces(Mesh *me)
-{
- MFace *f;
- int a, b;
-
- for (a = b = 0, f = me->mface; a < me->totface; a++, f++) {
- if (f->v3) {
- if (a != b) {
- memcpy(&me->mface[b], f, sizeof(me->mface[b]));
- CustomData_copy_data(&me->fdata, &me->fdata, a, b, 1);
- }
- b++;
- }
- }
- if (a != b) {
- CustomData_free_elem(&me->fdata, b, a - b);
- me->totface = b;
- }
-}
-
-/* Works on both loops and polys! */
-/* Note: It won't try to guess which loops of an invalid poly to remove!
- * this is the work of the caller, to mark those loops...
- * See e.g. BKE_mesh_validate_arrays(). */
-void BKE_mesh_strip_loose_polysloops(Mesh *me)
-{
- MPoly *p;
- MLoop *l;
- int a, b;
- /* New loops idx! */
- int *new_idx = MEM_mallocN(sizeof(int) * me->totloop, __func__);
-
- for (a = b = 0, p = me->mpoly; a < me->totpoly; a++, p++) {
- int invalid = FALSE;
- int i = p->loopstart;
- int stop = i + p->totloop;
-
- if (stop > me->totloop || stop < i) {
- invalid = TRUE;
- }
- else {
- l = &me->mloop[i];
- i = stop - i;
- /* If one of the poly's loops is invalid, the whole poly is invalid! */
- for (; i--; l++) {
- if (l->e == INVALID_LOOP_EDGE_MARKER) {
- invalid = TRUE;
- break;
- }
- }
- }
-
- if (p->totloop >= 3 && !invalid) {
- if (a != b) {
- memcpy(&me->mpoly[b], p, sizeof(me->mpoly[b]));
- CustomData_copy_data(&me->pdata, &me->pdata, a, b, 1);
- }
- b++;
- }
- }
- if (a != b) {
- CustomData_free_elem(&me->pdata, b, a - b);
- me->totpoly = b;
- }
-
- /* And now, get rid of invalid loops. */
- for (a = b = 0, l = me->mloop; a < me->totloop; a++, l++) {
- if (l->e != INVALID_LOOP_EDGE_MARKER) {
- if (a != b) {
- memcpy(&me->mloop[b], l, sizeof(me->mloop[b]));
- CustomData_copy_data(&me->ldata, &me->ldata, a, b, 1);
- }
- new_idx[a] = b;
- b++;
- }
- else {
- /* XXX Theoretically, we should be able to not do this, as no remaining poly
- * should use any stripped loop. But for security's sake... */
- new_idx[a] = -a;
- }
- }
- if (a != b) {
- CustomData_free_elem(&me->ldata, b, a - b);
- me->totloop = b;
- }
-
- /* And now, update polys' start loop index. */
- /* Note: At this point, there should never be any poly using a striped loop! */
- for (a = 0, p = me->mpoly; a < me->totpoly; a++, p++) {
- p->loopstart = new_idx[p->loopstart];
- }
-
- MEM_freeN(new_idx);
-}
-
-void BKE_mesh_strip_loose_edges(Mesh *me)
-{
- MEdge *e;
- MLoop *l;
- int a, b;
- unsigned int *new_idx = MEM_mallocN(sizeof(int) * me->totedge, __func__);
-
- for (a = b = 0, e = me->medge; a < me->totedge; a++, e++) {
- if (e->v1 != e->v2) {
- if (a != b) {
- memcpy(&me->medge[b], e, sizeof(me->medge[b]));
- CustomData_copy_data(&me->edata, &me->edata, a, b, 1);
- }
- new_idx[a] = b;
- b++;
- }
- else {
- new_idx[a] = INVALID_LOOP_EDGE_MARKER;
- }
- }
- if (a != b) {
- CustomData_free_elem(&me->edata, b, a - b);
- me->totedge = b;
- }
-
- /* And now, update loops' edge indices. */
- /* XXX We hope no loop was pointing to a striped edge!
- * Else, its e will be set to INVALID_LOOP_EDGE_MARKER :/ */
- for (a = 0, l = me->mloop; a < me->totloop; a++, l++) {
- l->e = new_idx[l->e];
- }
-
- MEM_freeN(new_idx);
-}
-
void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
{
DispList *dl;
@@ -1237,10 +1038,12 @@ static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge,
int totedge = *r_totedge;
int totedge_new;
EdgeHash *eh;
+ unsigned int eh_reserve;
const MPoly *mp;
int i;
- eh = BLI_edgehash_new();
+ eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly));
+ eh = BLI_edgehash_new_ex(__func__, eh_reserve);
for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart);
@@ -1307,7 +1110,13 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
MEdge **alledge, int *totedge, MLoop **allloop, MPoly **allpoly,
int *totloop, int *totpoly)
{
- return BKE_mesh_nurbs_displist_to_mdata(ob, &ob->disp,
+ ListBase disp = {NULL, NULL};
+
+ if (ob->curve_cache) {
+ disp = ob->curve_cache->disp;
+ }
+
+ return BKE_mesh_nurbs_displist_to_mdata(ob, &disp,
allvert, totvert,
alledge, totedge,
allloop, allpoly, NULL,
@@ -1653,8 +1462,13 @@ void BKE_mesh_from_nurbs(Object *ob)
{
Curve *cu = (Curve *) ob->data;
bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
+ ListBase disp = {NULL, NULL};
+
+ if (ob->curve_cache) {
+ disp = ob->curve_cache->disp;
+ }
- BKE_mesh_from_nurbs_displist(ob, &ob->disp, use_orco_uv);
+ BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv);
}
typedef struct EdgeLink {
@@ -1914,445 +1728,10 @@ void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
}
}
-void BKE_mesh_calc_normals_mapping(MVert *mverts, int numVerts,
- MLoop *mloop, MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
- MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3])
-{
- BKE_mesh_calc_normals_mapping_ex(mverts, numVerts, mloop, mpolys,
- numLoops, numPolys, polyNors_r, mfaces, numFaces,
- origIndexFace, faceNors_r, FALSE);
-}
-
-void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, int numVerts,
- MLoop *mloop, MPoly *mpolys,
- int numLoops, int numPolys, float (*polyNors_r)[3],
- MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3],
- const bool only_face_normals)
-{
- float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r;
- int i;
- MFace *mf;
- MPoly *mp;
-
- if (numPolys == 0) {
- return;
- }
-
- /* if we are not calculating verts and no verts were passes then we have nothing to do */
- if ((only_face_normals == TRUE) && (polyNors_r == NULL) && (faceNors_r == NULL)) {
- printf("%s: called with nothing to do\n", __func__);
- return;
- }
-
- if (!pnors) pnors = MEM_callocN(sizeof(float) * 3 * numPolys, "poly_nors mesh.c");
- /* if (!fnors) fnors = MEM_callocN(sizeof(float) * 3 * numFaces, "face nors mesh.c"); */ /* NO NEED TO ALLOC YET */
-
-
- if (only_face_normals == FALSE) {
- /* vertex normals are optional, they require some extra calculations,
- * so make them optional */
- BKE_mesh_calc_normals_poly(mverts, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
- }
- else {
- /* only calc poly normals */
- mp = mpolys;
- for (i = 0; i < numPolys; i++, mp++) {
- BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]);
- }
- }
-
- if (origIndexFace &&
- /* fnors == faceNors_r */ /* NO NEED TO ALLOC YET */
- fnors != NULL &&
- numFaces)
- {
- mf = mfaces;
- for (i = 0; i < numFaces; i++, mf++, origIndexFace++) {
- if (*origIndexFace < numPolys) {
- copy_v3_v3(fnors[i], pnors[*origIndexFace]);
- }
- else {
- /* eek, we're not corresponding to polys */
- printf("error in %s: tessellation face indices are incorrect. normals may look bad.\n", __func__);
- }
- }
- }
-
- if (pnors != polyNors_r) MEM_freeN(pnors);
- /* if (fnors != faceNors_r) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */
-
- fnors = pnors = NULL;
-
-}
-
-static void mesh_calc_normals_poly_accum(MPoly *mp, MLoop *ml,
- MVert *mvert, float polyno[3], float (*tnorms)[3])
-{
- const int nverts = mp->totloop;
- float (*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, nverts);
- int i;
-
- /* Polygon Normal and edge-vector */
- /* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */
- {
- int i_prev = nverts - 1;
- float const *v_prev = mvert[ml[i_prev].v].co;
- float const *v_curr;
-
- zero_v3(polyno);
- /* Newell's Method */
- for (i = 0; i < nverts; i++) {
- v_curr = mvert[ml[i].v].co;
- add_newell_cross_v3_v3v3(polyno, v_prev, v_curr);
-
- /* Unrelated to normalize, calcualte edge-vector */
- sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr);
- normalize_v3(edgevecbuf[i_prev]);
- i_prev = i;
-
- v_prev = v_curr;
- }
- if (UNLIKELY(normalize_v3(polyno) == 0.0f)) {
- polyno[2] = 1.0f; /* other axis set to 0.0 */
- }
- }
-
- /* accumulate angle weighted face normal */
- /* inline version of #accumulate_vertex_normals_poly */
- {
- const float *prev_edge = edgevecbuf[nverts - 1];
-
- for (i = 0; i < nverts; i++) {
- const float *cur_edge = edgevecbuf[i];
-
- /* calculate angle between the two poly edges incident on
- * this vertex */
- const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
-
- /* accumulate */
- madd_v3_v3fl(tnorms[ml[i].v], polyno, fac);
- prev_edge = cur_edge;
- }
- }
-
-}
-
-void BKE_mesh_calc_normals_poly(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
- int UNUSED(numLoops), int numPolys, float (*r_polynors)[3],
- const bool only_face_normals)
-{
- float (*pnors)[3] = r_polynors;
- float (*tnorms)[3];
- int i;
- MPoly *mp;
-
- if (only_face_normals) {
- BLI_assert(pnors != NULL);
-
-#pragma omp parallel for if (numPolys > BM_OMP_LIMIT)
- for (i = 0; i < numPolys; i++) {
- BKE_mesh_calc_poly_normal(&mpolys[i], mloop + mpolys[i].loopstart, mverts, pnors[i]);
- }
- return;
- }
-
- /* first go through and calculate normals for all the polys */
- tnorms = MEM_callocN(sizeof(*tnorms) * numVerts, __func__);
-
- if (pnors) {
- mp = mpolys;
- for (i = 0; i < numPolys; i++, mp++) {
- mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], tnorms);
- }
- }
- else {
- float tpnor[3]; /* temp poly normal */
- mp = mpolys;
- for (i = 0; i < numPolys; i++, mp++) {
- mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, tnorms);
- }
- }
-
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
- for (i = 0; i < numVerts; i++) {
- MVert *mv = &mverts[i];
- float *no = tnorms[i];
-
- if (UNLIKELY(normalize_v3(no) == 0.0f)) {
- normalize_v3_v3(no, mv->co);
- }
-
- normal_float_to_short_v3(mv->no, no);
- }
-
- MEM_freeN(tnorms);
-}
-
-void BKE_mesh_calc_normals(Mesh *mesh)
-{
- BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert,
- mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
- NULL, false);
-}
-
-void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3])
-{
- float (*tnorms)[3] = MEM_callocN(numVerts * sizeof(*tnorms), "tnorms");
- float (*fnors)[3] = (faceNors_r) ? faceNors_r : MEM_callocN(sizeof(*fnors) * numFaces, "meshnormals");
- int i;
-
- for (i = 0; i < numFaces; i++) {
- MFace *mf = &mfaces[i];
- float *f_no = fnors[i];
- float *n4 = (mf->v4) ? tnorms[mf->v4] : NULL;
- float *c4 = (mf->v4) ? mverts[mf->v4].co : NULL;
-
- if (mf->v4)
- normal_quad_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co);
- else
- normal_tri_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co);
-
- accumulate_vertex_normals(tnorms[mf->v1], tnorms[mf->v2], tnorms[mf->v3], n4,
- f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, c4);
- }
-
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
- for (i = 0; i < numVerts; i++) {
- MVert *mv = &mverts[i];
- float *no = tnorms[i];
-
- if (UNLIKELY(normalize_v3(no) == 0.0f)) {
- normalize_v3_v3(no, mv->co);
- }
-
- normal_float_to_short_v3(mv->no, no);
- }
-
- MEM_freeN(tnorms);
-
- if (fnors != faceNors_r)
- MEM_freeN(fnors);
-}
-
-static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata,
- MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol)
-{
- MTFace *texface;
- MTexPoly *texpoly;
- MCol *mcol;
- MLoopCol *mloopcol;
- MLoopUV *mloopuv;
- MFace *mf;
- int i;
-
- mf = mface + findex;
-
- for (i = 0; i < numTex; i++) {
- texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
- texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, findex, i);
-
- ME_MTEXFACE_CPY(texpoly, texface);
-
- mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
- copy_v2_v2(mloopuv->uv, texface->uv[0]); mloopuv++;
- copy_v2_v2(mloopuv->uv, texface->uv[1]); mloopuv++;
- copy_v2_v2(mloopuv->uv, texface->uv[2]); mloopuv++;
-
- if (mf->v4) {
- copy_v2_v2(mloopuv->uv, texface->uv[3]); mloopuv++;
- }
- }
-
- for (i = 0; i < numCol; i++) {
- mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
- mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
-
- MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]); mloopcol++;
- MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[1]); mloopcol++;
- MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[2]); mloopcol++;
- if (mf->v4) {
- MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[3]); mloopcol++;
- }
- }
-
- if (CustomData_has_layer(fdata, CD_MDISPS)) {
- MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS);
- MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS);
- float (*disps)[3] = fd->disps;
- int tot = mf->v4 ? 4 : 3;
- int side, corners;
-
- if (CustomData_external_test(fdata, CD_MDISPS)) {
- if (id && fdata->external) {
- CustomData_external_add(ldata, id, CD_MDISPS,
- totloop, fdata->external->filename);
- }
- }
-
- corners = multires_mdisp_corners(fd);
-
- if (corners == 0) {
- /* Empty MDisp layers appear in at least one of the sintel.blend files.
- * Not sure why this happens, but it seems fine to just ignore them here.
- * If (corners == 0) for a non-empty layer though, something went wrong. */
- BLI_assert(fd->totdisp == 0);
- }
- else {
- side = sqrt(fd->totdisp / corners);
-
- for (i = 0; i < tot; i++, disps += side * side, ld++) {
- ld->totdisp = side * side;
- ld->level = (int)(logf(side - 1.0f) / (float)M_LN2) + 1;
-
- if (ld->disps)
- MEM_freeN(ld->disps);
-
- ld->disps = MEM_mallocN(sizeof(float) * 3 * side * side, "converted loop mdisps");
- if (fd->disps) {
- memcpy(ld->disps, disps, sizeof(float) * 3 * side * side);
- }
- else {
- memset(ld->disps, 0, sizeof(float) * 3 * side * side);
- }
- }
- }
- }
-}
-
-void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
-{
- BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id, &mesh->fdata, &mesh->ldata, &mesh->pdata,
- mesh->totedge, mesh->totface, mesh->totloop, mesh->totpoly,
- mesh->medge, mesh->mface,
- &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly);
-
- BKE_mesh_update_customdata_pointers(mesh, true);
-}
-
-/* the same as BKE_mesh_convert_mfaces_to_mpolys but oriented to be used in do_versions from readfile.c
- * the difference is how active/render/clone/stencil indices are handled here
- *
- * normally thay're being set from pdata which totally makes sense for meshes which are already
- * converted to bmesh structures, but when loading older files indices shall be updated in other
- * way around, so newly added pdata and ldata would have this indices set based on fdata layer
- *
- * this is normally only needed when reading older files, in all other cases BKE_mesh_convert_mfaces_to_mpolys
- * shall be always used
+/**
+ * Return a newly MEM_malloc'd array of all the mesh vertex locations
+ * \note \a numVerts_r may be NULL
*/
-void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
-{
- BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id, &mesh->fdata, &mesh->ldata, &mesh->pdata,
- mesh->totedge, mesh->totface, mesh->totloop, mesh->totpoly,
- mesh->medge, mesh->mface,
- &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly);
-
- CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->pdata, &mesh->ldata);
-
- BKE_mesh_update_customdata_pointers(mesh, true);
-}
-
-void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata,
- int totedge_i, int totface_i, int totloop_i, int totpoly_i,
- MEdge *medge, MFace *mface,
- int *totloop_r, int *totpoly_r,
- MLoop **mloop_r, MPoly **mpoly_r)
-{
- MFace *mf;
- MLoop *ml, *mloop;
- MPoly *mp, *mpoly;
- MEdge *me;
- EdgeHash *eh;
- int numTex, numCol;
- int i, j, totloop, totpoly, *polyindex;
-
- /* just in case some of these layers are filled in (can happen with python created meshes) */
- CustomData_free(ldata, totloop_i);
- CustomData_free(pdata, totpoly_i);
-
- totpoly = totface_i;
- mpoly = MEM_callocN(sizeof(MPoly) * totpoly, "mpoly converted");
- CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly);
-
- numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
- numCol = CustomData_number_of_layers(fdata, CD_MCOL);
-
- totloop = 0;
- mf = mface;
- for (i = 0; i < totface_i; i++, mf++) {
- totloop += mf->v4 ? 4 : 3;
- }
-
- mloop = MEM_callocN(sizeof(MLoop) * totloop, "mloop converted");
-
- CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop);
-
- CustomData_to_bmeshpoly(fdata, pdata, ldata, totloop, totpoly);
-
- if (id) {
- /* ensure external data is transferred */
- CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i);
- }
-
- eh = BLI_edgehash_new();
-
- /* build edge hash */
- me = medge;
- for (i = 0; i < totedge_i; i++, me++) {
- BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
-
- /* unrelated but avoid having the FGON flag enabled, so we can reuse it later for something else */
- me->flag &= ~ME_FGON;
- }
-
- polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
-
- j = 0; /* current loop index */
- ml = mloop;
- mf = mface;
- mp = mpoly;
- for (i = 0; i < totface_i; i++, mf++, mp++) {
- mp->loopstart = j;
-
- mp->totloop = mf->v4 ? 4 : 3;
-
- mp->mat_nr = mf->mat_nr;
- mp->flag = mf->flag;
-
-# define ML(v1, v2) { \
- ml->v = mf->v1; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); ml++; j++; \
- } (void)0
-
- ML(v1, v2);
- ML(v2, v3);
- if (mf->v4) {
- ML(v3, v4);
- ML(v4, v1);
- }
- else {
- ML(v3, v1);
- }
-
-# undef ML
-
- bm_corners_to_loops_ex(id, fdata, ldata, pdata, mface, totloop, i, mp->loopstart, numTex, numCol);
-
- if (polyindex) {
- *polyindex = i;
- polyindex++;
- }
- }
-
- /* note, we don't convert NGons at all, these are not even real ngons,
- * they have their own UV's, colors etc - its more an editing feature. */
-
- BLI_edgehash_free(eh, NULL);
-
- *totpoly_r = totpoly;
- *totloop_r = totloop;
- *mpoly_r = mpoly;
- *mloop_r = mloop;
-}
-
float (*BKE_mesh_vertexCos_get(Mesh *me, int *r_numVerts))[3]
{
int i, numVerts = me->totvert;
@@ -2365,1069 +1744,10 @@ float (*BKE_mesh_vertexCos_get(Mesh *me, int *r_numVerts))[3]
return cos;
}
-
-/* ngon version wip, based on EDBM_uv_vert_map_create */
-/* this replaces the non bmesh function (in trunk) which takes MTFace's, if we ever need it back we could
- * but for now this replaces it because its unused. */
-
-UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
- unsigned int totpoly, unsigned int totvert, int selected, float *limit)
-{
- UvVertMap *vmap;
- UvMapVert *buf;
- MPoly *mp;
- unsigned int a;
- int i, totuv, nverts;
-
- totuv = 0;
-
- /* generate UvMapVert array */
- mp = mpoly;
- for (a = 0; a < totpoly; a++, mp++)
- if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL)))
- totuv += mp->totloop;
-
- if (totuv == 0)
- return NULL;
-
- vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
- if (!vmap)
- return NULL;
-
- vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*");
- buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert");
-
- if (!vmap->vert || !vmap->buf) {
- BKE_mesh_uv_vert_map_free(vmap);
- return NULL;
- }
-
- mp = mpoly;
- for (a = 0; a < totpoly; a++, mp++) {
- if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
- nverts = mp->totloop;
-
- for (i = 0; i < nverts; i++) {
- buf->tfindex = i;
- buf->f = a;
- buf->separate = 0;
- buf->next = vmap->vert[mloop[mp->loopstart + i].v];
- vmap->vert[mloop[mp->loopstart + i].v] = buf;
- buf++;
- }
- }
- }
-
- /* sort individual uvs for each vert */
- for (a = 0; a < totvert; a++) {
- UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
- UvMapVert *iterv, *v, *lastv, *next;
- float *uv, *uv2, uvdiff[2];
-
- while (vlist) {
- v = vlist;
- vlist = vlist->next;
- v->next = newvlist;
- newvlist = v;
-
- uv = mloopuv[mpoly[v->f].loopstart + v->tfindex].uv;
- lastv = NULL;
- iterv = vlist;
-
- while (iterv) {
- next = iterv->next;
-
- uv2 = mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv;
- sub_v2_v2v2(uvdiff, uv2, uv);
-
-
- if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1]) {
- if (lastv) lastv->next = next;
- else vlist = next;
- iterv->next = newvlist;
- newvlist = iterv;
- }
- else
- lastv = iterv;
-
- iterv = next;
- }
-
- newvlist->separate = 1;
- }
-
- vmap->vert[a] = newvlist;
- }
-
- return vmap;
-}
-
-UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v)
-{
- return vmap->vert[v];
-}
-
-void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
-{
- if (vmap) {
- if (vmap->vert) MEM_freeN(vmap->vert);
- if (vmap->buf) MEM_freeN(vmap->buf);
- MEM_freeN(vmap);
- }
-}
-
-/* Generates a map where the key is the vertex and the value is a list
- * of polys that use that vertex as a corner. The lists are allocated
- * from one memory pool. */
-void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
- const MPoly *mpoly, const MLoop *mloop,
- int totvert, int totpoly, int totloop)
-{
- MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * totvert, "vert poly map");
- int *indices, *index_iter;
- int i, j;
-
- indices = index_iter = MEM_mallocN(sizeof(int) * totloop, "vert poly map mem");
-
- /* Count number of polys for each vertex */
- for (i = 0; i < totpoly; i++) {
- const MPoly *p = &mpoly[i];
-
- for (j = 0; j < p->totloop; j++)
- map[mloop[p->loopstart + j].v].count++;
- }
-
- /* Assign indices mem */
- for (i = 0; i < totvert; i++) {
- map[i].indices = index_iter;
- index_iter += map[i].count;
-
- /* Reset 'count' for use as index in last loop */
- map[i].count = 0;
- }
-
- /* Find the users */
- for (i = 0; i < totpoly; i++) {
- const MPoly *p = &mpoly[i];
-
- for (j = 0; j < p->totloop; j++) {
- int v = mloop[p->loopstart + j].v;
-
- map[v].indices[map[v].count] = i;
- map[v].count++;
- }
- }
-
- *r_map = map;
- *r_mem = indices;
-}
-
-/* Generates a map where the key is the vertex and the value is a list
- * of edges that use that vertex as an endpoint. The lists are allocated
- * from one memory pool. */
-void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
- const MEdge *medge, int totvert, int totedge)
-{
- MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * totvert, "vert-edge map");
- int *indices = MEM_mallocN(sizeof(int) * totedge * 2, "vert-edge map mem");
- int *i_pt = indices;
-
- int i;
-
- /* Count number of edges for each vertex */
- for (i = 0; i < totedge; i++) {
- map[medge[i].v1].count++;
- map[medge[i].v2].count++;
- }
-
- /* Assign indices mem */
- for (i = 0; i < totvert; i++) {
- map[i].indices = i_pt;
- i_pt += map[i].count;
-
- /* Reset 'count' for use as index in last loop */
- map[i].count = 0;
- }
-
- /* Find the users */
- for (i = 0; i < totedge; i++) {
- const int v[2] = {medge[i].v1, medge[i].v2};
-
- map[v[0]].indices[map[v[0]].count] = i;
- map[v[1]].indices[map[v[1]].count] = i;
-
- map[v[0]].count++;
- map[v[1]].count++;
- }
-
- *r_map = map;
- *r_mem = indices;
-}
-
-void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem,
- const MEdge *UNUSED(medge), const int totedge,
- const MPoly *mpoly, const int totpoly,
- const MLoop *mloop, const int totloop)
-{
- MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * totedge, "edge-poly map");
- int *indices = MEM_mallocN(sizeof(int) * totloop, "edge-poly map mem");
- int *index_step;
- const MPoly *mp;
- int i;
-
- /* count face users */
- for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
- const MLoop *ml;
- int j = mp->totloop;
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- map[ml->e].count++;
- }
- }
-
- /* create offsets */
- index_step = indices;
- for (i = 0; i < totedge; i++) {
- map[i].indices = index_step;
- index_step += map[i].count;
-
- /* re-count, using this as an index below */
- map[i].count = 0;
-
- }
-
- /* assign poly-edge users */
- for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
- const MLoop *ml;
- int j = mp->totloop;
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- MeshElemMap *map_ele = &map[ml->e];
- map_ele->indices[map_ele->count++] = i;
- }
- }
-
- *r_map = map;
- *r_mem = indices;
-}
-
-void BKE_mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata,
- CustomData *pdata, int lindex[4], int findex,
- const int polyindex,
- const int mf_len, /* 3 or 4 */
-
- /* cache values to avoid lookups every time */
- const int numTex, /* CustomData_number_of_layers(pdata, CD_MTEXPOLY) */
- const int numCol, /* CustomData_number_of_layers(ldata, CD_MLOOPCOL) */
- const int hasPCol, /* CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL) */
- const int hasOrigSpace /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */
- )
-{
- MTFace *texface;
- MTexPoly *texpoly;
- MCol *mcol;
- MLoopCol *mloopcol;
- MLoopUV *mloopuv;
- int i, j;
-
- for (i = 0; i < numTex; i++) {
- texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
- texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
-
- ME_MTEXFACE_CPY(texface, texpoly);
-
- for (j = 0; j < mf_len; j++) {
- mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i);
- copy_v2_v2(texface->uv[j], mloopuv->uv);
- }
- }
-
- for (i = 0; i < numCol; i++) {
- mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
-
- for (j = 0; j < mf_len; j++) {
- mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i);
- MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
- }
- }
-
- if (hasPCol) {
- mcol = CustomData_get(fdata, findex, CD_PREVIEW_MCOL);
-
- for (j = 0; j < mf_len; j++) {
- mloopcol = CustomData_get(ldata, lindex[j], CD_PREVIEW_MLOOPCOL);
- MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
- }
- }
-
- if (hasOrigSpace) {
- OrigSpaceFace *of = CustomData_get(fdata, findex, CD_ORIGSPACE);
- OrigSpaceLoop *lof;
-
- for (j = 0; j < mf_len; j++) {
- lof = CustomData_get(ldata, lindex[j], CD_ORIGSPACE_MLOOP);
- copy_v2_v2(of->uv[j], lof->uv);
- }
- }
-}
-
-/*
- * this function recreates a tessellation.
- * returns number of tessellation faces.
- */
-int BKE_mesh_recalc_tessellation(CustomData *fdata,
- CustomData *ldata, CustomData *pdata,
- MVert *mvert, int totface, int totloop,
- int totpoly,
- /* when tessellating to recalculate normals after
- * we can skip copying here */
- const bool do_face_nor_cpy)
-{
- /* use this to avoid locking pthread for _every_ polygon
- * and calling the fill function */
-
-#define USE_TESSFACE_SPEEDUP
-#define USE_TESSFACE_QUADS // NEEDS FURTHER TESTING
-
-#define TESSFACE_SCANFILL (1 << 0)
-#define TESSFACE_IS_QUAD (1 << 1)
-
- const int looptris_tot = poly_to_tri_count(totpoly, totloop);
-
- MPoly *mp, *mpoly;
- MLoop *ml, *mloop;
- MFace *mface, *mf;
- ScanFillContext sf_ctx;
- ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first;
- ScanFillFace *sf_tri;
- int *mface_to_poly_map;
- int lindex[4]; /* only ever use 3 in this case */
- int poly_index, j, mface_index;
-
- const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
- const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
- const int hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
- const int hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
-
- mpoly = CustomData_get_layer(pdata, CD_MPOLY);
- mloop = CustomData_get_layer(ldata, CD_MLOOP);
-
- /* allocate the length of totfaces, avoid many small reallocs,
- * if all faces are tri's it will be correct, quads == 2x allocs */
- /* take care. we are _not_ calloc'ing so be sure to initialize each field */
- mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * looptris_tot, __func__);
- mface = MEM_mallocN(sizeof(*mface) * looptris_tot, __func__);
-
- mface_index = 0;
- mp = mpoly;
- for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
- if (mp->totloop < 3) {
- /* do nothing */
- }
-
-#ifdef USE_TESSFACE_SPEEDUP
-
-#define ML_TO_MF(i1, i2, i3) \
- mface_to_poly_map[mface_index] = poly_index; \
- mf = &mface[mface_index]; \
- /* set loop indices, transformed to vert indices later */ \
- mf->v1 = mp->loopstart + i1; \
- mf->v2 = mp->loopstart + i2; \
- mf->v3 = mp->loopstart + i3; \
- mf->v4 = 0; \
- mf->mat_nr = mp->mat_nr; \
- mf->flag = mp->flag; \
- mf->edcode = 0; \
- (void)0
-
-/* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */
-#define ML_TO_MF_QUAD() \
- mface_to_poly_map[mface_index] = poly_index; \
- mf = &mface[mface_index]; \
- /* set loop indices, transformed to vert indices later */ \
- mf->v1 = mp->loopstart + 0; /* EXCEPTION */ \
- mf->v2 = mp->loopstart + 1; /* EXCEPTION */ \
- mf->v3 = mp->loopstart + 2; /* EXCEPTION */ \
- mf->v4 = mp->loopstart + 3; /* EXCEPTION */ \
- mf->mat_nr = mp->mat_nr; \
- mf->flag = mp->flag; \
- mf->edcode = TESSFACE_IS_QUAD; /* EXCEPTION */ \
- (void)0
-
-
- else if (mp->totloop == 3) {
- ML_TO_MF(0, 1, 2);
- mface_index++;
- }
- else if (mp->totloop == 4) {
-#ifdef USE_TESSFACE_QUADS
- ML_TO_MF_QUAD();
- mface_index++;
-#else
- ML_TO_MF(0, 1, 2);
- mface_index++;
- ML_TO_MF(0, 2, 3);
- mface_index++;
-#endif
- }
-#endif /* USE_TESSFACE_SPEEDUP */
- else {
-#define USE_TESSFACE_CALCNORMAL
-
- int totfilltri;
-
-#ifdef USE_TESSFACE_CALCNORMAL
- float normal[3];
- zero_v3(normal);
-#endif
- ml = mloop + mp->loopstart;
-
- BLI_scanfill_begin(&sf_ctx);
- sf_vert_first = NULL;
- sf_vert_last = NULL;
- for (j = 0; j < mp->totloop; j++, ml++) {
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, mvert[ml->v].co);
-
- sf_vert->keyindex = mp->loopstart + j;
-
- if (sf_vert_last) {
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
-#ifdef USE_TESSFACE_CALCNORMAL
- add_newell_cross_v3_v3v3(normal, sf_vert_last->co, sf_vert->co);
-#endif
- }
-
- if (!sf_vert_first)
- sf_vert_first = sf_vert;
- sf_vert_last = sf_vert;
- }
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first);
-#ifdef USE_TESSFACE_CALCNORMAL
- add_newell_cross_v3_v3v3(normal, sf_vert_last->co, sf_vert_first->co);
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- normal[2] = 1.0f;
- }
- totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, normal);
-#else
- totfilltri = BLI_scanfill_calc(&sf_ctx, 0);
-#endif
- BLI_assert(totfilltri <= mp->totloop - 2);
- (void)totfilltri;
-
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) {
- mface_to_poly_map[mface_index] = poly_index;
- mf = &mface[mface_index];
-
- /* set loop indices, transformed to vert indices later */
- mf->v1 = sf_tri->v1->keyindex;
- mf->v2 = sf_tri->v2->keyindex;
- mf->v3 = sf_tri->v3->keyindex;
- mf->v4 = 0;
-
- mf->mat_nr = mp->mat_nr;
- mf->flag = mp->flag;
-
-#ifdef USE_TESSFACE_SPEEDUP
- mf->edcode = TESSFACE_SCANFILL; /* tag for sorting loop indices */
-#endif
-
- mface_index++;
- }
-
- BLI_scanfill_end(&sf_ctx);
-
-#undef USE_TESSFACE_CALCNORMAL
- }
- }
-
- CustomData_free(fdata, totface);
- totface = mface_index;
-
- BLI_assert(totface <= looptris_tot);
-
- /* not essential but without this we store over-alloc'd memory in the CustomData layers */
- if (LIKELY(looptris_tot != totface)) {
- mface = MEM_reallocN(mface, sizeof(*mface) * totface);
- mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * totface);
- }
-
- CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
-
- /* CD_ORIGINDEX will contain an array of indices from tessfaces to the polygons
- * they are directly tessellated from */
- CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
- CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
-
- if (do_face_nor_cpy) {
- /* If polys have a normals layer, copying that to faces can help
- * avoid the need to recalculate normals later */
- if (CustomData_has_layer(pdata, CD_NORMAL)) {
- float (*pnors)[3] = CustomData_get_layer(pdata, CD_NORMAL);
- float (*fnors)[3] = CustomData_add_layer(fdata, CD_NORMAL, CD_CALLOC, NULL, totface);
- for (mface_index = 0; mface_index < totface; mface_index++) {
- copy_v3_v3(fnors[mface_index], pnors[mface_to_poly_map[mface_index]]);
- }
- }
- }
-
- mf = mface;
- for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
-
-#ifdef USE_TESSFACE_QUADS
- const int mf_len = mf->edcode & TESSFACE_IS_QUAD ? 4 : 3;
-#endif
-
-#ifdef USE_TESSFACE_SPEEDUP
- /* skip sorting when not using ngons */
- if (UNLIKELY(mf->edcode & TESSFACE_SCANFILL))
-#endif
- {
- /* sort loop indices to ensure winding is correct */
- if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
- if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3);
- if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
-
- if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
- if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3);
- if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
- }
-
- /* end abusing the edcode */
-#if defined(USE_TESSFACE_QUADS) || defined(USE_TESSFACE_SPEEDUP)
- mf->edcode = 0;
-#endif
-
-
- lindex[0] = mf->v1;
- lindex[1] = mf->v2;
- lindex[2] = mf->v3;
-#ifdef USE_TESSFACE_QUADS
- if (mf_len == 4) lindex[3] = mf->v4;
-#endif
-
- /*transform loop indices to vert indices*/
- mf->v1 = mloop[mf->v1].v;
- mf->v2 = mloop[mf->v2].v;
- mf->v3 = mloop[mf->v3].v;
-#ifdef USE_TESSFACE_QUADS
- if (mf_len == 4) mf->v4 = mloop[mf->v4].v;
-#endif
-
- BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
- lindex, mface_index, mface_to_poly_map[mface_index],
-#ifdef USE_TESSFACE_QUADS
- mf_len,
-#else
- 3,
-#endif
- numTex, numCol, hasPCol, hasOrigSpace);
-
-
-#ifdef USE_TESSFACE_QUADS
- test_index_face(mf, fdata, mface_index, mf_len);
-#endif
-
- }
-
- return totface;
-
-#undef USE_TESSFACE_SPEEDUP
-
-}
-
-
-#ifdef USE_BMESH_SAVE_AS_COMPAT
-
-/*
- * this function recreates a tessellation.
- * returns number of tessellation faces.
- */
-int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
- struct CustomData *pdata, int totface, int UNUSED(totloop), int totpoly)
-{
- MLoop *mloop;
-
- int lindex[4];
- int i;
- int k;
-
- MPoly *mp, *mpoly;
- MFace *mface = NULL, *mf;
- BLI_array_declare(mface);
-
- const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
- const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
- const int hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
- const int hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
-
- mpoly = CustomData_get_layer(pdata, CD_MPOLY);
- mloop = CustomData_get_layer(ldata, CD_MLOOP);
-
- mp = mpoly;
- k = 0;
- for (i = 0; i < totpoly; i++, mp++) {
- if (ELEM(mp->totloop, 3, 4)) {
- BLI_array_grow_one(mface);
- mf = &mface[k];
-
- mf->mat_nr = mp->mat_nr;
- mf->flag = mp->flag;
-
- mf->v1 = mp->loopstart + 0;
- mf->v2 = mp->loopstart + 1;
- mf->v3 = mp->loopstart + 2;
- mf->v4 = (mp->totloop == 4) ? (mp->loopstart + 3) : 0;
-
- /* abuse edcode for temp storage and clear next loop */
- mf->edcode = (char)mp->totloop; /* only ever 3 or 4 */
-
- k++;
- }
- }
-
- CustomData_free(fdata, totface);
-
- totface = k;
-
- CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
-
- CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
-
- mp = mpoly;
- k = 0;
- for (i = 0; i < totpoly; i++, mp++) {
- if (ELEM(mp->totloop, 3, 4)) {
- mf = &mface[k];
-
- if (mf->edcode == 3) {
- /* sort loop indices to ensure winding is correct */
- /* NO SORT - looks like we can skip this */
-
- lindex[0] = mf->v1;
- lindex[1] = mf->v2;
- lindex[2] = mf->v3;
- lindex[3] = 0; /* unused */
-
- /* transform loop indices to vert indices */
- mf->v1 = mloop[mf->v1].v;
- mf->v2 = mloop[mf->v2].v;
- mf->v3 = mloop[mf->v3].v;
-
- BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
- lindex, k, i, 3,
- numTex, numCol, hasPCol, hasOrigSpace);
- test_index_face(mf, fdata, k, 3);
- }
- else {
- /* sort loop indices to ensure winding is correct */
- /* NO SORT - looks like we can skip this */
-
- lindex[0] = mf->v1;
- lindex[1] = mf->v2;
- lindex[2] = mf->v3;
- lindex[3] = mf->v4;
-
- /* transform loop indices to vert indices */
- mf->v1 = mloop[mf->v1].v;
- mf->v2 = mloop[mf->v2].v;
- mf->v3 = mloop[mf->v3].v;
- mf->v4 = mloop[mf->v4].v;
-
- BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
- lindex, k, i, 4,
- numTex, numCol, hasPCol, hasOrigSpace);
- test_index_face(mf, fdata, k, 4);
- }
-
- mf->edcode = 0;
-
- k++;
- }
- }
-
- return k;
-}
-#endif /* USE_BMESH_SAVE_AS_COMPAT */
-
-/*
- * COMPUTE POLY NORMAL
- *
- * Computes the normal of a planar
- * polygon See Graphics Gems for
- * computing newell normal.
- *
- */
-static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
- MVert *mvert, float normal[3])
-{
- const int nverts = mpoly->totloop;
- float const *v_prev = mvert[loopstart[nverts - 1].v].co;
- float const *v_curr;
- int i;
-
- zero_v3(normal);
-
- /* Newell's Method */
- for (i = 0; i < nverts; i++) {
- v_curr = mvert[loopstart[i].v].co;
- add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
- v_prev = v_curr;
- }
-
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- normal[2] = 1.0f; /* other axis set to 0.0 */
- }
-}
-
-void BKE_mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, float no[3])
-{
- if (mpoly->totloop > 4) {
- mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no);
- }
- else if (mpoly->totloop == 3) {
- normal_tri_v3(no,
- mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co
- );
- }
- else if (mpoly->totloop == 4) {
- normal_quad_v3(no,
- mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co,
- mvarray[loopstart[3].v].co
- );
- }
- else { /* horrible, two sided face! */
- no[0] = 0.0;
- no[1] = 0.0;
- no[2] = 1.0;
- }
-}
-/* duplicate of function above _but_ takes coords rather then mverts */
-static void mesh_calc_ngon_normal_coords(MPoly *mpoly, MLoop *loopstart,
- const float (*vertex_coords)[3], float normal[3])
-{
- const int nverts = mpoly->totloop;
- float const *v_prev = vertex_coords[loopstart[nverts - 1].v];
- float const *v_curr;
- int i;
-
- zero_v3(normal);
-
- /* Newell's Method */
- for (i = 0; i < nverts; i++) {
- v_curr = vertex_coords[loopstart[i].v];
- add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
- v_prev = v_curr;
- }
-
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- normal[2] = 1.0f; /* other axis set to 0.0 */
- }
-}
-
-void BKE_mesh_calc_poly_normal_coords(MPoly *mpoly, MLoop *loopstart,
- const float (*vertex_coords)[3], float no[3])
-{
- if (mpoly->totloop > 4) {
- mesh_calc_ngon_normal_coords(mpoly, loopstart, vertex_coords, no);
- }
- else if (mpoly->totloop == 3) {
- normal_tri_v3(no,
- vertex_coords[loopstart[0].v],
- vertex_coords[loopstart[1].v],
- vertex_coords[loopstart[2].v]
- );
- }
- else if (mpoly->totloop == 4) {
- normal_quad_v3(no,
- vertex_coords[loopstart[0].v],
- vertex_coords[loopstart[1].v],
- vertex_coords[loopstart[2].v],
- vertex_coords[loopstart[3].v]
- );
- }
- else { /* horrible, two sided face! */
- no[0] = 0.0;
- no[1] = 0.0;
- no[2] = 1.0;
- }
-}
-
-static void mesh_calc_ngon_center(MPoly *mpoly, MLoop *loopstart,
- MVert *mvert, float cent[3])
-{
- const float w = 1.0f / (float)mpoly->totloop;
- int i;
-
- zero_v3(cent);
-
- for (i = 0; i < mpoly->totloop; i++) {
- madd_v3_v3fl(cent, mvert[(loopstart++)->v].co, w);
- }
-}
-
-void BKE_mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, float cent[3])
-{
- if (mpoly->totloop == 3) {
- cent_tri_v3(cent,
- mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co
- );
- }
- else if (mpoly->totloop == 4) {
- cent_quad_v3(cent,
- mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co,
- mvarray[loopstart[3].v].co
- );
- }
- else {
- mesh_calc_ngon_center(mpoly, loopstart, mvarray, cent);
- }
-}
-
-/* note, passing polynormal is only a speedup so we can skip calculating it */
-float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, const float polynormal[3])
-{
- if (mpoly->totloop == 3) {
- return area_tri_v3(mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co
- );
- }
- else if (mpoly->totloop == 4) {
- return area_quad_v3(mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co,
- mvarray[loopstart[3].v].co
- );
- }
- else {
- int i;
- MLoop *l_iter = loopstart;
- float area, polynorm_local[3];
- float (*vertexcos)[3] = BLI_array_alloca(vertexcos, mpoly->totloop);
- const float *no = polynormal ? polynormal : polynorm_local;
-
- /* pack vertex cos into an array for area_poly_v3 */
- for (i = 0; i < mpoly->totloop; i++, l_iter++) {
- copy_v3_v3(vertexcos[i], mvarray[l_iter->v].co);
- }
-
- /* need normal for area_poly_v3 as well */
- if (polynormal == NULL) {
- BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, polynorm_local);
- }
-
- /* finally calculate the area */
- area = area_poly_v3(mpoly->totloop, vertexcos, no);
-
- return area;
- }
-}
-
-/* note, results won't be correct if polygon is non-planar */
-static float mesh_calc_poly_planar_area_centroid(MPoly *mpoly, MLoop *loopstart, MVert *mvarray, float cent[3])
-{
- int i;
- float tri_area;
- float total_area = 0.0f;
- float v1[3], v2[3], v3[3], normal[3], tri_cent[3];
-
- BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal);
- copy_v3_v3(v1, mvarray[loopstart[0].v].co);
- copy_v3_v3(v2, mvarray[loopstart[1].v].co);
- zero_v3(cent);
-
- for (i = 2; i < mpoly->totloop; i++) {
- copy_v3_v3(v3, mvarray[loopstart[i].v].co);
-
- tri_area = area_tri_signed_v3(v1, v2, v3, normal);
- total_area += tri_area;
-
- cent_tri_v3(tri_cent, v1, v2, v3);
- madd_v3_v3fl(cent, tri_cent, tri_area);
-
- copy_v3_v3(v2, v3);
- }
-
- mul_v3_fl(cent, 1.0f / total_area);
-
- return total_area;
-}
-
/**
- * Calculate smooth groups from sharp edges.
- *
- * \param r_totgroup The total number of groups, 1 or more.
- * \return Polygon aligned array of group index values (starting at 1)
+ * Find the index of the loop in 'poly' which references vertex,
+ * returns -1 if not found
*/
-int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
- const MPoly *mpoly, const int totpoly,
- const MLoop *mloop, const int totloop,
- int *r_totgroup)
-{
- int *poly_groups;
- int *poly_stack;
- STACK_DECLARE(poly_stack);
-
- int poly_prev = 0;
- int poly_group_id = 0;
-
- /* map vars */
- MeshElemMap *edge_poly_map;
- int *edge_poly_mem;
-
- if (totpoly == 0) {
- *r_totgroup = 0;
- return NULL;
- }
-
- BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
- medge, totedge,
- mpoly, totpoly,
- mloop, totloop);
-
- poly_groups = MEM_callocN(sizeof(int) * totpoly, __func__);
- poly_stack = MEM_mallocN(sizeof(int) * totpoly, __func__);
-
- STACK_INIT(poly_stack);
-
- while (true) {
- int poly;
-
- for (poly = poly_prev; poly < totpoly; poly++) {
- if (poly_groups[poly] == 0) {
- break;
- }
- }
-
- if (poly == totpoly) {
- /* all done */
- break;
- }
-
- /* start searching from here next time */
- poly_prev = poly + 1;
-
- /* group starts at 1 */
- poly_group_id++;
-
- poly_groups[poly] = poly_group_id;
- STACK_PUSH(poly_stack, poly);
-
- while ((poly = STACK_POP_ELSE(poly_stack, -1)) != -1) {
-
- const MPoly *mp = &mpoly[poly];
- const MLoop *ml;
- int j = mp->totloop;
-
- BLI_assert(poly_groups[poly] == poly_group_id);
-
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- if (!(medge[ml->e].flag & ME_SHARP)) {
- /* loop over poly users */
- const MeshElemMap *map_ele = &edge_poly_map[ml->e];
- int *p = map_ele->indices;
- int i = map_ele->count;
-
- for (; i--; p++) {
- /* if we meet other non initialized its a bug */
- BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
-
- if (poly_groups[*p] == 0) {
- poly_groups[*p] = poly_group_id;
- STACK_PUSH(poly_stack, *p);
- }
- }
- }
- }
- }
- }
-
- MEM_freeN(edge_poly_map);
- MEM_freeN(edge_poly_mem);
- MEM_freeN(poly_stack);
-
- STACK_FREE(poly_stack);
-
- *r_totgroup = poly_group_id;
-
- return poly_groups;
-}
-
-
-
-/**
- * This function takes the difference between 2 vertex-coord-arrays
- * (\a vert_cos_src, \a vert_cos_dst),
- * and applies the difference to \a vert_cos_new relative to \a vert_cos_org.
- *
- * \param vert_cos_src reference deform source.
- * \param vert_cos_dst reference deform destination.
- *
- * \param vert_cos_org reference for the output location.
- * \param vert_cos_new resulting coords.
- */
-void BKE_mesh_calc_relative_deform(
- const MPoly *mpoly, const int totpoly,
- const MLoop *mloop, const int totvert,
-
- const float (*vert_cos_src)[3],
- const float (*vert_cos_dst)[3],
-
- const float (*vert_cos_org)[3],
- float (*vert_cos_new)[3])
-{
- const MPoly *mp;
- int i;
-
- int *vert_accum = MEM_callocN(sizeof(*vert_accum) * totvert, __func__);
-
- memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * totvert);
-
- for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
- const MLoop *loopstart = mloop + mp->loopstart;
- int j;
-
- for (j = 0; j < mp->totloop; j++) {
- int v_prev = (loopstart + ((mp->totloop + (j - 1)) % mp->totloop))->v;
- int v_curr = (loopstart + j)->v;
- int v_next = (loopstart + ((j + 1) % mp->totloop))->v;
-
- float tvec[3];
-
- barycentric_transform(
- tvec, vert_cos_dst[v_curr],
- vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
- vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]
- );
-
- add_v3_v3(vert_cos_new[v_curr], tvec);
- vert_accum[v_curr] += 1;
- }
- }
-
- for (i = 0; i < totvert; i++) {
- if (vert_accum[i]) {
- mul_v3_fl(vert_cos_new[i], 1.0f / (float)vert_accum[i]);
- }
- else {
- copy_v3_v3(vert_cos_new[i], vert_cos_org[i]);
- }
- }
-
- MEM_freeN(vert_accum);
-}
-
-/* Find the index of the loop in 'poly' which references vertex,
- * returns -1 if not found */
int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
unsigned vert)
{
@@ -3440,9 +1760,11 @@ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
return -1;
}
-/* Fill 'adj_r' with the loop indices in 'poly' adjacent to the
+/**
+ * Fill \a adj_r with the loop indices in \a poly adjacent to the
* vertex. Returns the index of the loop matching vertex, or -1 if the
- * vertex is not in 'poly' */
+ * vertex is not in \a poly
+ */
int poly_get_adj_loops_from_vert(unsigned adj_r[3], const MPoly *poly,
const MLoop *mloop, unsigned vert)
{
@@ -3462,8 +1784,10 @@ int poly_get_adj_loops_from_vert(unsigned adj_r[3], const MPoly *poly,
return corner;
}
-/* Return the index of the edge vert that is not equal to 'v'. If
- * neither edge vertex is equal to 'v', returns -1. */
+/**
+ * Return the index of the edge vert that is not equal to \a v. If
+ * neither edge vertex is equal to \a v, returns -1.
+ */
int BKE_mesh_edge_other_vert(const MEdge *e, int v)
{
if (e->v1 == v)
@@ -3474,186 +1798,8 @@ int BKE_mesh_edge_other_vert(const MEdge *e, int v)
return -1;
}
-/* update the hide flag for edges and faces from the corresponding
- * flag in verts */
-void BKE_mesh_flush_hidden_from_verts_ex(const MVert *mvert,
- const MLoop *mloop,
- MEdge *medge, const int totedge,
- MPoly *mpoly, const int totpoly)
-{
- int i, j;
-
- for (i = 0; i < totedge; i++) {
- MEdge *e = &medge[i];
- if (mvert[e->v1].flag & ME_HIDE ||
- mvert[e->v2].flag & ME_HIDE)
- {
- e->flag |= ME_HIDE;
- }
- else {
- e->flag &= ~ME_HIDE;
- }
- }
- for (i = 0; i < totpoly; i++) {
- MPoly *p = &mpoly[i];
- p->flag &= ~ME_HIDE;
- for (j = 0; j < p->totloop; j++) {
- if (mvert[mloop[p->loopstart + j].v].flag & ME_HIDE)
- p->flag |= ME_HIDE;
- }
- }
-}
-void BKE_mesh_flush_hidden_from_verts(Mesh *me)
-{
- BKE_mesh_flush_hidden_from_verts_ex(me->mvert, me->mloop,
- me->medge, me->totedge,
- me->mpoly, me->totpoly);
-}
-
-void BKE_mesh_flush_hidden_from_polys_ex(MVert *mvert,
- const MLoop *mloop,
- MEdge *medge, const int UNUSED(totedge),
- const MPoly *mpoly, const int totpoly)
-{
- const MPoly *mp;
- int i;
-
- i = totpoly;
- for (mp = mpoly; i--; mp++) {
- if (mp->flag & ME_HIDE) {
- const MLoop *ml;
- int j;
- j = mp->totloop;
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- mvert[ml->v].flag |= ME_HIDE;
- medge[ml->e].flag |= ME_HIDE;
- }
- }
- }
-
- i = totpoly;
- for (mp = mpoly; i--; mp++) {
- if ((mp->flag & ME_HIDE) == 0) {
- const MLoop *ml;
- int j;
- j = mp->totloop;
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- mvert[ml->v].flag &= ~ME_HIDE;
- medge[ml->e].flag &= ~ME_HIDE;
- }
- }
- }
-}
-void BKE_mesh_flush_hidden_from_polys(Mesh *me)
-{
- BKE_mesh_flush_hidden_from_polys_ex(me->mvert, me->mloop,
- me->medge, me->totedge,
- me->mpoly, me->totpoly);
-}
-
-/**
- * simple poly -> vert/edge selection.
- */
-void BKE_mesh_flush_select_from_polys_ex(MVert *mvert, const int totvert,
- const MLoop *mloop,
- MEdge *medge, const int totedge,
- const MPoly *mpoly, const int totpoly)
-{
- MVert *mv;
- MEdge *med;
- const MPoly *mp;
- int i;
-
- i = totvert;
- for (mv = mvert; i--; mv++) {
- mv->flag &= ~SELECT;
- }
-
- i = totedge;
- for (med = medge; i--; med++) {
- med->flag &= ~SELECT;
- }
-
- i = totpoly;
- for (mp = mpoly; i--; mp++) {
- /* assume if its selected its not hidden and none of its verts/edges are hidden
- * (a common assumption)*/
- if (mp->flag & ME_FACE_SEL) {
- const MLoop *ml;
- int j;
- j = mp->totloop;
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- mvert[ml->v].flag |= SELECT;
- medge[ml->e].flag |= SELECT;
- }
- }
- }
-}
-void BKE_mesh_flush_select_from_polys(Mesh *me)
-{
- BKE_mesh_flush_select_from_polys_ex(me->mvert, me->totvert,
- me->mloop,
- me->medge, me->totedge,
- me->mpoly, me->totpoly);
-}
-
-void BKE_mesh_flush_select_from_verts_ex(const MVert *mvert, const int UNUSED(totvert),
- const MLoop *mloop,
- MEdge *medge, const int totedge,
- MPoly *mpoly, const int totpoly)
-{
- MEdge *med;
- MPoly *mp;
- int i;
-
- /* edges */
- i = totedge;
- for (med = medge; i--; med++) {
- if ((med->flag & ME_HIDE) == 0) {
- if ((mvert[med->v1].flag & SELECT) && (mvert[med->v2].flag & SELECT)) {
- med->flag |= SELECT;
- }
- else {
- med->flag &= ~SELECT;
- }
- }
- }
-
- /* polys */
- i = totpoly;
- for (mp = mpoly; i--; mp++) {
- if ((mp->flag & ME_HIDE) == 0) {
- int ok = TRUE;
- const MLoop *ml;
- int j;
- j = mp->totloop;
- for (ml = &mloop[mp->loopstart]; j--; ml++) {
- if ((mvert[ml->v].flag & SELECT) == 0) {
- ok = FALSE;
- break;
- }
- }
-
- if (ok) {
- mp->flag |= ME_FACE_SEL;
- }
- else {
- mp->flag &= ~ME_FACE_SEL;
- }
- }
- }
-}
-void BKE_mesh_flush_select_from_verts(Mesh *me)
-{
- BKE_mesh_flush_select_from_verts_ex(me->mvert, me->totvert,
- me->mloop,
- me->medge, me->totedge,
- me->mpoly, me->totpoly);
-}
-
-
/* basic vertex data functions */
-int BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
+bool BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
{
int i = me->totvert;
MVert *mvert;
@@ -3664,59 +1810,6 @@ int BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
return (me->totvert != 0);
}
-int BKE_mesh_center_median(Mesh *me, float cent[3])
-{
- int i = me->totvert;
- MVert *mvert;
- zero_v3(cent);
- for (mvert = me->mvert; i--; mvert++) {
- add_v3_v3(cent, mvert->co);
- }
- /* otherwise we get NAN for 0 verts */
- if (me->totvert) {
- mul_v3_fl(cent, 1.0f / (float)me->totvert);
- }
-
- return (me->totvert != 0);
-}
-
-int BKE_mesh_center_bounds(Mesh *me, float cent[3])
-{
- float min[3], max[3];
- INIT_MINMAX(min, max);
- if (BKE_mesh_minmax(me, min, max)) {
- mid_v3_v3v3(cent, min, max);
- return 1;
- }
-
- return 0;
-}
-
-int BKE_mesh_center_centroid(Mesh *me, float cent[3])
-{
- int i = me->totpoly;
- MPoly *mpoly;
- float poly_area;
- float total_area = 0.0f;
- float poly_cent[3];
-
- zero_v3(cent);
-
- /* calculate a weighted average of polygon centroids */
- for (mpoly = me->mpoly; i--; mpoly++) {
- poly_area = mesh_calc_poly_planar_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
-
- madd_v3_v3fl(cent, poly_cent, poly_area);
- total_area += poly_area;
- }
- /* otherwise we get NAN for 0 polys */
- if (me->totpoly) {
- mul_v3_fl(cent, 1.0f / total_area);
- }
-
- return (me->totpoly != 0);
-}
-
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
{
int i = me->totvert;
@@ -3773,85 +1866,6 @@ void BKE_mesh_tessface_clear(Mesh *mesh)
mesh_tessface_clear_intern(mesh, TRUE);
}
-#if 0 /* slow version of the function below */
-void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, float angles[])
-{
- MLoop *ml;
- MLoop *mloop = &loopstart[-mpoly->loopstart];
-
- int j;
- for (j = 0, ml = loopstart; j < mpoly->totloop; j++, ml++) {
- MLoop *ml_prev = ME_POLY_LOOP_PREV(mloop, mpoly, j);
- MLoop *ml_next = ME_POLY_LOOP_NEXT(mloop, mpoly, j);
-
- float e1[3], e2[3];
-
- sub_v3_v3v3(e1, mvarray[ml_next->v].co, mvarray[ml->v].co);
- sub_v3_v3v3(e2, mvarray[ml_prev->v].co, mvarray[ml->v].co);
-
- angles[j] = (float)M_PI - angle_v3v3(e1, e2);
- }
-}
-
-#else /* equivalent the function above but avoid multiple subtractions + normalize */
-
-void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
- MVert *mvarray, float angles[])
-{
- float nor_prev[3];
- float nor_next[3];
-
- int i_this = mpoly->totloop - 1;
- int i_next = 0;
-
- sub_v3_v3v3(nor_prev, mvarray[loopstart[i_this - 1].v].co, mvarray[loopstart[i_this].v].co);
- normalize_v3(nor_prev);
-
- while (i_next < mpoly->totloop) {
- sub_v3_v3v3(nor_next, mvarray[loopstart[i_this].v].co, mvarray[loopstart[i_next].v].co);
- normalize_v3(nor_next);
- angles[i_this] = angle_normalized_v3v3(nor_prev, nor_next);
-
- /* step */
- copy_v3_v3(nor_prev, nor_next);
- i_this = i_next;
- i_next++;
- }
-}
-#endif
-
-void BKE_mesh_poly_edgehash_insert(EdgeHash *ehash, const MPoly *mp, const MLoop *mloop)
-{
- const MLoop *ml, *ml_next;
- int i = mp->totloop;
-
- ml_next = mloop; /* first loop */
- ml = &ml_next[i - 1]; /* last loop */
-
- while (i-- != 0) {
- if (!BLI_edgehash_haskey(ehash, ml->v, ml_next->v)) {
- BLI_edgehash_insert(ehash, ml->v, ml_next->v, NULL);
- }
-
- ml = ml_next;
- ml_next++;
- }
-}
-
-void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap, const MPoly *mp, const MLoop *mloop)
-{
- const MLoop *ml;
- int i = mp->totloop;
-
- ml = mloop;
-
- while (i-- != 0) {
- BLI_BITMAP_SET(edge_bitmap, ml->e);
- ml++;
- }
-}
-
void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh)
{
if (UNLIKELY(mesh->cd_flag)) {
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
new file mode 100644
index 00000000000..07dfae2f28a
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -0,0 +1,2301 @@
+/*
+ * ***** 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/blenkernel/intern/mesh_evaluate.c
+ * \ingroup bke
+ *
+ * Functions to evaluate mesh data.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_memarena.h"
+#include "BLI_math.h"
+#include "BLI_edgehash.h"
+#include "BLI_bitmap.h"
+#include "BLI_scanfill.h"
+#include "BLI_linklist.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_alloca.h"
+
+#include "BKE_customdata.h"
+#include "BKE_mesh.h"
+#include "BKE_multires.h"
+
+#include "BLI_strict_flags.h"
+
+
+// #define DEBUG_TIME
+
+#ifdef DEBUG_TIME
+# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Normal Calculation
+ * \{ */
+
+/**
+ * Call when there are no polygons.
+ */
+static void mesh_calc_normals_vert_fallback(MVert *mverts, int numVerts)
+{
+ int i;
+ for (i = 0; i < numVerts; i++) {
+ MVert *mv = &mverts[i];
+ float no[3];
+
+ normalize_v3_v3(no, mv->co);
+ normal_float_to_short_v3(mv->no, no);
+ }
+}
+
+/* Calculate vertex and face normals, face normals are returned in *faceNors_r if non-NULL
+ * and vertex normals are stored in actual mverts.
+ */
+void BKE_mesh_calc_normals_mapping(MVert *mverts, int numVerts,
+ MLoop *mloop, MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
+ MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3])
+{
+ BKE_mesh_calc_normals_mapping_ex(mverts, numVerts, mloop, mpolys,
+ numLoops, numPolys, polyNors_r, mfaces, numFaces,
+ origIndexFace, faceNors_r, FALSE);
+}
+/* extended version of 'BKE_mesh_calc_normals_poly' with option not to calc vertex normals */
+void BKE_mesh_calc_normals_mapping_ex(
+ MVert *mverts, int numVerts,
+ MLoop *mloop, MPoly *mpolys,
+ int numLoops, int numPolys, float (*polyNors_r)[3],
+ MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3],
+ const bool only_face_normals)
+{
+ float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r;
+ int i;
+ MFace *mf;
+ MPoly *mp;
+
+ if (numPolys == 0) {
+ if (only_face_normals == FALSE) {
+ mesh_calc_normals_vert_fallback(mverts, numVerts);
+ }
+ return;
+ }
+
+ /* if we are not calculating verts and no verts were passes then we have nothing to do */
+ if ((only_face_normals == TRUE) && (polyNors_r == NULL) && (faceNors_r == NULL)) {
+ printf("%s: called with nothing to do\n", __func__);
+ return;
+ }
+
+ if (!pnors) pnors = MEM_callocN(sizeof(float[3]) * (size_t)numPolys, __func__);
+ /* if (!fnors) fnors = MEM_callocN(sizeof(float[3]) * numFaces, "face nors mesh.c"); */ /* NO NEED TO ALLOC YET */
+
+
+ if (only_face_normals == FALSE) {
+ /* vertex normals are optional, they require some extra calculations,
+ * so make them optional */
+ BKE_mesh_calc_normals_poly(mverts, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
+ }
+ else {
+ /* only calc poly normals */
+ mp = mpolys;
+ for (i = 0; i < numPolys; i++, mp++) {
+ BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]);
+ }
+ }
+
+ if (origIndexFace &&
+ /* fnors == faceNors_r */ /* NO NEED TO ALLOC YET */
+ fnors != NULL &&
+ numFaces)
+ {
+ mf = mfaces;
+ for (i = 0; i < numFaces; i++, mf++, origIndexFace++) {
+ if (*origIndexFace < numPolys) {
+ copy_v3_v3(fnors[i], pnors[*origIndexFace]);
+ }
+ else {
+ /* eek, we're not corresponding to polys */
+ printf("error in %s: tessellation face indices are incorrect. normals may look bad.\n", __func__);
+ }
+ }
+ }
+
+ if (pnors != polyNors_r) MEM_freeN(pnors);
+ /* if (fnors != faceNors_r) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */
+
+ fnors = pnors = NULL;
+
+}
+
+static void mesh_calc_normals_poly_accum(MPoly *mp, MLoop *ml,
+ MVert *mvert, float polyno[3], float (*tnorms)[3])
+{
+ const int nverts = mp->totloop;
+ float (*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, (size_t)nverts);
+ int i;
+
+ /* Polygon Normal and edge-vector */
+ /* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */
+ {
+ int i_prev = nverts - 1;
+ float const *v_prev = mvert[ml[i_prev].v].co;
+ float const *v_curr;
+
+ zero_v3(polyno);
+ /* Newell's Method */
+ for (i = 0; i < nverts; i++) {
+ v_curr = mvert[ml[i].v].co;
+ add_newell_cross_v3_v3v3(polyno, v_prev, v_curr);
+
+ /* Unrelated to normalize, calculate edge-vector */
+ sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr);
+ normalize_v3(edgevecbuf[i_prev]);
+ i_prev = i;
+
+ v_prev = v_curr;
+ }
+ if (UNLIKELY(normalize_v3(polyno) == 0.0f)) {
+ polyno[2] = 1.0f; /* other axis set to 0.0 */
+ }
+ }
+
+ /* accumulate angle weighted face normal */
+ /* inline version of #accumulate_vertex_normals_poly */
+ {
+ const float *prev_edge = edgevecbuf[nverts - 1];
+
+ for (i = 0; i < nverts; i++) {
+ const float *cur_edge = edgevecbuf[i];
+
+ /* calculate angle between the two poly edges incident on
+ * this vertex */
+ const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
+
+ /* accumulate */
+ madd_v3_v3fl(tnorms[ml[i].v], polyno, fac);
+ prev_edge = cur_edge;
+ }
+ }
+
+}
+
+void BKE_mesh_calc_normals_poly(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
+ int UNUSED(numLoops), int numPolys, float (*r_polynors)[3],
+ const bool only_face_normals)
+{
+ float (*pnors)[3] = r_polynors;
+ float (*tnorms)[3];
+ int i;
+ MPoly *mp;
+
+ if (only_face_normals) {
+ BLI_assert(pnors != NULL);
+
+#pragma omp parallel for if (numPolys > BKE_MESH_OMP_LIMIT)
+ for (i = 0; i < numPolys; i++) {
+ BKE_mesh_calc_poly_normal(&mpolys[i], mloop + mpolys[i].loopstart, mverts, pnors[i]);
+ }
+ return;
+ }
+
+ /* first go through and calculate normals for all the polys */
+ tnorms = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, __func__);
+
+ if (pnors) {
+ mp = mpolys;
+ for (i = 0; i < numPolys; i++, mp++) {
+ mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], tnorms);
+ }
+ }
+ else {
+ float tpnor[3]; /* temp poly normal */
+ mp = mpolys;
+ for (i = 0; i < numPolys; i++, mp++) {
+ mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, tnorms);
+ }
+ }
+
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ for (i = 0; i < numVerts; i++) {
+ MVert *mv = &mverts[i];
+ float *no = tnorms[i];
+
+ if (UNLIKELY(normalize_v3(no) == 0.0f)) {
+ normalize_v3_v3(no, mv->co);
+ }
+
+ normal_float_to_short_v3(mv->no, no);
+ }
+
+ MEM_freeN(tnorms);
+}
+
+void BKE_mesh_calc_normals(Mesh *mesh)
+{
+#ifdef DEBUG_TIME
+ TIMEIT_START(BKE_mesh_calc_normals);
+#endif
+ BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert,
+ mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
+ NULL, false);
+#ifdef DEBUG_TIME
+ TIMEIT_END(BKE_mesh_calc_normals);
+#endif
+}
+
+void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3])
+{
+ float (*tnorms)[3] = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, "tnorms");
+ float (*fnors)[3] = (faceNors_r) ? faceNors_r : MEM_callocN(sizeof(*fnors) * (size_t)numFaces, "meshnormals");
+ int i;
+
+ for (i = 0; i < numFaces; i++) {
+ MFace *mf = &mfaces[i];
+ float *f_no = fnors[i];
+ float *n4 = (mf->v4) ? tnorms[mf->v4] : NULL;
+ float *c4 = (mf->v4) ? mverts[mf->v4].co : NULL;
+
+ if (mf->v4)
+ normal_quad_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co);
+ else
+ normal_tri_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co);
+
+ accumulate_vertex_normals(tnorms[mf->v1], tnorms[mf->v2], tnorms[mf->v3], n4,
+ f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, c4);
+ }
+
+ /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ for (i = 0; i < numVerts; i++) {
+ MVert *mv = &mverts[i];
+ float *no = tnorms[i];
+
+ if (UNLIKELY(normalize_v3(no) == 0.0f)) {
+ normalize_v3_v3(no, mv->co);
+ }
+
+ normal_float_to_short_v3(mv->no, no);
+ }
+
+ MEM_freeN(tnorms);
+
+ if (fnors != faceNors_r)
+ MEM_freeN(fnors);
+}
+
+/**
+ * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
+ * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
+ */
+void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *medges, int numEdges,
+ MLoop *mloops, float (*r_loopnors)[3], int numLoops,
+ MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle)
+{
+#define INDEX_UNSET INT_MIN
+#define INDEX_INVALID -1
+/* See comment about edge_to_loops below. */
+#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID))
+
+ /* Mapping edge -> loops.
+ * If that edge is used by more than two loops (polys), it is always sharp (and tagged as such, see below).
+ * We also use the second loop index as a kind of flag: smooth edge: > 0,
+ * sharp edge: < 0 (INDEX_INVALID || INDEX_UNSET),
+ * unset: INDEX_UNSET
+ * Note that currently we only have two values for second loop of sharp edges. However, if needed, we can
+ * store the negated value of loop index instead of INDEX_INVALID to retrieve th real value later in code).
+ * Note also that lose edges always have both values set to 0!
+ */
+ int (*edge_to_loops)[2] = MEM_callocN(sizeof(int[2]) * (size_t)numEdges, __func__);
+
+ /* Simple mapping from a loop to its polygon index. */
+ int *loop_to_poly = MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
+
+ MPoly *mp;
+ int mp_index;
+ const bool check_angle = (split_angle < (float)M_PI);
+
+ /* Temp normal stack. */
+ BLI_SMALLSTACK_DECLARE(normal, float *);
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(BKE_mesh_normals_loop_split);
+#endif
+
+ if (check_angle) {
+ split_angle = cosf(split_angle);
+ }
+
+ /* 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 INT_MIN to tag it as unset). */
+ e2l[0] = ml_curr_index;
+ e2l[1] = INDEX_UNSET;
+ }
+ 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 angle between
+ * both its polys' normals is above split_angle value...
+ */
+ if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) ||
+ (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 that two loops using this edge, tag as sharp if not yet done. */
+ e2l[1] = INDEX_INVALID;
+ }
+ /* Else, edge is already 'disqualified' (i.e. sharp)! */
+ }
+ }
+
+ /* We now know edges that can be smoothed (with their vector, and their two loops), and edges that will be hard!
+ * Now, time to generate the normals.
+ */
+ for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ MLoop *ml_curr, *ml_prev;
+ float (*lnors)[3];
+ const int ml_last_index = (mp->loopstart + mp->totloop) - 1;
+ int ml_curr_index = mp->loopstart;
+ int ml_prev_index = ml_last_index;
+
+ ml_curr = &mloops[ml_curr_index];
+ ml_prev = &mloops[ml_prev_index];
+ lnors = &r_loopnors[ml_curr_index];
+
+ for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++, lnors++) {
+ const int *e2l_curr = edge_to_loops[ml_curr->e];
+ const int *e2l_prev = edge_to_loops[ml_prev->e];
+
+ if (!IS_EDGE_SHARP(e2l_curr)) {
+ /* A smooth edge.
+ * We skip it because it is either:
+ * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
+ * one of its ends, i.e. one of its two sharp edges), or...
+ * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex
+ * are just fine!
+ */
+ }
+ else if (IS_EDGE_SHARP(e2l_prev)) {
+ /* Simple case (both edges around that vertex are sharp in current polygon),
+ * this vertex just takes its poly normal.
+ */
+ copy_v3_v3(*lnors, polynors[mp_index]);
+ /* No need to mark loop as done here, we won't run into it again anyway! */
+ }
+ /* This loop may have been already computed, in which case its 'to_poly' map is set to -1... */
+ else if (loop_to_poly[ml_curr_index] != -1) {
+ /* Gah... We have to fan around current vertex, until we find the other non-smooth edge,
+ * and accumulate face normals into the vertex!
+ * Note in case this vertex has only one sharp edges, this is a waste because the normal is the same as
+ * the vertex normal, but I do not see any easy way to detect that (would need to count number
+ * of sharp edges per vertex, I doubt the additional memory usage would be worth it, especially as
+ * it should not be a common case in real-life meshes anyway).
+ */
+ const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
+ const int *e2lfan_curr;
+ float vec_curr[3], vec_prev[3];
+ MLoop *mlfan_curr, *mlfan_next;
+ MPoly *mpfan_next;
+ float lnor[3] = {0.0f, 0.0f, 0.0f};
+ /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
+
+ e2lfan_curr = e2l_prev;
+ mlfan_curr = ml_prev;
+ mlfan_curr_index = ml_prev_index;
+ mlfan_vert_index = ml_curr_index;
+ mpfan_curr_index = mp_index;
+
+ /* Only need to compute previous edge's vector once, then we can just reuse old current one! */
+ {
+ const MEdge *me_prev = &medges[ml_prev->e];
+ const MVert *mv_1 = &mverts[mv_pivot_index];
+ const MVert *mv_2 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] : &mverts[me_prev->v1];
+
+ sub_v3_v3v3(vec_prev, mv_2->co, mv_1->co);
+ normalize_v3(vec_prev);
+ }
+
+ while (true) {
+ /* Compute edge vectors.
+ * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing them
+ * twice (or more) here. However, time gained is not worth memory and time lost,
+ * given the fact that this code should not be called that much in real-life meshes...
+ */
+ {
+ const MEdge *me_curr = &medges[ml_curr->e];
+ const MVert *mv_1 = &mverts[mv_pivot_index];
+ const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] :
+ &mverts[me_curr->v1];
+
+ sub_v3_v3v3(vec_curr, mv_2->co, mv_1->co);
+ normalize_v3(vec_curr);
+ }
+
+ {
+ /* Code similar to accumulate_vertex_normals_poly. */
+ /* Calculate angle between the two poly edges incident on this vertex. */
+ const float fac = saacos(dot_v3v3(vec_curr, vec_prev));
+ /* Accumulate */
+ madd_v3_v3fl(lnor, polynors[mpfan_curr_index], fac);
+ }
+
+ /* We store here a pointer to all loop-normals processed. */
+ BLI_SMALLSTACK_PUSH(normal, &(r_loopnors[mlfan_vert_index][0]));
+
+ /* And we are done with this loop, mark it as such! */
+ loop_to_poly[mlfan_vert_index] = -1;
+
+ if (IS_EDGE_SHARP(e2lfan_curr)) {
+ /* Current edge is sharp, we have finished with this fan of faces around this vert! */
+ break;
+ }
+
+ copy_v3_v3(vec_prev, vec_curr);
+
+ /* Warning! This is rather complex!
+ * We have to find our next edge around the vertex (fan mode).
+ * First we find the next loop, which is either previous or next to mlfan_curr_index, depending
+ * whether both loops using current edge are in the same direction or not, and whether
+ * mlfan_curr_index actually uses the vertex we are fanning around!
+ * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
+ * (i.e. not the future mlfan_curr)...
+ */
+ mlfan_curr_index = (e2lfan_curr[0] == mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
+ mpfan_curr_index = loop_to_poly[mlfan_curr_index];
+ mlfan_next = &mloops[mlfan_curr_index];
+ mpfan_next = &mpolys[mpfan_curr_index];
+ if ((mlfan_curr->v == mlfan_next->v && mlfan_curr->v == mv_pivot_index) ||
+ (mlfan_curr->v != mlfan_next->v && mlfan_curr->v != mv_pivot_index))
+ {
+ /* We need the previous loop, but current one is our vertex's loop. */
+ mlfan_vert_index = mlfan_curr_index;
+ if (--mlfan_curr_index < mpfan_next->loopstart) {
+ mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
+ }
+ }
+ else {
+ /* We need the next loop, which is also our vertex's loop. */
+ if (++mlfan_curr_index >= mpfan_next->loopstart + mpfan_next->totloop) {
+ mlfan_curr_index = mpfan_next->loopstart;
+ }
+ mlfan_vert_index = mlfan_curr_index;
+ }
+ mlfan_curr = &mloops[mlfan_curr_index];
+ /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+
+ e2lfan_curr = edge_to_loops[mlfan_curr->e];
+ }
+
+ /* In case we get a zero normal here, just use vertex normal already set! */
+ if (LIKELY(normalize_v3(lnor) != 0.0f)) {
+ /* Copy back the final computed normal into all related loop-normals. */
+ float *nor;
+ while ((nor = BLI_SMALLSTACK_POP(normal))) {
+ copy_v3_v3(nor, lnor);
+ }
+ }
+ }
+
+ ml_prev = ml_curr;
+ ml_prev_index = ml_curr_index;
+ }
+ }
+
+ BLI_SMALLSTACK_FREE(normal);
+
+ MEM_freeN(edge_to_loops);
+ MEM_freeN(loop_to_poly);
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(BKE_mesh_normals_loop_split);
+#endif
+
+#undef INDEX_UNSET
+#undef INDEX_INVALID
+#undef IS_EDGE_SHARP
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Polygon Calculations
+ * \{ */
+
+/*
+ * COMPUTE POLY NORMAL
+ *
+ * Computes the normal of a planar
+ * polygon See Graphics Gems for
+ * computing newell normal.
+ *
+ */
+static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvert, float normal[3])
+{
+ const int nverts = mpoly->totloop;
+ float const *v_prev = mvert[loopstart[nverts - 1].v].co;
+ float const *v_curr;
+ int i;
+
+ zero_v3(normal);
+
+ /* Newell's Method */
+ for (i = 0; i < nverts; i++) {
+ v_curr = mvert[loopstart[i].v].co;
+ add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
+ v_prev = v_curr;
+ }
+
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f; /* other axis set to 0.0 */
+ }
+}
+
+void BKE_mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, float no[3])
+{
+ if (mpoly->totloop > 4) {
+ mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no);
+ }
+ else if (mpoly->totloop == 3) {
+ normal_tri_v3(no,
+ mvarray[loopstart[0].v].co,
+ mvarray[loopstart[1].v].co,
+ mvarray[loopstart[2].v].co
+ );
+ }
+ else if (mpoly->totloop == 4) {
+ normal_quad_v3(no,
+ mvarray[loopstart[0].v].co,
+ mvarray[loopstart[1].v].co,
+ mvarray[loopstart[2].v].co,
+ mvarray[loopstart[3].v].co
+ );
+ }
+ else { /* horrible, two sided face! */
+ no[0] = 0.0;
+ no[1] = 0.0;
+ no[2] = 1.0;
+ }
+}
+/* duplicate of function above _but_ takes coords rather then mverts */
+static void mesh_calc_ngon_normal_coords(MPoly *mpoly, MLoop *loopstart,
+ const float (*vertex_coords)[3], float normal[3])
+{
+ const int nverts = mpoly->totloop;
+ float const *v_prev = vertex_coords[loopstart[nverts - 1].v];
+ float const *v_curr;
+ int i;
+
+ zero_v3(normal);
+
+ /* Newell's Method */
+ for (i = 0; i < nverts; i++) {
+ v_curr = vertex_coords[loopstart[i].v];
+ add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
+ v_prev = v_curr;
+ }
+
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f; /* other axis set to 0.0 */
+ }
+}
+
+void BKE_mesh_calc_poly_normal_coords(MPoly *mpoly, MLoop *loopstart,
+ const float (*vertex_coords)[3], float no[3])
+{
+ if (mpoly->totloop > 4) {
+ mesh_calc_ngon_normal_coords(mpoly, loopstart, vertex_coords, no);
+ }
+ else if (mpoly->totloop == 3) {
+ normal_tri_v3(no,
+ vertex_coords[loopstart[0].v],
+ vertex_coords[loopstart[1].v],
+ vertex_coords[loopstart[2].v]
+ );
+ }
+ else if (mpoly->totloop == 4) {
+ normal_quad_v3(no,
+ vertex_coords[loopstart[0].v],
+ vertex_coords[loopstart[1].v],
+ vertex_coords[loopstart[2].v],
+ vertex_coords[loopstart[3].v]
+ );
+ }
+ else { /* horrible, two sided face! */
+ no[0] = 0.0;
+ no[1] = 0.0;
+ no[2] = 1.0;
+ }
+}
+
+static void mesh_calc_ngon_center(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvert, float cent[3])
+{
+ const float w = 1.0f / (float)mpoly->totloop;
+ int i;
+
+ zero_v3(cent);
+
+ for (i = 0; i < mpoly->totloop; i++) {
+ madd_v3_v3fl(cent, mvert[(loopstart++)->v].co, w);
+ }
+}
+
+void BKE_mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, float cent[3])
+{
+ if (mpoly->totloop == 3) {
+ cent_tri_v3(cent,
+ mvarray[loopstart[0].v].co,
+ mvarray[loopstart[1].v].co,
+ mvarray[loopstart[2].v].co
+ );
+ }
+ else if (mpoly->totloop == 4) {
+ cent_quad_v3(cent,
+ mvarray[loopstart[0].v].co,
+ mvarray[loopstart[1].v].co,
+ mvarray[loopstart[2].v].co,
+ mvarray[loopstart[3].v].co
+ );
+ }
+ else {
+ mesh_calc_ngon_center(mpoly, loopstart, mvarray, cent);
+ }
+}
+
+/* note, passing polynormal is only a speedup so we can skip calculating it */
+float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, const float polynormal[3])
+{
+ if (mpoly->totloop == 3) {
+ return area_tri_v3(mvarray[loopstart[0].v].co,
+ mvarray[loopstart[1].v].co,
+ mvarray[loopstart[2].v].co
+ );
+ }
+ else if (mpoly->totloop == 4) {
+ return area_quad_v3(mvarray[loopstart[0].v].co,
+ mvarray[loopstart[1].v].co,
+ mvarray[loopstart[2].v].co,
+ mvarray[loopstart[3].v].co
+ );
+ }
+ else {
+ int i;
+ MLoop *l_iter = loopstart;
+ float area, polynorm_local[3];
+ float (*vertexcos)[3] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop);
+ const float *no = polynormal ? polynormal : polynorm_local;
+
+ /* pack vertex cos into an array for area_poly_v3 */
+ for (i = 0; i < mpoly->totloop; i++, l_iter++) {
+ copy_v3_v3(vertexcos[i], mvarray[l_iter->v].co);
+ }
+
+ /* need normal for area_poly_v3 as well */
+ if (polynormal == NULL) {
+ BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, polynorm_local);
+ }
+
+ /* finally calculate the area */
+ area = area_poly_v3(mpoly->totloop, vertexcos, no);
+
+ return area;
+ }
+}
+
+/* note, results won't be correct if polygon is non-planar */
+static float mesh_calc_poly_planar_area_centroid(MPoly *mpoly, MLoop *loopstart, MVert *mvarray, float cent[3])
+{
+ int i;
+ float tri_area;
+ float total_area = 0.0f;
+ float v1[3], v2[3], v3[3], normal[3], tri_cent[3];
+
+ BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal);
+ copy_v3_v3(v1, mvarray[loopstart[0].v].co);
+ copy_v3_v3(v2, mvarray[loopstart[1].v].co);
+ zero_v3(cent);
+
+ for (i = 2; i < mpoly->totloop; i++) {
+ copy_v3_v3(v3, mvarray[loopstart[i].v].co);
+
+ tri_area = area_tri_signed_v3(v1, v2, v3, normal);
+ total_area += tri_area;
+
+ cent_tri_v3(tri_cent, v1, v2, v3);
+ madd_v3_v3fl(cent, tri_cent, tri_area);
+
+ copy_v3_v3(v2, v3);
+ }
+
+ mul_v3_fl(cent, 1.0f / total_area);
+
+ return total_area;
+}
+
+#if 0 /* slow version of the function below */
+void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, float angles[])
+{
+ MLoop *ml;
+ MLoop *mloop = &loopstart[-mpoly->loopstart];
+
+ int j;
+ for (j = 0, ml = loopstart; j < mpoly->totloop; j++, ml++) {
+ MLoop *ml_prev = ME_POLY_LOOP_PREV(mloop, mpoly, j);
+ MLoop *ml_next = ME_POLY_LOOP_NEXT(mloop, mpoly, j);
+
+ float e1[3], e2[3];
+
+ sub_v3_v3v3(e1, mvarray[ml_next->v].co, mvarray[ml->v].co);
+ sub_v3_v3v3(e2, mvarray[ml_prev->v].co, mvarray[ml->v].co);
+
+ angles[j] = (float)M_PI - angle_v3v3(e1, e2);
+ }
+}
+
+#else /* equivalent the function above but avoid multiple subtractions + normalize */
+
+void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
+ MVert *mvarray, float angles[])
+{
+ float nor_prev[3];
+ float nor_next[3];
+
+ int i_this = mpoly->totloop - 1;
+ int i_next = 0;
+
+ sub_v3_v3v3(nor_prev, mvarray[loopstart[i_this - 1].v].co, mvarray[loopstart[i_this].v].co);
+ normalize_v3(nor_prev);
+
+ while (i_next < mpoly->totloop) {
+ sub_v3_v3v3(nor_next, mvarray[loopstart[i_this].v].co, mvarray[loopstart[i_next].v].co);
+ normalize_v3(nor_next);
+ angles[i_this] = angle_normalized_v3v3(nor_prev, nor_next);
+
+ /* step */
+ copy_v3_v3(nor_prev, nor_next);
+ i_this = i_next;
+ i_next++;
+ }
+}
+#endif
+
+void BKE_mesh_poly_edgehash_insert(EdgeHash *ehash, const MPoly *mp, const MLoop *mloop)
+{
+ const MLoop *ml, *ml_next;
+ int i = mp->totloop;
+
+ ml_next = mloop; /* first loop */
+ ml = &ml_next[i - 1]; /* last loop */
+
+ while (i-- != 0) {
+ BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, NULL);
+
+ ml = ml_next;
+ ml_next++;
+ }
+}
+
+void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap, const MPoly *mp, const MLoop *mloop)
+{
+ const MLoop *ml;
+ int i = mp->totloop;
+
+ ml = mloop;
+
+ while (i-- != 0) {
+ BLI_BITMAP_SET(edge_bitmap, ml->e);
+ ml++;
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Center Calculation
+ * \{ */
+
+bool BKE_mesh_center_median(Mesh *me, float cent[3])
+{
+ int i = me->totvert;
+ MVert *mvert;
+ zero_v3(cent);
+ for (mvert = me->mvert; i--; mvert++) {
+ add_v3_v3(cent, mvert->co);
+ }
+ /* otherwise we get NAN for 0 verts */
+ if (me->totvert) {
+ mul_v3_fl(cent, 1.0f / (float)me->totvert);
+ }
+
+ return (me->totvert != 0);
+}
+
+bool BKE_mesh_center_bounds(Mesh *me, float cent[3])
+{
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ if (BKE_mesh_minmax(me, min, max)) {
+ mid_v3_v3v3(cent, min, max);
+ return true;
+ }
+
+ return false;
+}
+
+bool BKE_mesh_center_centroid(Mesh *me, float cent[3])
+{
+ int i = me->totpoly;
+ MPoly *mpoly;
+ float poly_area;
+ float total_area = 0.0f;
+ float poly_cent[3];
+
+ zero_v3(cent);
+
+ /* calculate a weighted average of polygon centroids */
+ for (mpoly = me->mpoly; i--; mpoly++) {
+ poly_area = mesh_calc_poly_planar_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
+
+ madd_v3_v3fl(cent, poly_cent, poly_area);
+ total_area += poly_area;
+ }
+ /* otherwise we get NAN for 0 polys */
+ if (me->totpoly) {
+ mul_v3_fl(cent, 1.0f / total_area);
+ }
+
+ /* zero area faces cause this, fallback to median */
+ if (UNLIKELY(!is_finite_v3(cent))) {
+ return BKE_mesh_center_median(me, cent);
+ }
+
+ return (me->totpoly != 0);
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Connectivity Mapping
+ * \{ */
+
+
+/* ngon version wip, based on EDBM_uv_vert_map_create */
+/* this replaces the non bmesh function (in trunk) which takes MTFace's, if we ever need it back we could
+ * but for now this replaces it because its unused. */
+
+UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
+ unsigned int totpoly, unsigned int totvert, int selected, float *limit)
+{
+ UvVertMap *vmap;
+ UvMapVert *buf;
+ MPoly *mp;
+ unsigned int a;
+ int i, totuv, nverts;
+
+ totuv = 0;
+
+ /* generate UvMapVert array */
+ mp = mpoly;
+ for (a = 0; a < totpoly; a++, mp++)
+ if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL)))
+ totuv += mp->totloop;
+
+ if (totuv == 0)
+ return NULL;
+
+ vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
+ if (!vmap)
+ return NULL;
+
+ vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*");
+ buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * (size_t)totuv, "UvMapVert");
+
+ if (!vmap->vert || !vmap->buf) {
+ BKE_mesh_uv_vert_map_free(vmap);
+ return NULL;
+ }
+
+ mp = mpoly;
+ for (a = 0; a < totpoly; a++, mp++) {
+ if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
+ nverts = mp->totloop;
+
+ for (i = 0; i < nverts; i++) {
+ buf->tfindex = (unsigned char)i;
+ buf->f = a;
+ buf->separate = 0;
+ buf->next = vmap->vert[mloop[mp->loopstart + i].v];
+ vmap->vert[mloop[mp->loopstart + i].v] = buf;
+ buf++;
+ }
+ }
+ }
+
+ /* sort individual uvs for each vert */
+ for (a = 0; a < totvert; a++) {
+ UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
+ UvMapVert *iterv, *v, *lastv, *next;
+ float *uv, *uv2, uvdiff[2];
+
+ while (vlist) {
+ v = vlist;
+ vlist = vlist->next;
+ v->next = newvlist;
+ newvlist = v;
+
+ uv = mloopuv[mpoly[v->f].loopstart + v->tfindex].uv;
+ lastv = NULL;
+ iterv = vlist;
+
+ while (iterv) {
+ next = iterv->next;
+
+ uv2 = mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv;
+ sub_v2_v2v2(uvdiff, uv2, uv);
+
+
+ if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1]) {
+ if (lastv) lastv->next = next;
+ else vlist = next;
+ iterv->next = newvlist;
+ newvlist = iterv;
+ }
+ else
+ lastv = iterv;
+
+ iterv = next;
+ }
+
+ newvlist->separate = 1;
+ }
+
+ vmap->vert[a] = newvlist;
+ }
+
+ return vmap;
+}
+
+UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v)
+{
+ return vmap->vert[v];
+}
+
+void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
+{
+ if (vmap) {
+ if (vmap->vert) MEM_freeN(vmap->vert);
+ if (vmap->buf) MEM_freeN(vmap->buf);
+ MEM_freeN(vmap);
+ }
+}
+
+/* Generates a map where the key is the vertex and the value is a list
+ * of polys that use that vertex as a corner. The lists are allocated
+ * from one memory pool. */
+void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop)
+{
+ MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert poly map");
+ int *indices, *index_iter;
+ int i, j;
+
+ indices = index_iter = MEM_mallocN(sizeof(int) * (size_t)totloop, "vert poly map mem");
+
+ /* Count number of polys for each vertex */
+ for (i = 0; i < totpoly; i++) {
+ const MPoly *p = &mpoly[i];
+
+ for (j = 0; j < p->totloop; j++)
+ map[mloop[p->loopstart + j].v].count++;
+ }
+
+ /* Assign indices mem */
+ for (i = 0; i < totvert; i++) {
+ map[i].indices = index_iter;
+ index_iter += map[i].count;
+
+ /* Reset 'count' for use as index in last loop */
+ map[i].count = 0;
+ }
+
+ /* Find the users */
+ for (i = 0; i < totpoly; i++) {
+ const MPoly *p = &mpoly[i];
+
+ for (j = 0; j < p->totloop; j++) {
+ unsigned int v = mloop[p->loopstart + j].v;
+
+ map[v].indices[map[v].count] = i;
+ map[v].count++;
+ }
+ }
+
+ *r_map = map;
+ *r_mem = indices;
+}
+
+/* Generates a map where the key is the vertex and the value is a list
+ * of edges that use that vertex as an endpoint. The lists are allocated
+ * from one memory pool. */
+void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
+ const MEdge *medge, int totvert, int totedge)
+{
+ MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert-edge map");
+ int *indices = MEM_mallocN(sizeof(int[2]) * (size_t)totedge, "vert-edge map mem");
+ int *i_pt = indices;
+
+ int i;
+
+ /* Count number of edges for each vertex */
+ for (i = 0; i < totedge; i++) {
+ map[medge[i].v1].count++;
+ map[medge[i].v2].count++;
+ }
+
+ /* Assign indices mem */
+ for (i = 0; i < totvert; i++) {
+ map[i].indices = i_pt;
+ i_pt += map[i].count;
+
+ /* Reset 'count' for use as index in last loop */
+ map[i].count = 0;
+ }
+
+ /* Find the users */
+ for (i = 0; i < totedge; i++) {
+ const unsigned int v[2] = {medge[i].v1, medge[i].v2};
+
+ map[v[0]].indices[map[v[0]].count] = i;
+ map[v[1]].indices[map[v[1]].count] = i;
+
+ map[v[0]].count++;
+ map[v[1]].count++;
+ }
+
+ *r_map = map;
+ *r_mem = indices;
+}
+
+void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem,
+ const MEdge *UNUSED(medge), const int totedge,
+ const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totloop)
+{
+ MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totedge, "edge-poly map");
+ int *indices = MEM_mallocN(sizeof(int) * (size_t)totloop, "edge-poly map mem");
+ int *index_step;
+ const MPoly *mp;
+ int i;
+
+ /* count face users */
+ for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
+ const MLoop *ml;
+ int j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ map[ml->e].count++;
+ }
+ }
+
+ /* create offsets */
+ index_step = indices;
+ for (i = 0; i < totedge; i++) {
+ map[i].indices = index_step;
+ index_step += map[i].count;
+
+ /* re-count, using this as an index below */
+ map[i].count = 0;
+
+ }
+
+ /* assign poly-edge users */
+ for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
+ const MLoop *ml;
+ int j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ MeshElemMap *map_ele = &map[ml->e];
+ map_ele->indices[map_ele->count++] = i;
+ }
+ }
+
+ *r_map = map;
+ *r_mem = indices;
+}
+
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name NGon Tessellation (NGon/Tessface Conversion)
+ * \{ */
+
+/**
+ * Convert a triangle or quadrangle of loop/poly data to tessface data
+ */
+void BKE_mesh_loops_to_mface_corners(
+ CustomData *fdata, CustomData *ldata,
+ CustomData *pdata, int lindex[4], int findex,
+ const int polyindex,
+ const int mf_len, /* 3 or 4 */
+
+ /* cache values to avoid lookups every time */
+ const int numTex, /* CustomData_number_of_layers(pdata, CD_MTEXPOLY) */
+ const int numCol, /* CustomData_number_of_layers(ldata, CD_MLOOPCOL) */
+ const bool hasPCol, /* CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL) */
+ const bool hasOrigSpace /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */
+)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ int i, j;
+
+ for (i = 0; i < numTex; i++) {
+ texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
+
+ ME_MTEXFACE_CPY(texface, texpoly);
+
+ for (j = 0; j < mf_len; j++) {
+ mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i);
+ copy_v2_v2(texface->uv[j], mloopuv->uv);
+ }
+ }
+
+ for (i = 0; i < numCol; i++) {
+ mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
+
+ for (j = 0; j < mf_len; j++) {
+ mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i);
+ MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
+ }
+ }
+
+ if (hasPCol) {
+ mcol = CustomData_get(fdata, findex, CD_PREVIEW_MCOL);
+
+ for (j = 0; j < mf_len; j++) {
+ mloopcol = CustomData_get(ldata, lindex[j], CD_PREVIEW_MLOOPCOL);
+ MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
+ }
+ }
+
+ if (hasOrigSpace) {
+ OrigSpaceFace *of = CustomData_get(fdata, findex, CD_ORIGSPACE);
+ OrigSpaceLoop *lof;
+
+ for (j = 0; j < mf_len; j++) {
+ lof = CustomData_get(ldata, lindex[j], CD_ORIGSPACE_MLOOP);
+ copy_v2_v2(of->uv[j], lof->uv);
+ }
+ }
+}
+
+/**
+ * Recreate tessellation.
+ *
+ * use_poly_origindex sets whether or not the tessellation faces' origindex
+ * layer should point to original poly indices or real poly indices.
+ *
+ * use_face_origindex sets the tessellation faces' origindex layer
+ * to point to the tessellation faces themselves, not the polys.
+ *
+ * if both of the above are 0, it'll use the indices of the mpolys of the MPoly
+ * data in pdata, and ignore the origindex layer altogether.
+ *
+ * \return number of tessellation faces.
+ */
+int BKE_mesh_recalc_tessellation(CustomData *fdata,
+ CustomData *ldata, CustomData *pdata,
+ MVert *mvert, int totface, int totloop,
+ int totpoly,
+ /* when tessellating to recalculate normals after
+ * we can skip copying here */
+ const bool do_face_nor_cpy)
+{
+ /* use this to avoid locking pthread for _every_ polygon
+ * and calling the fill function */
+
+#define USE_TESSFACE_SPEEDUP
+#define USE_TESSFACE_QUADS // NEEDS FURTHER TESTING
+
+#define TESSFACE_SCANFILL (1 << 0)
+#define TESSFACE_IS_QUAD (1 << 1)
+
+ const int looptris_tot = poly_to_tri_count(totpoly, totloop);
+
+ MPoly *mp, *mpoly;
+ MLoop *ml, *mloop;
+ MFace *mface, *mf;
+ ScanFillContext sf_ctx;
+ ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first;
+ ScanFillFace *sf_tri;
+ MemArena *sf_arena = NULL;
+ int *mface_to_poly_map;
+ int lindex[4]; /* only ever use 3 in this case */
+ int poly_index, j, mface_index;
+
+ const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+ const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
+ const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+
+ mpoly = CustomData_get_layer(pdata, CD_MPOLY);
+ mloop = CustomData_get_layer(ldata, CD_MLOOP);
+
+ /* allocate the length of totfaces, avoid many small reallocs,
+ * if all faces are tri's it will be correct, quads == 2x allocs */
+ /* take care. we are _not_ calloc'ing so be sure to initialize each field */
+ mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * (size_t)looptris_tot, __func__);
+ mface = MEM_mallocN(sizeof(*mface) * (size_t)looptris_tot, __func__);
+
+ mface_index = 0;
+ mp = mpoly;
+ for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
+ const unsigned int mp_loopstart = (unsigned int)mp->loopstart;
+ if (mp->totloop < 3) {
+ /* do nothing */
+ }
+
+#ifdef USE_TESSFACE_SPEEDUP
+
+#define ML_TO_MF(i1, i2, i3) \
+ mface_to_poly_map[mface_index] = poly_index; \
+ mf = &mface[mface_index]; \
+ /* set loop indices, transformed to vert indices later */ \
+ mf->v1 = mp_loopstart + i1; \
+ mf->v2 = mp_loopstart + i2; \
+ mf->v3 = mp_loopstart + i3; \
+ mf->v4 = 0; \
+ mf->mat_nr = mp->mat_nr; \
+ mf->flag = mp->flag; \
+ mf->edcode = 0; \
+ (void)0
+
+/* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */
+#define ML_TO_MF_QUAD() \
+ mface_to_poly_map[mface_index] = poly_index; \
+ mf = &mface[mface_index]; \
+ /* set loop indices, transformed to vert indices later */ \
+ mf->v1 = mp_loopstart + 0; /* EXCEPTION */ \
+ mf->v2 = mp_loopstart + 1; /* EXCEPTION */ \
+ mf->v3 = mp_loopstart + 2; /* EXCEPTION */ \
+ mf->v4 = mp_loopstart + 3; /* EXCEPTION */ \
+ mf->mat_nr = mp->mat_nr; \
+ mf->flag = mp->flag; \
+ mf->edcode = TESSFACE_IS_QUAD; /* EXCEPTION */ \
+ (void)0
+
+
+ else if (mp->totloop == 3) {
+ ML_TO_MF(0, 1, 2);
+ mface_index++;
+ }
+ else if (mp->totloop == 4) {
+#ifdef USE_TESSFACE_QUADS
+ ML_TO_MF_QUAD();
+ mface_index++;
+#else
+ ML_TO_MF(0, 1, 2);
+ mface_index++;
+ ML_TO_MF(0, 2, 3);
+ mface_index++;
+#endif
+ }
+#endif /* USE_TESSFACE_SPEEDUP */
+ else {
+#define USE_TESSFACE_CALCNORMAL
+
+ unsigned int totfilltri;
+
+#ifdef USE_TESSFACE_CALCNORMAL
+ float normal[3];
+ zero_v3(normal);
+#endif
+ ml = mloop + mp->loopstart;
+
+ if (UNLIKELY(sf_arena == NULL)) {
+ sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
+ }
+
+ BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
+ sf_vert_first = NULL;
+ sf_vert_last = NULL;
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, mvert[ml->v].co);
+
+ sf_vert->keyindex = (unsigned int)(mp->loopstart + j);
+
+ if (sf_vert_last) {
+ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
+#ifdef USE_TESSFACE_CALCNORMAL
+ add_newell_cross_v3_v3v3(normal, sf_vert_last->co, sf_vert->co);
+#endif
+ }
+
+ if (!sf_vert_first)
+ sf_vert_first = sf_vert;
+ sf_vert_last = sf_vert;
+ }
+ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first);
+#ifdef USE_TESSFACE_CALCNORMAL
+ add_newell_cross_v3_v3v3(normal, sf_vert_last->co, sf_vert_first->co);
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f;
+ }
+ totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, normal);
+#else
+ totfilltri = BLI_scanfill_calc(&sf_ctx, 0);
+#endif
+ BLI_assert(totfilltri <= (unsigned int)(mp->totloop - 2));
+ (void)totfilltri;
+
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) {
+ mface_to_poly_map[mface_index] = poly_index;
+ mf = &mface[mface_index];
+
+ /* set loop indices, transformed to vert indices later */
+ mf->v1 = sf_tri->v1->keyindex;
+ mf->v2 = sf_tri->v2->keyindex;
+ mf->v3 = sf_tri->v3->keyindex;
+ mf->v4 = 0;
+
+ mf->mat_nr = mp->mat_nr;
+ mf->flag = mp->flag;
+
+#ifdef USE_TESSFACE_SPEEDUP
+ mf->edcode = TESSFACE_SCANFILL; /* tag for sorting loop indices */
+#endif
+
+ mface_index++;
+ }
+
+ BLI_scanfill_end_arena(&sf_ctx, sf_arena);
+
+#undef USE_TESSFACE_CALCNORMAL
+ }
+ }
+
+ if (sf_arena) {
+ BLI_memarena_free(sf_arena);
+ sf_arena = NULL;
+ }
+
+ CustomData_free(fdata, totface);
+ totface = mface_index;
+
+ BLI_assert(totface <= looptris_tot);
+
+ /* not essential but without this we store over-alloc'd memory in the CustomData layers */
+ if (LIKELY(looptris_tot != totface)) {
+ mface = MEM_reallocN(mface, sizeof(*mface) * (size_t)totface);
+ mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * (size_t)totface);
+ }
+
+ CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
+
+ /* CD_ORIGINDEX will contain an array of indices from tessfaces to the polygons
+ * they are directly tessellated from */
+ CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
+ CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+
+ if (do_face_nor_cpy) {
+ /* If polys have a normals layer, copying that to faces can help
+ * avoid the need to recalculate normals later */
+ if (CustomData_has_layer(pdata, CD_NORMAL)) {
+ float (*pnors)[3] = CustomData_get_layer(pdata, CD_NORMAL);
+ float (*fnors)[3] = CustomData_add_layer(fdata, CD_NORMAL, CD_CALLOC, NULL, totface);
+ for (mface_index = 0; mface_index < totface; mface_index++) {
+ copy_v3_v3(fnors[mface_index], pnors[mface_to_poly_map[mface_index]]);
+ }
+ }
+ }
+
+ mf = mface;
+ for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
+
+#ifdef USE_TESSFACE_QUADS
+ const int mf_len = mf->edcode & TESSFACE_IS_QUAD ? 4 : 3;
+#endif
+
+#ifdef USE_TESSFACE_SPEEDUP
+ /* skip sorting when not using ngons */
+ if (UNLIKELY(mf->edcode & TESSFACE_SCANFILL))
+#endif
+ {
+ /* sort loop indices to ensure winding is correct */
+ if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
+ if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3);
+ if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
+
+ if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
+ if (mf->v2 > mf->v3) SWAP(unsigned int, mf->v2, mf->v3);
+ if (mf->v1 > mf->v2) SWAP(unsigned int, mf->v1, mf->v2);
+ }
+
+ /* end abusing the edcode */
+#if defined(USE_TESSFACE_QUADS) || defined(USE_TESSFACE_SPEEDUP)
+ mf->edcode = 0;
+#endif
+
+
+ lindex[0] = (int)mf->v1;
+ lindex[1] = (int)mf->v2;
+ lindex[2] = (int)mf->v3;
+#ifdef USE_TESSFACE_QUADS
+ if (mf_len == 4) lindex[3] = (int)mf->v4;
+#endif
+
+ /*transform loop indices to vert indices*/
+ mf->v1 = mloop[mf->v1].v;
+ mf->v2 = mloop[mf->v2].v;
+ mf->v3 = mloop[mf->v3].v;
+#ifdef USE_TESSFACE_QUADS
+ if (mf_len == 4) mf->v4 = mloop[mf->v4].v;
+#endif
+
+ BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
+ lindex, mface_index, mface_to_poly_map[mface_index],
+#ifdef USE_TESSFACE_QUADS
+ mf_len,
+#else
+ 3,
+#endif
+ numTex, numCol, hasPCol, hasOrigSpace);
+
+
+#ifdef USE_TESSFACE_QUADS
+ test_index_face(mf, fdata, mface_index, mf_len);
+#endif
+
+ }
+
+ return totface;
+
+#undef USE_TESSFACE_SPEEDUP
+
+}
+
+
+#ifdef USE_BMESH_SAVE_AS_COMPAT
+
+/**
+ * This function recreates a tessellation.
+ * returns number of tessellation faces.
+ *
+ * for forwards compat only quad->tri polys to mface, skip ngons.
+ */
+int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
+ struct CustomData *pdata, int totface, int UNUSED(totloop), int totpoly)
+{
+ MLoop *mloop;
+
+ int lindex[4];
+ int i;
+ int k;
+
+ MPoly *mp, *mpoly;
+ MFace *mface, *mf;
+
+ const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+ const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
+ const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+
+ /* over-alloc, ngons will be skipped */
+ mface = MEM_mallocN(sizeof(*mface) * (size_t)totpoly, __func__);
+
+ mpoly = CustomData_get_layer(pdata, CD_MPOLY);
+ mloop = CustomData_get_layer(ldata, CD_MLOOP);
+
+ mp = mpoly;
+ k = 0;
+ for (i = 0; i < totpoly; i++, mp++) {
+ if (ELEM(mp->totloop, 3, 4)) {
+ const unsigned int mp_loopstart = (unsigned int)mp->loopstart;
+ mf = &mface[k];
+
+ mf->mat_nr = mp->mat_nr;
+ mf->flag = mp->flag;
+
+ mf->v1 = mp_loopstart + 0;
+ mf->v2 = mp_loopstart + 1;
+ mf->v3 = mp_loopstart + 2;
+ mf->v4 = (mp->totloop == 4) ? (mp_loopstart + 3) : 0;
+
+ /* abuse edcode for temp storage and clear next loop */
+ mf->edcode = (char)mp->totloop; /* only ever 3 or 4 */
+
+ k++;
+ }
+ }
+
+ CustomData_free(fdata, totface);
+
+ totface = k;
+
+ CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
+
+ CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+
+ mp = mpoly;
+ k = 0;
+ for (i = 0; i < totpoly; i++, mp++) {
+ if (ELEM(mp->totloop, 3, 4)) {
+ mf = &mface[k];
+
+ if (mf->edcode == 3) {
+ /* sort loop indices to ensure winding is correct */
+ /* NO SORT - looks like we can skip this */
+
+ lindex[0] = (int)mf->v1;
+ lindex[1] = (int)mf->v2;
+ lindex[2] = (int)mf->v3;
+ lindex[3] = 0; /* unused */
+
+ /* transform loop indices to vert indices */
+ mf->v1 = mloop[mf->v1].v;
+ mf->v2 = mloop[mf->v2].v;
+ mf->v3 = mloop[mf->v3].v;
+
+ BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
+ lindex, k, i, 3,
+ numTex, numCol, hasPCol, hasOrigSpace);
+ test_index_face(mf, fdata, k, 3);
+ }
+ else {
+ /* sort loop indices to ensure winding is correct */
+ /* NO SORT - looks like we can skip this */
+
+ lindex[0] = (int)mf->v1;
+ lindex[1] = (int)mf->v2;
+ lindex[2] = (int)mf->v3;
+ lindex[3] = (int)mf->v4;
+
+ /* transform loop indices to vert indices */
+ mf->v1 = mloop[mf->v1].v;
+ mf->v2 = mloop[mf->v2].v;
+ mf->v3 = mloop[mf->v3].v;
+ mf->v4 = mloop[mf->v4].v;
+
+ BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
+ lindex, k, i, 4,
+ numTex, numCol, hasPCol, hasOrigSpace);
+ test_index_face(mf, fdata, k, 4);
+ }
+
+ mf->edcode = 0;
+
+ k++;
+ }
+ }
+
+ return k;
+}
+#endif /* USE_BMESH_SAVE_AS_COMPAT */
+
+
+static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata,
+ MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol)
+{
+ MTFace *texface;
+ MTexPoly *texpoly;
+ MCol *mcol;
+ MLoopCol *mloopcol;
+ MLoopUV *mloopuv;
+ MFace *mf;
+ int i;
+
+ mf = mface + findex;
+
+ for (i = 0; i < numTex; i++) {
+ texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
+ texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, findex, i);
+
+ ME_MTEXFACE_CPY(texpoly, texface);
+
+ mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
+ copy_v2_v2(mloopuv->uv, texface->uv[0]); mloopuv++;
+ copy_v2_v2(mloopuv->uv, texface->uv[1]); mloopuv++;
+ copy_v2_v2(mloopuv->uv, texface->uv[2]); mloopuv++;
+
+ if (mf->v4) {
+ copy_v2_v2(mloopuv->uv, texface->uv[3]); mloopuv++;
+ }
+ }
+
+ for (i = 0; i < numCol; i++) {
+ mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
+ mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
+
+ MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]); mloopcol++;
+ MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[1]); mloopcol++;
+ MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[2]); mloopcol++;
+ if (mf->v4) {
+ MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[3]); mloopcol++;
+ }
+ }
+
+ if (CustomData_has_layer(fdata, CD_MDISPS)) {
+ MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS);
+ MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS);
+ float (*disps)[3] = fd->disps;
+ int tot = mf->v4 ? 4 : 3;
+ int corners;
+
+ if (CustomData_external_test(fdata, CD_MDISPS)) {
+ if (id && fdata->external) {
+ CustomData_external_add(ldata, id, CD_MDISPS,
+ totloop, fdata->external->filename);
+ }
+ }
+
+ corners = multires_mdisp_corners(fd);
+
+ if (corners == 0) {
+ /* Empty MDisp layers appear in at least one of the sintel.blend files.
+ * Not sure why this happens, but it seems fine to just ignore them here.
+ * If (corners == 0) for a non-empty layer though, something went wrong. */
+ BLI_assert(fd->totdisp == 0);
+ }
+ else {
+ const int side = (int)sqrtf((float)(fd->totdisp / corners));
+ const int side_sq = side * side;
+ const size_t disps_size = sizeof(float[3]) * (size_t)side_sq;
+
+ for (i = 0; i < tot; i++, disps += side_sq, ld++) {
+ ld->totdisp = side_sq;
+ ld->level = (int)(logf((float)side - 1.0f) / (float)M_LN2) + 1;
+
+ if (ld->disps)
+ MEM_freeN(ld->disps);
+
+ ld->disps = MEM_mallocN(disps_size, "converted loop mdisps");
+ if (fd->disps) {
+ memcpy(ld->disps, disps, disps_size);
+ }
+ else {
+ memset(ld->disps, 0, disps_size);
+ }
+ }
+ }
+ }
+}
+
+
+void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
+{
+ BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id, &mesh->fdata, &mesh->ldata, &mesh->pdata,
+ mesh->totedge, mesh->totface, mesh->totloop, mesh->totpoly,
+ mesh->medge, mesh->mface,
+ &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly);
+
+ BKE_mesh_update_customdata_pointers(mesh, true);
+}
+
+/* the same as BKE_mesh_convert_mfaces_to_mpolys but oriented to be used in do_versions from readfile.c
+ * the difference is how active/render/clone/stencil indices are handled here
+ *
+ * normally thay're being set from pdata which totally makes sense for meshes which are already
+ * converted to bmesh structures, but when loading older files indices shall be updated in other
+ * way around, so newly added pdata and ldata would have this indices set based on fdata layer
+ *
+ * this is normally only needed when reading older files, in all other cases BKE_mesh_convert_mfaces_to_mpolys
+ * shall be always used
+ */
+void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
+{
+ BKE_mesh_convert_mfaces_to_mpolys_ex(&mesh->id, &mesh->fdata, &mesh->ldata, &mesh->pdata,
+ mesh->totedge, mesh->totface, mesh->totloop, mesh->totpoly,
+ mesh->medge, mesh->mface,
+ &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly);
+
+ CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->pdata, &mesh->ldata);
+
+ BKE_mesh_update_customdata_pointers(mesh, true);
+}
+
+void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata,
+ int totedge_i, int totface_i, int totloop_i, int totpoly_i,
+ MEdge *medge, MFace *mface,
+ int *totloop_r, int *totpoly_r,
+ MLoop **mloop_r, MPoly **mpoly_r)
+{
+ MFace *mf;
+ MLoop *ml, *mloop;
+ MPoly *mp, *mpoly;
+ MEdge *me;
+ EdgeHash *eh;
+ int numTex, numCol;
+ int i, j, totloop, totpoly, *polyindex;
+
+ /* just in case some of these layers are filled in (can happen with python created meshes) */
+ CustomData_free(ldata, totloop_i);
+ CustomData_free(pdata, totpoly_i);
+
+ totpoly = totface_i;
+ mpoly = MEM_callocN(sizeof(MPoly) * (size_t)totpoly, "mpoly converted");
+ CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly);
+
+ numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
+ numCol = CustomData_number_of_layers(fdata, CD_MCOL);
+
+ totloop = 0;
+ mf = mface;
+ for (i = 0; i < totface_i; i++, mf++) {
+ totloop += mf->v4 ? 4 : 3;
+ }
+
+ mloop = MEM_callocN(sizeof(MLoop) * (size_t)totloop, "mloop converted");
+
+ CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop);
+
+ CustomData_to_bmeshpoly(fdata, pdata, ldata, totloop, totpoly);
+
+ if (id) {
+ /* ensure external data is transferred */
+ CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i);
+ }
+
+ eh = BLI_edgehash_new_ex(__func__, (unsigned int)totedge_i);
+
+ /* build edge hash */
+ me = medge;
+ for (i = 0; i < totedge_i; i++, me++) {
+ BLI_edgehash_insert(eh, me->v1, me->v2, SET_UINT_IN_POINTER(i));
+
+ /* unrelated but avoid having the FGON flag enabled, so we can reuse it later for something else */
+ me->flag &= ~ME_FGON;
+ }
+
+ polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
+
+ j = 0; /* current loop index */
+ ml = mloop;
+ mf = mface;
+ mp = mpoly;
+ for (i = 0; i < totface_i; i++, mf++, mp++) {
+ mp->loopstart = j;
+
+ mp->totloop = mf->v4 ? 4 : 3;
+
+ mp->mat_nr = mf->mat_nr;
+ mp->flag = mf->flag;
+
+# define ML(v1, v2) { \
+ ml->v = mf->v1; \
+ ml->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); \
+ ml++; j++; \
+ } (void)0
+
+ ML(v1, v2);
+ ML(v2, v3);
+ if (mf->v4) {
+ ML(v3, v4);
+ ML(v4, v1);
+ }
+ else {
+ ML(v3, v1);
+ }
+
+# undef ML
+
+ bm_corners_to_loops_ex(id, fdata, ldata, pdata, mface, totloop, i, mp->loopstart, numTex, numCol);
+
+ if (polyindex) {
+ *polyindex = i;
+ polyindex++;
+ }
+ }
+
+ /* note, we don't convert NGons at all, these are not even real ngons,
+ * they have their own UV's, colors etc - its more an editing feature. */
+
+ BLI_edgehash_free(eh, NULL);
+
+ *totpoly_r = totpoly;
+ *totloop_r = totloop;
+ *mpoly_r = mpoly;
+ *mloop_r = mloop;
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Flag Flushing
+ * \{ */
+
+/* update the hide flag for edges and faces from the corresponding
+ * flag in verts */
+void BKE_mesh_flush_hidden_from_verts_ex(const MVert *mvert,
+ const MLoop *mloop,
+ MEdge *medge, const int totedge,
+ MPoly *mpoly, const int totpoly)
+{
+ int i, j;
+
+ for (i = 0; i < totedge; i++) {
+ MEdge *e = &medge[i];
+ if (mvert[e->v1].flag & ME_HIDE ||
+ mvert[e->v2].flag & ME_HIDE)
+ {
+ e->flag |= ME_HIDE;
+ }
+ else {
+ e->flag &= ~ME_HIDE;
+ }
+ }
+ for (i = 0; i < totpoly; i++) {
+ MPoly *p = &mpoly[i];
+ p->flag &= (char)~ME_HIDE;
+ for (j = 0; j < p->totloop; j++) {
+ if (mvert[mloop[p->loopstart + j].v].flag & ME_HIDE)
+ p->flag |= ME_HIDE;
+ }
+ }
+}
+void BKE_mesh_flush_hidden_from_verts(Mesh *me)
+{
+ BKE_mesh_flush_hidden_from_verts_ex(me->mvert, me->mloop,
+ me->medge, me->totedge,
+ me->mpoly, me->totpoly);
+}
+
+void BKE_mesh_flush_hidden_from_polys_ex(MVert *mvert,
+ const MLoop *mloop,
+ MEdge *medge, const int UNUSED(totedge),
+ const MPoly *mpoly, const int totpoly)
+{
+ const MPoly *mp;
+ int i;
+
+ i = totpoly;
+ for (mp = mpoly; i--; mp++) {
+ if (mp->flag & ME_HIDE) {
+ const MLoop *ml;
+ int j;
+ j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ mvert[ml->v].flag |= ME_HIDE;
+ medge[ml->e].flag |= ME_HIDE;
+ }
+ }
+ }
+
+ i = totpoly;
+ for (mp = mpoly; i--; mp++) {
+ if ((mp->flag & ME_HIDE) == 0) {
+ const MLoop *ml;
+ int j;
+ j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ mvert[ml->v].flag &= (char)~ME_HIDE;
+ medge[ml->e].flag &= (char)~ME_HIDE;
+ }
+ }
+ }
+}
+void BKE_mesh_flush_hidden_from_polys(Mesh *me)
+{
+ BKE_mesh_flush_hidden_from_polys_ex(me->mvert, me->mloop,
+ me->medge, me->totedge,
+ me->mpoly, me->totpoly);
+}
+
+/**
+ * simple poly -> vert/edge selection.
+ */
+void BKE_mesh_flush_select_from_polys_ex(MVert *mvert, const int totvert,
+ const MLoop *mloop,
+ MEdge *medge, const int totedge,
+ const MPoly *mpoly, const int totpoly)
+{
+ MVert *mv;
+ MEdge *med;
+ const MPoly *mp;
+ int i;
+
+ i = totvert;
+ for (mv = mvert; i--; mv++) {
+ mv->flag &= (char)~SELECT;
+ }
+
+ i = totedge;
+ for (med = medge; i--; med++) {
+ med->flag &= ~SELECT;
+ }
+
+ i = totpoly;
+ for (mp = mpoly; i--; mp++) {
+ /* assume if its selected its not hidden and none of its verts/edges are hidden
+ * (a common assumption)*/
+ if (mp->flag & ME_FACE_SEL) {
+ const MLoop *ml;
+ int j;
+ j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ mvert[ml->v].flag |= SELECT;
+ medge[ml->e].flag |= SELECT;
+ }
+ }
+ }
+}
+void BKE_mesh_flush_select_from_polys(Mesh *me)
+{
+ BKE_mesh_flush_select_from_polys_ex(me->mvert, me->totvert,
+ me->mloop,
+ me->medge, me->totedge,
+ me->mpoly, me->totpoly);
+}
+
+void BKE_mesh_flush_select_from_verts_ex(const MVert *mvert, const int UNUSED(totvert),
+ const MLoop *mloop,
+ MEdge *medge, const int totedge,
+ MPoly *mpoly, const int totpoly)
+{
+ MEdge *med;
+ MPoly *mp;
+ int i;
+
+ /* edges */
+ i = totedge;
+ for (med = medge; i--; med++) {
+ if ((med->flag & ME_HIDE) == 0) {
+ if ((mvert[med->v1].flag & SELECT) && (mvert[med->v2].flag & SELECT)) {
+ med->flag |= SELECT;
+ }
+ else {
+ med->flag &= ~SELECT;
+ }
+ }
+ }
+
+ /* polys */
+ i = totpoly;
+ for (mp = mpoly; i--; mp++) {
+ if ((mp->flag & ME_HIDE) == 0) {
+ int ok = TRUE;
+ const MLoop *ml;
+ int j;
+ j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ if ((mvert[ml->v].flag & SELECT) == 0) {
+ ok = FALSE;
+ break;
+ }
+ }
+
+ if (ok) {
+ mp->flag |= ME_FACE_SEL;
+ }
+ else {
+ mp->flag &= (char)~ME_FACE_SEL;
+ }
+ }
+ }
+}
+void BKE_mesh_flush_select_from_verts(Mesh *me)
+{
+ BKE_mesh_flush_select_from_verts_ex(me->mvert, me->totvert,
+ me->mloop,
+ me->medge, me->totedge,
+ me->mpoly, me->totpoly);
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Smooth Groups
+ * \{ */
+
+/**
+ * Calculate smooth groups from sharp edges.
+ *
+ * \param r_totgroup The total number of groups, 1 or more.
+ * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1.
+ */
+int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
+ const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totloop,
+ int *r_totgroup, const bool use_bitflags)
+{
+ int *poly_groups;
+ int *poly_stack;
+
+ int poly_prev = 0;
+ const int temp_poly_group_id = 3; /* Placeholder value. */
+ const int poly_group_id_overflowed = 5; /* Group we could not find any available bit, will be reset to 0 at end */
+ int tot_group = 0;
+ bool group_id_overflow = false;
+
+ /* map vars */
+ MeshElemMap *edge_poly_map;
+ int *edge_poly_mem;
+
+ if (totpoly == 0) {
+ *r_totgroup = 0;
+ return NULL;
+ }
+
+ BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem,
+ medge, totedge,
+ mpoly, totpoly,
+ mloop, totloop);
+
+ poly_groups = MEM_callocN(sizeof(int) * (size_t)totpoly, __func__);
+ poly_stack = MEM_mallocN(sizeof(int) * (size_t)totpoly, __func__);
+
+ while (true) {
+ int poly;
+ int bit_poly_group_mask = 0;
+ int poly_group_id;
+ int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */
+
+ for (poly = poly_prev; poly < totpoly; poly++) {
+ if (poly_groups[poly] == 0) {
+ break;
+ }
+ }
+
+ if (poly == totpoly) {
+ /* all done */
+ break;
+ }
+
+ poly_group_id = use_bitflags ? temp_poly_group_id : ++tot_group;
+
+ /* start searching from here next time */
+ poly_prev = poly + 1;
+
+ poly_groups[poly] = poly_group_id;
+ poly_stack[ps_end_idx++] = poly;
+
+ while (ps_curr_idx != ps_end_idx) {
+ const MPoly *mp;
+ const MLoop *ml;
+ int j;
+
+ poly = poly_stack[ps_curr_idx++];
+ BLI_assert(poly_groups[poly] == poly_group_id);
+
+ mp = &mpoly[poly];
+ for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
+ /* loop over poly users */
+ const MeshElemMap *map_ele = &edge_poly_map[ml->e];
+ int *p = map_ele->indices;
+ int i = map_ele->count;
+ if (!(medge[ml->e].flag & ME_SHARP)) {
+ for (; i--; p++) {
+ /* if we meet other non initialized its a bug */
+ BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
+
+ if (poly_groups[*p] == 0) {
+ poly_groups[*p] = poly_group_id;
+ poly_stack[ps_end_idx++] = *p;
+ }
+ }
+ }
+ else if (use_bitflags) {
+ /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
+ for (; i--; p++) {
+ int bit = poly_groups[*p];
+ if (!ELEM3(bit, 0, poly_group_id, poly_group_id_overflowed) &&
+ !(bit_poly_group_mask & bit))
+ {
+ bit_poly_group_mask |= bit;
+ }
+ }
+ }
+ }
+ }
+ /* And now, we have all our poly from current group in poly_stack (from 0 to (ps_end_idx - 1)), as well as
+ * all smoothgroups bits we can't use in bit_poly_group_mask.
+ */
+ if (use_bitflags) {
+ int i, *p, gid_bit = 0;
+ poly_group_id = 1;
+
+ /* Find first bit available! */
+ for (; (poly_group_id & bit_poly_group_mask) && (gid_bit < 32); gid_bit++) {
+ poly_group_id <<= 1; /* will 'overflow' on last possible iteration. */
+ }
+ if (UNLIKELY(gid_bit > 31)) {
+ /* All bits used in contiguous smooth groups, we can't do much!
+ * Note: this is *very* unlikely - theoretically, four groups are enough, I don't think we can reach
+ * this goal with such a simple algo, but I don't think either we'll never need all 32 groups!
+ */
+ printf("Warning, could not find an available id for current smooth group, faces will me marked "
+ "as out of any smooth group...\n");
+ poly_group_id = poly_group_id_overflowed; /* Can't use 0, will have to set them to this value later. */
+ group_id_overflow = true;
+ }
+ if (gid_bit > tot_group) {
+ tot_group = gid_bit;
+ }
+ /* And assign the final smooth group id to that poly group! */
+ for (i = ps_end_idx, p = poly_stack; i--; p++) {
+ poly_groups[*p] = poly_group_id;
+ }
+ }
+ }
+
+ if (UNLIKELY(group_id_overflow)) {
+ int i = totpoly, *gid = poly_groups;
+ for (; i--; gid++) {
+ if (*gid == poly_group_id_overflowed) {
+ *gid = 0;
+ }
+ }
+ }
+
+ MEM_freeN(edge_poly_map);
+ MEM_freeN(edge_poly_mem);
+ MEM_freeN(poly_stack);
+
+ *r_totgroup = tot_group + 1;
+
+ return poly_groups;
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Spatial Calculation
+ * \{ */
+
+/**
+ * This function takes the difference between 2 vertex-coord-arrays
+ * (\a vert_cos_src, \a vert_cos_dst),
+ * and applies the difference to \a vert_cos_new relative to \a vert_cos_org.
+ *
+ * \param vert_cos_src reference deform source.
+ * \param vert_cos_dst reference deform destination.
+ *
+ * \param vert_cos_org reference for the output location.
+ * \param vert_cos_new resulting coords.
+ */
+void BKE_mesh_calc_relative_deform(
+ const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totvert,
+
+ const float (*vert_cos_src)[3],
+ const float (*vert_cos_dst)[3],
+
+ const float (*vert_cos_org)[3],
+ float (*vert_cos_new)[3])
+{
+ const MPoly *mp;
+ int i;
+
+ int *vert_accum = MEM_callocN(sizeof(*vert_accum) * (size_t)totvert, __func__);
+
+ memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * (size_t)totvert);
+
+ for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
+ const MLoop *loopstart = mloop + mp->loopstart;
+ int j;
+
+ for (j = 0; j < mp->totloop; j++) {
+ unsigned int v_prev = loopstart[(mp->totloop + (j - 1)) % mp->totloop].v;
+ unsigned int v_curr = loopstart[j].v;
+ unsigned int v_next = loopstart[(j + 1) % mp->totloop].v;
+
+ float tvec[3];
+
+ barycentric_transform(
+ tvec, vert_cos_dst[v_curr],
+ vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
+ vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]
+ );
+
+ add_v3_v3(vert_cos_new[v_curr], tvec);
+ vert_accum[v_curr] += 1;
+ }
+ }
+
+ for (i = 0; i < totvert; i++) {
+ if (vert_accum[i]) {
+ mul_v3_fl(vert_cos_new[i], 1.0f / (float)vert_accum[i]);
+ }
+ else {
+ copy_v3_v3(vert_cos_new[i], vert_cos_org[i]);
+ }
+ }
+
+ MEM_freeN(vert_accum);
+}
+/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 2eced15a147..1c9576d74d0 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -49,7 +49,12 @@
#include "MEM_guardedalloc.h"
-#define SELECT 1
+/* loop v/e are unsigned, so using max uint_32 value as invalid marker... */
+#define INVALID_LOOP_EDGE_MARKER 4294967295u
+
+
+/** \name Internal functions
+ * \{ */
typedef union {
uint32_t verts[2];
@@ -181,17 +186,37 @@ static int search_polyloop_cmp(const void *v1, const void *v2)
/* Else, sort on loopstart. */
return sp1->loopstart > sp2->loopstart ? 1 : sp1->loopstart < sp2->loopstart ? -1 : 0;
}
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
-#define PRINT if (do_verbose) printf
+/** \name Mesh Validation
+ * \{ */
-int BKE_mesh_validate_arrays(Mesh *mesh,
- MVert *mverts, unsigned int totvert,
- MEdge *medges, unsigned int totedge,
- MFace *mfaces, unsigned int totface,
- MLoop *mloops, unsigned int totloop,
- MPoly *mpolys, unsigned int totpoly,
- MDeformVert *dverts, /* assume totvert length */
- const bool do_verbose, const bool do_fixes)
+#define PRINT_MSG(...) (void) \
+ ( \
+ ((do_verbose) ? printf(__VA_ARGS__) : 0))
+
+#define PRINT_ERR(...) (void) \
+ (is_valid = false, \
+ ((do_verbose) ? printf(__VA_ARGS__) : 0))
+
+/**
+ * Validate the mesh, \a do_fixes requires \a mesh to be non-null.
+ *
+ * \return false if no changes needed to be made.
+ */
+bool BKE_mesh_validate_arrays(Mesh *mesh,
+ MVert *mverts, unsigned int totvert,
+ MEdge *medges, unsigned int totedge,
+ MFace *mfaces, unsigned int totface,
+ MLoop *mloops, unsigned int totloop,
+ MPoly *mpolys, unsigned int totpoly,
+ MDeformVert *dverts, /* assume totvert length */
+ const bool do_verbose, const bool do_fixes,
+ bool *r_change)
{
# define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = true; } (void)0
# define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1)
@@ -206,6 +231,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
unsigned int i, j;
int *v;
+ bool is_valid = true;
+
bool do_edge_free = false;
bool do_face_free = false;
bool do_polyloop_free = false; /* This regroups loops and polys! */
@@ -216,15 +243,15 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
bool do_edge_recalc = false;
- EdgeHash *edge_hash = BLI_edgehash_new();
+ EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, totedge);
BLI_assert(!(do_fixes && mesh == NULL));
- PRINT("%s: verts(%u), edges(%u), loops(%u), polygons(%u)\n",
- __func__, totvert, totedge, totloop, totpoly);
+ PRINT_MSG("%s: verts(%u), edges(%u), loops(%u), polygons(%u)\n",
+ __func__, totvert, totedge, totloop, totpoly);
if (totedge == 0 && totpoly != 0) {
- PRINT("\tLogical error, %u polygons and 0 edges\n", totpoly);
+ PRINT_ERR("\tLogical error, %u polygons and 0 edges\n", totpoly);
do_edge_recalc = do_fixes;
}
@@ -233,7 +260,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
for (j = 0; j < 3; j++) {
if (!finite(mv->co[j])) {
- PRINT("\tVertex %u: has invalid coordinate\n", i);
+ PRINT_ERR("\tVertex %u: has invalid coordinate\n", i);
if (do_fixes) {
zero_v3(mv->co);
@@ -247,7 +274,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
}
if (fix_normal) {
- PRINT("\tVertex %u: has zero normal, assuming Z-up normal\n", i);
+ PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal\n", i);
if (do_fixes) {
mv->no[2] = SHRT_MAX;
verts_fixed = TRUE;
@@ -258,21 +285,21 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
for (i = 0, me = medges; i < totedge; i++, me++) {
int remove = FALSE;
if (me->v1 == me->v2) {
- PRINT("\tEdge %u: has matching verts, both %u\n", i, me->v1);
+ PRINT_ERR("\tEdge %u: has matching verts, both %u\n", i, me->v1);
remove = do_fixes;
}
if (me->v1 >= totvert) {
- PRINT("\tEdge %u: v1 index out of range, %u\n", i, me->v1);
+ PRINT_ERR("\tEdge %u: v1 index out of range, %u\n", i, me->v1);
remove = do_fixes;
}
if (me->v2 >= totvert) {
- PRINT("\tEdge %u: v2 index out of range, %u\n", i, me->v2);
+ PRINT_ERR("\tEdge %u: v2 index out of range, %u\n", i, me->v2);
remove = do_fixes;
}
if (BLI_edgehash_haskey(edge_hash, me->v1, me->v2)) {
- PRINT("\tEdge %u: is a duplicate of %d\n", i,
- GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, me->v1, me->v2)));
+ PRINT_ERR("\tEdge %u: is a duplicate of %d\n", i,
+ GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, me->v1, me->v2)));
remove = do_fixes;
}
@@ -288,13 +315,13 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
# define REMOVE_FACE_TAG(_mf) { _mf->v3 = 0; do_face_free = TRUE; } (void)0
# define CHECK_FACE_VERT_INDEX(a, b) \
if (mf->a == mf->b) { \
- PRINT(" face %u: verts invalid, " STRINGIFY(a) "/" STRINGIFY(b) " both %u\n", i, mf->a); \
+ PRINT_ERR(" face %u: verts invalid, " STRINGIFY(a) "/" STRINGIFY(b) " both %u\n", i, mf->a); \
remove = do_fixes; \
} (void)0
# define CHECK_FACE_EDGE(a, b) \
if (!BLI_edgehash_haskey(edge_hash, mf->a, mf->b)) { \
- PRINT(" face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) \
- " (%u,%u) is missing edge data\n", i, mf->a, mf->b); \
+ PRINT_ERR(" face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) \
+ " (%u,%u) is missing edge data\n", i, mf->a, mf->b); \
do_edge_recalc = TRUE; \
} (void)0
@@ -306,7 +333,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
SortFace *sf_prev;
unsigned int totsortface = 0;
- PRINT("No Polys, only tesselated Faces\n");
+ PRINT_ERR("No Polys, only tesselated Faces\n");
for (i = 0, mf = mfaces, sf = sort_faces; i < totface; i++, mf++) {
int remove = FALSE;
@@ -317,7 +344,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
do {
fv[fidx] = *(&(mf->v1) + fidx);
if (fv[fidx] >= totvert) {
- PRINT("\tFace %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]);
+ PRINT_ERR("\tFace %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]);
remove = do_fixes;
}
} while (fidx--);
@@ -394,14 +421,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
mf_prev = mfaces + sf_prev->index;
if (mf->v4) {
- PRINT("\tFace %u & %u: are duplicates (%u,%u,%u,%u) (%u,%u,%u,%u)\n",
- sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4,
- mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4);
+ PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u,%u) (%u,%u,%u,%u)\n",
+ sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4,
+ mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4);
}
else {
- PRINT("\tFace %u & %u: are duplicates (%u,%u,%u) (%u,%u,%u)\n",
- sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3,
- mf_prev->v1, mf_prev->v2, mf_prev->v3);
+ PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u) (%u,%u,%u)\n",
+ sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3,
+ mf_prev->v1, mf_prev->v2, mf_prev->v3);
}
}
@@ -446,13 +473,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
if (mp->loopstart < 0 || mp->totloop < 3) {
/* Invalid loop data. */
- PRINT("\tPoly %u is invalid (loopstart: %u, totloop: %u)\n", sp->index, mp->loopstart, mp->totloop);
+ PRINT_ERR("\tPoly %u is invalid (loopstart: %u, totloop: %u)\n",
+ sp->index, mp->loopstart, mp->totloop);
sp->invalid = TRUE;
}
else if (mp->loopstart + mp->totloop > totloop) {
/* Invalid loop data. */
- PRINT("\tPoly %u uses loops out of range (loopstart: %u, loopend: %u, max nbr of loops: %u)\n",
- sp->index, mp->loopstart, mp->loopstart + mp->totloop - 1, totloop - 1);
+ PRINT_ERR("\tPoly %u uses loops out of range (loopstart: %u, loopend: %u, max nbr of loops: %u)\n",
+ sp->index, mp->loopstart, mp->loopstart + mp->totloop - 1, totloop - 1);
sp->invalid = TRUE;
}
else {
@@ -467,7 +495,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++, v++) {
if (ml->v >= totvert) {
/* Invalid vert idx. */
- PRINT("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v);
+ PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v);
sp->invalid = TRUE;
}
@@ -480,7 +508,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
v = sp->verts;
for (j = 0; j < mp->totloop; j++, v++) {
if ((mverts[*v].flag & ME_VERT_TMP_TAG) == 0) {
- PRINT("\tPoly %u has duplicate vert reference at corner (%u)\n", i, j);
+ PRINT_ERR("\tPoly %u has duplicate vert reference at corner (%u)\n", i, j);
sp->invalid = TRUE;
}
mverts[*v].flag &= ~ME_VERT_TMP_TAG;
@@ -496,7 +524,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
v2 = mloops[sp->loopstart + (j + 1) % mp->totloop].v;
if (!BLI_edgehash_haskey(edge_hash, v1, v2)) {
/* Edge not existing. */
- PRINT("\tPoly %u needs missing edge (%u, %u)\n", sp->index, v1, v2);
+ PRINT_ERR("\tPoly %u needs missing edge (%u, %u)\n", sp->index, v1, v2);
if (do_fixes)
do_edge_recalc = TRUE;
else
@@ -508,11 +536,11 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
if (do_fixes) {
int prev_e = ml->e;
ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
- PRINT("\tLoop %u has invalid edge reference (%u), fixed using edge %u\n",
- sp->loopstart + j, prev_e, ml->e);
+ PRINT_ERR("\tLoop %u has invalid edge reference (%u), fixed using edge %u\n",
+ sp->loopstart + j, prev_e, ml->e);
}
else {
- PRINT("\tLoop %u has invalid edge reference (%u)\n", sp->loopstart + j, ml->e);
+ PRINT_ERR("\tLoop %u has invalid edge reference (%u)\n", sp->loopstart + j, ml->e);
sp->invalid = TRUE;
}
}
@@ -524,11 +552,11 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
if (do_fixes) {
int prev_e = ml->e;
ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
- PRINT("\tPoly %u has invalid edge reference (%u), fixed using edge %u\n",
- sp->index, prev_e, ml->e);
+ PRINT_ERR("\tPoly %u has invalid edge reference (%u), fixed using edge %u\n",
+ sp->index, prev_e, ml->e);
}
else {
- PRINT("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e);
+ PRINT_ERR("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e);
sp->invalid = TRUE;
}
}
@@ -546,16 +574,16 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
if (*v != *prev_v) {
int dlt = v - prev_v;
if (dlt > 1) {
- PRINT("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
- sp->index, *prev_v, dlt);
+ PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
+ sp->index, *prev_v, dlt);
sp->invalid = TRUE;
}
prev_v = v;
}
}
if (v - prev_v > 1) { /* Don't forget final verts! */
- PRINT("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
- sp->index, *prev_v, (int)(v - prev_v));
+ PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
+ sp->index, *prev_v, (int)(v - prev_v));
sp->invalid = TRUE;
}
}
@@ -633,11 +661,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
}
if ((p1_nv == p2_nv) && (memcmp(p1_v, p2_v, p1_nv * sizeof(*p1_v)) == 0)) {
if (do_verbose) {
- PRINT("\tPolys %u and %u use same vertices (%u",
- prev_sp->index, sp->index, *p1_v);
+ PRINT_ERR("\tPolys %u and %u use same vertices (%u",
+ prev_sp->index, sp->index, *p1_v);
for (j = 1; j < p1_nv; j++)
- PRINT(", %u", p1_v[j]);
- PRINT("), considering poly %u as invalid.\n", sp->index);
+ PRINT_ERR(", %u", p1_v[j]);
+ PRINT_ERR("), considering poly %u as invalid.\n", sp->index);
+ }
+ else {
+ is_valid = false;
}
sp->invalid = TRUE;
}
@@ -673,7 +704,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
/* Unused loops. */
if (prev_end < sp->loopstart) {
for (j = prev_end, ml = &mloops[prev_end]; j < sp->loopstart; j++, ml++) {
- PRINT("\tLoop %u is unused.\n", j);
+ PRINT_ERR("\tLoop %u is unused.\n", j);
if (do_fixes)
REMOVE_LOOP_TAG(ml);
}
@@ -682,8 +713,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
}
/* Multi-used loops. */
else if (prev_end > sp->loopstart) {
- PRINT("\tPolys %u and %u share loops from %u to %u, considering poly %u as invalid.\n",
- prev_sp->index, sp->index, sp->loopstart, prev_end, sp->index);
+ PRINT_ERR("\tPolys %u and %u share loops from %u to %u, considering poly %u as invalid.\n",
+ prev_sp->index, sp->index, sp->loopstart, prev_end, sp->index);
if (do_fixes) {
REMOVE_POLY_TAG((&mpolys[sp->index]));
/* DO NOT REMOVE ITS LOOPS!!!
@@ -701,7 +732,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
/* We may have some remaining unused loops to get rid of! */
if (prev_end < totloop) {
for (j = prev_end, ml = &mloops[prev_end]; j < totloop; j++, ml++) {
- PRINT("\tLoop %u is unused.\n", j);
+ PRINT_ERR("\tLoop %u is unused.\n", j);
if (do_fixes)
REMOVE_LOOP_TAG(ml);
}
@@ -721,14 +752,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
/* note, greater then max defgroups is accounted for in our code, but not < 0 */
if (!finite(dw->weight)) {
- PRINT("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
+ PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
if (do_fixes) {
dw->weight = 0.0f;
vert_weights_fixed = TRUE;
}
}
else if (dw->weight < 0.0f || dw->weight > 1.0f) {
- PRINT("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
+ PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
if (do_fixes) {
CLAMP(dw->weight, 0.0f, 1.0f);
vert_weights_fixed = TRUE;
@@ -736,7 +767,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
}
if (dw->def_nr < 0) {
- PRINT("\tVertex deform %u, has invalid group %d\n", i, dw->def_nr);
+ PRINT_ERR("\tVertex deform %u, has invalid group %d\n", i, dw->def_nr);
if (do_fixes) {
defvert_remove_group(dv, dw);
if (dv->dw) {
@@ -787,8 +818,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
int tot_elem = 0;
if (msel->index < 0) {
- PRINT("\tMesh select element %d type %d index is negative, "
- "resetting selection stack.\n", i, msel->type);
+ PRINT_ERR("\tMesh select element %d type %d index is negative, "
+ "resetting selection stack.\n", i, msel->type);
free_msel = TRUE;
break;
}
@@ -806,8 +837,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
}
if (msel->index > tot_elem) {
- PRINT("\tMesh select element %d type %d index %d is larger than data array size %d, "
- "resetting selection stack.\n", i, msel->type, msel->index, tot_elem);
+ PRINT_ERR("\tMesh select element %d type %d index %d is larger than data array size %d, "
+ "resetting selection stack.\n", i, msel->type, msel->index, tot_elem);
free_msel = TRUE;
break;
@@ -821,29 +852,49 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
}
}
- PRINT("%s: finished\n\n", __func__);
+ PRINT_MSG("%s: finished\n\n", __func__);
+
+ *r_change = (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);
- return (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);
+ return is_valid;
}
-static int mesh_validate_customdata(CustomData *data, const bool do_verbose, const bool do_fixes)
+static bool mesh_validate_customdata(CustomData *data, CustomDataMask mask,
+ const bool do_verbose, const bool do_fixes,
+ bool *r_change)
{
- int i = 0, has_fixes = 0;
+ bool is_valid = true;
+ bool has_fixes = false;
+ int i = 0;
- PRINT("%s: Checking %d CD layers...\n", __func__, data->totlayer);
+ PRINT_MSG("%s: Checking %d CD layers...\n", __func__, data->totlayer);
while (i < data->totlayer) {
CustomDataLayer *layer = &data->layers[i];
- CustomDataMask mask = CD_TYPE_AS_MASK(layer->type);
- int ok = 1;
+ bool ok = true;
+
+ if (CustomData_layertype_is_singleton(layer->type)) {
+ const int layer_tot = CustomData_number_of_layers(data, layer->type);
+ if (layer_tot > 1) {
+ PRINT_ERR("\tCustomDataLayer type %d is a singleton, found %d in Mesh structure\n",
+ layer->type, layer_tot);
+ ok = false;
+ }
+ }
- if ((mask & CD_MASK_MESH) == 0) {
- PRINT("\tCustomDataLayer type %d which isn't in CD_MASK_MESH is stored in Mesh structure\n", layer->type);
+ if (mask != 0) {
+ CustomDataMask layer_typemask = CD_TYPE_AS_MASK(layer->type);
+ if ((layer_typemask & mask) == 0) {
+ PRINT_ERR("\tCustomDataLayer type %d which isn't in the mask\n",
+ layer->type);
+ ok = false;
+ }
+ }
+ if (ok == false) {
if (do_fixes) {
CustomData_free_layer(data, layer->type, 0, i);
- ok = 0;
- has_fixes = 1;
+ has_fixes = true;
}
}
@@ -851,65 +902,455 @@ static int mesh_validate_customdata(CustomData *data, const bool do_verbose, con
i++;
}
- PRINT("%s: Finished\n\n", __func__);
+ PRINT_MSG("%s: Finished (is_valid=%d)\n\n", __func__, (int)!has_fixes);
- return has_fixes;
+ *r_change = has_fixes;
+
+ return is_valid;
}
#undef PRINT
-static int BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
- CustomData *ldata, CustomData *pdata,
- const bool do_verbose, const short do_fixes)
+/**
+ * \returns is_valid.
+ */
+bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
+ CustomData *ldata, CustomData *pdata,
+ const bool check_meshmask,
+ const bool do_verbose, const bool do_fixes,
+ bool *r_change)
{
- int vfixed = 0, efixed = 0, lfixed = 0, pfixed = 0;
+ bool is_valid = true;
+ bool is_change_v, is_change_e, is_change_l, is_change_p;
+ int tot_texpoly, tot_uvloop;
+ CustomDataMask mask = check_meshmask ? CD_MASK_MESH : 0;
+
+ is_valid &= mesh_validate_customdata(vdata, mask, do_verbose, do_fixes, &is_change_v);
+ is_valid &= mesh_validate_customdata(edata, mask, do_verbose, do_fixes, &is_change_e);
+ is_valid &= mesh_validate_customdata(ldata, mask, do_verbose, do_fixes, &is_change_l);
+ is_valid &= mesh_validate_customdata(pdata, mask, do_verbose, do_fixes, &is_change_p);
+
+ tot_texpoly = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ tot_uvloop = CustomData_number_of_layers(ldata, CD_MLOOPUV);
+ if (tot_texpoly != tot_uvloop) {
+ PRINT_ERR("\tCustomDataLayer mismatch, tot_texpoly(%d), tot_uvloop(%d)\n",
+ tot_texpoly, tot_uvloop);
+ }
- vfixed = mesh_validate_customdata(vdata, do_verbose, do_fixes);
- efixed = mesh_validate_customdata(edata, do_verbose, do_fixes);
- lfixed = mesh_validate_customdata(ldata, do_verbose, do_fixes);
- pfixed = mesh_validate_customdata(pdata, do_verbose, do_fixes);
+ *r_change = (is_change_v || is_change_e || is_change_l || is_change_p);
- return vfixed || efixed || lfixed || pfixed;
+ return is_valid;
}
+/**
+ * \see #DM_is_valid to call on derived meshes
+ *
+ * \returns true if a change is made.
+ */
int BKE_mesh_validate(Mesh *me, const int do_verbose)
{
- int layers_fixed = 0, arrays_fixed = 0;
+ bool is_valid = true;
+ bool is_change;
if (do_verbose) {
printf("MESH: %s\n", me->id.name + 2);
}
- layers_fixed = BKE_mesh_validate_all_customdata(&me->vdata, &me->edata, &me->ldata, &me->pdata, do_verbose, TRUE);
- arrays_fixed = BKE_mesh_validate_arrays(me,
- me->mvert, me->totvert,
- me->medge, me->totedge,
- me->mface, me->totface,
- me->mloop, me->totloop,
- me->mpoly, me->totpoly,
- me->dvert,
- do_verbose, true);
-
- if (layers_fixed || arrays_fixed) {
+ is_valid &= BKE_mesh_validate_all_customdata(
+ &me->vdata, &me->edata, &me->ldata, &me->pdata,
+ true,
+ do_verbose, true,
+ &is_change);
+
+ is_valid &= BKE_mesh_validate_arrays(
+ me,
+ me->mvert, me->totvert,
+ me->medge, me->totedge,
+ me->mface, me->totface,
+ me->mloop, me->totloop,
+ me->mpoly, me->totpoly,
+ me->dvert,
+ do_verbose, true,
+ &is_change);
+
+ if (is_change) {
DAG_id_tag_update(&me->id, OB_RECALC_DATA);
return true;
}
- return false;
+ else {
+ return false;
+ }
+}
+
+/**
+ * Duplicate of BM_mesh_cd_validate() for Mesh data.
+ */
+void BKE_mesh_cd_validate(Mesh *me)
+{
+ int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+ int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
+ int mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
+ int uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
+ int i;
+
+ if (LIKELY(totlayer_mtex == totlayer_uv)) {
+ /* pass */
+ }
+ else if (totlayer_mtex < totlayer_uv) {
+ do {
+ const char *from_name = me->ldata.layers[uv_index + totlayer_mtex].name;
+ CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name);
+ CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex);
+ } while (totlayer_uv != ++totlayer_mtex);
+ mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
+ }
+ else if (totlayer_uv < totlayer_mtex) {
+ do {
+ const char *from_name = me->pdata.layers[mtex_index + totlayer_uv].name;
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name);
+ CustomData_set_layer_unique_name(&me->ldata, totlayer_uv);
+ } while (totlayer_mtex != ++totlayer_uv);
+ uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
+ }
+
+ BLI_assert(totlayer_mtex == totlayer_uv);
+
+ /* Check uv/tex names match as well!!! */
+ for (i = 0; i < totlayer_mtex; i++, mtex_index++, uv_index++) {
+ const char *name_src = me->pdata.layers[mtex_index].name;
+ const char *name_dst = me->ldata.layers[uv_index].name;
+ if (!STREQ(name_src, name_dst)) {
+ BKE_mesh_uv_cdlayer_rename_index(me, mtex_index, uv_index, -1, name_src, false);
+ }
+ }
+}
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Stripping (removing invalid data)
+ * \{ */
+
+/* We need to keep this for edge creation (for now?), and some old readfile code... */
+void BKE_mesh_strip_loose_faces(Mesh *me)
+{
+ MFace *f;
+ int a, b;
+
+ for (a = b = 0, f = me->mface; a < me->totface; a++, f++) {
+ if (f->v3) {
+ if (a != b) {
+ memcpy(&me->mface[b], f, sizeof(me->mface[b]));
+ CustomData_copy_data(&me->fdata, &me->fdata, a, b, 1);
+ }
+ b++;
+ }
+ }
+ if (a != b) {
+ CustomData_free_elem(&me->fdata, b, a - b);
+ me->totface = b;
+ }
+}
+
+/* Works on both loops and polys! */
+/* Note: It won't try to guess which loops of an invalid poly to remove!
+ * this is the work of the caller, to mark those loops...
+ * See e.g. BKE_mesh_validate_arrays(). */
+void BKE_mesh_strip_loose_polysloops(Mesh *me)
+{
+ MPoly *p;
+ MLoop *l;
+ int a, b;
+ /* New loops idx! */
+ int *new_idx = MEM_mallocN(sizeof(int) * me->totloop, __func__);
+
+ for (a = b = 0, p = me->mpoly; a < me->totpoly; a++, p++) {
+ int invalid = FALSE;
+ int i = p->loopstart;
+ int stop = i + p->totloop;
+
+ if (stop > me->totloop || stop < i) {
+ invalid = TRUE;
+ }
+ else {
+ l = &me->mloop[i];
+ i = stop - i;
+ /* If one of the poly's loops is invalid, the whole poly is invalid! */
+ for (; i--; l++) {
+ if (l->e == INVALID_LOOP_EDGE_MARKER) {
+ invalid = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (p->totloop >= 3 && !invalid) {
+ if (a != b) {
+ memcpy(&me->mpoly[b], p, sizeof(me->mpoly[b]));
+ CustomData_copy_data(&me->pdata, &me->pdata, a, b, 1);
+ }
+ b++;
+ }
+ }
+ if (a != b) {
+ CustomData_free_elem(&me->pdata, b, a - b);
+ me->totpoly = b;
+ }
+
+ /* And now, get rid of invalid loops. */
+ for (a = b = 0, l = me->mloop; a < me->totloop; a++, l++) {
+ if (l->e != INVALID_LOOP_EDGE_MARKER) {
+ if (a != b) {
+ memcpy(&me->mloop[b], l, sizeof(me->mloop[b]));
+ CustomData_copy_data(&me->ldata, &me->ldata, a, b, 1);
+ }
+ new_idx[a] = b;
+ b++;
+ }
+ else {
+ /* XXX Theoretically, we should be able to not do this, as no remaining poly
+ * should use any stripped loop. But for security's sake... */
+ new_idx[a] = -a;
+ }
+ }
+ if (a != b) {
+ CustomData_free_elem(&me->ldata, b, a - b);
+ me->totloop = b;
+ }
+
+ /* And now, update polys' start loop index. */
+ /* Note: At this point, there should never be any poly using a striped loop! */
+ for (a = 0, p = me->mpoly; a < me->totpoly; a++, p++) {
+ p->loopstart = new_idx[p->loopstart];
+ }
+
+ MEM_freeN(new_idx);
+}
+
+void BKE_mesh_strip_loose_edges(Mesh *me)
+{
+ MEdge *e;
+ MLoop *l;
+ int a, b;
+ unsigned int *new_idx = MEM_mallocN(sizeof(int) * me->totedge, __func__);
+
+ for (a = b = 0, e = me->medge; a < me->totedge; a++, e++) {
+ if (e->v1 != e->v2) {
+ if (a != b) {
+ memcpy(&me->medge[b], e, sizeof(me->medge[b]));
+ CustomData_copy_data(&me->edata, &me->edata, a, b, 1);
+ }
+ new_idx[a] = b;
+ b++;
+ }
+ else {
+ new_idx[a] = INVALID_LOOP_EDGE_MARKER;
+ }
+ }
+ if (a != b) {
+ CustomData_free_elem(&me->edata, b, a - b);
+ me->totedge = b;
+ }
+
+ /* And now, update loops' edge indices. */
+ /* XXX We hope no loop was pointing to a striped edge!
+ * Else, its e will be set to INVALID_LOOP_EDGE_MARKER :/ */
+ for (a = 0, l = me->mloop; a < me->totloop; a++, l++) {
+ l->e = new_idx[l->e];
+ }
+
+ MEM_freeN(new_idx);
+}
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Edge Calculation
+ * \{ */
+
+/* make edges in a Mesh, for outside of editmode */
+
+struct EdgeSort {
+ unsigned int v1, v2;
+ char is_loose, is_draw;
+};
+
+/* edges have to be added with lowest index first for sorting */
+static void to_edgesort(struct EdgeSort *ed,
+ unsigned int v1, unsigned int v2,
+ char is_loose, short is_draw)
+{
+ if (v1 < v2) {
+ ed->v1 = v1; ed->v2 = v2;
+ }
+ else {
+ ed->v1 = v2; ed->v2 = v1;
+ }
+ ed->is_loose = is_loose;
+ ed->is_draw = is_draw;
}
-int BKE_mesh_validate_dm(DerivedMesh *dm)
+static int vergedgesort(const void *v1, const void *v2)
{
- return BKE_mesh_validate_arrays(NULL,
- dm->getVertArray(dm), dm->getNumVerts(dm),
- dm->getEdgeArray(dm), dm->getNumEdges(dm),
- dm->getTessFaceArray(dm), dm->getNumTessFaces(dm),
- dm->getLoopArray(dm), dm->getNumLoops(dm),
- dm->getPolyArray(dm), dm->getNumPolys(dm),
- dm->getVertDataArray(dm, CD_MDEFORMVERT),
- TRUE, FALSE);
+ const struct EdgeSort *x1 = v1, *x2 = v2;
+
+ if (x1->v1 > x2->v1) return 1;
+ else if (x1->v1 < x2->v1) return -1;
+ else if (x1->v2 > x2->v2) return 1;
+ else if (x1->v2 < x2->v2) return -1;
+
+ return 0;
+}
+
+
+/* Create edges based on known verts and faces,
+ * this function is only used when loading very old blend files */
+
+static void mesh_calc_edges_mdata(
+ MVert *UNUSED(allvert), MFace *allface, MLoop *allloop,
+ MPoly *allpoly, int UNUSED(totvert), int totface, int UNUSED(totloop), int totpoly,
+ const bool use_old,
+ MEdge **r_medge, int *r_totedge)
+{
+ MPoly *mpoly;
+ MFace *mface;
+ MEdge *medge, *med;
+ EdgeHash *hash;
+ struct EdgeSort *edsort, *ed;
+ int a, totedge = 0;
+ unsigned int totedge_final = 0;
+ unsigned int edge_index;
+
+ /* we put all edges in array, sort them, and detect doubles that way */
+
+ for (a = totface, mface = allface; a > 0; a--, mface++) {
+ if (mface->v4) totedge += 4;
+ else if (mface->v3) totedge += 3;
+ else totedge += 1;
+ }
+
+ if (totedge == 0) {
+ /* flag that mesh has edges */
+ (*r_medge) = MEM_callocN(0, __func__);
+ (*r_totedge) = 0;
+ return;
+ }
+
+ ed = edsort = MEM_mallocN(totedge * sizeof(struct EdgeSort), "EdgeSort");
+
+ for (a = totface, mface = allface; a > 0; a--, mface++) {
+ to_edgesort(ed++, mface->v1, mface->v2, !mface->v3, mface->edcode & ME_V1V2);
+ if (mface->v4) {
+ to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3);
+ to_edgesort(ed++, mface->v3, mface->v4, 0, mface->edcode & ME_V3V4);
+ to_edgesort(ed++, mface->v4, mface->v1, 0, mface->edcode & ME_V4V1);
+ }
+ else if (mface->v3) {
+ to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3);
+ to_edgesort(ed++, mface->v3, mface->v1, 0, mface->edcode & ME_V3V1);
+ }
+ }
+
+ qsort(edsort, totedge, sizeof(struct EdgeSort), vergedgesort);
+
+ /* count final amount */
+ for (a = totedge, ed = edsort; a > 1; a--, ed++) {
+ /* edge is unique when it differs from next edge, or is last */
+ if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) totedge_final++;
+ }
+ totedge_final++;
+
+ medge = MEM_callocN(sizeof(MEdge) * totedge_final, __func__);
+
+ for (a = totedge, med = medge, ed = edsort; a > 1; a--, ed++) {
+ /* edge is unique when it differs from next edge, or is last */
+ if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) {
+ med->v1 = ed->v1;
+ med->v2 = ed->v2;
+ if (use_old == false || ed->is_draw) med->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ if (ed->is_loose) med->flag |= ME_LOOSEEDGE;
+
+ /* order is swapped so extruding this edge as a surface wont flip face normals
+ * with cyclic curves */
+ if (ed->v1 + 1 != ed->v2) {
+ SWAP(unsigned int, med->v1, med->v2);
+ }
+ med++;
+ }
+ else {
+ /* equal edge, we merge the drawflag */
+ (ed + 1)->is_draw |= ed->is_draw;
+ }
+ }
+ /* last edge */
+ med->v1 = ed->v1;
+ med->v2 = ed->v2;
+ med->flag = ME_EDGEDRAW;
+ if (ed->is_loose) med->flag |= ME_LOOSEEDGE;
+ med->flag |= ME_EDGERENDER;
+
+ MEM_freeN(edsort);
+
+ /* set edge members of mloops */
+ hash = BLI_edgehash_new_ex(__func__, totedge_final);
+ for (edge_index = 0, med = medge; edge_index < totedge_final; edge_index++, med++) {
+ BLI_edgehash_insert(hash, med->v1, med->v2, SET_UINT_IN_POINTER(edge_index));
+ }
+
+ mpoly = allpoly;
+ for (a = 0; a < totpoly; a++, mpoly++) {
+ MLoop *ml, *ml_next;
+ int i = mpoly->totloop;
+
+ ml_next = allloop + mpoly->loopstart; /* first loop */
+ ml = &ml_next[i - 1]; /* last loop */
+
+ while (i-- != 0) {
+ ml->e = GET_UINT_FROM_POINTER(BLI_edgehash_lookup(hash, ml->v, ml_next->v));
+ ml = ml_next;
+ ml_next++;
+ }
+ }
+
+ BLI_edgehash_free(hash, NULL);
+
+ *r_medge = medge;
+ *r_totedge = totedge_final;
}
/**
+ * If the mesh is from a very old blender version,
+ * convert mface->edcode to edge drawflags
+ */
+void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old)
+{
+ MEdge *medge;
+ int totedge = 0;
+
+ mesh_calc_edges_mdata(me->mvert, me->mface, me->mloop, me->mpoly,
+ me->totvert, me->totface, me->totloop, me->totpoly,
+ use_old, &medge, &totedge);
+
+ if (totedge == 0) {
+ /* flag that mesh has edges */
+ me->medge = medge;
+ me->totedge = 0;
+ return;
+ }
+
+ medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge);
+ me->medge = medge;
+ me->totedge = totedge;
+
+ BKE_mesh_strip_loose_faces(me);
+}
+
+
+/**
* Calculate edges from polygons
*
* \param mesh The mesh to add edges into
@@ -921,7 +1362,8 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
EdgeHashIterator *ehi;
MPoly *mp;
MEdge *med, *med_orig;
- EdgeHash *eh = BLI_edgehash_new();
+ EdgeHash *eh;
+ unsigned int eh_reserve;
int i, totedge, totpoly = mesh->totpoly;
int med_index;
/* select for newly created meshes which are selected [#25595] */
@@ -930,6 +1372,9 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
if (mesh->totedge == 0)
update = false;
+ eh_reserve = max_ii(update ? mesh->totedge : 0, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly));
+ eh = BLI_edgehash_new_ex(__func__, eh_reserve);
+
if (update) {
/* assume existing edges are valid
* useful when adding more faces and generating edges from them */
@@ -999,3 +1444,4 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
BLI_edgehash_free(eh, NULL);
}
+/** \} */
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 41e0acf9f7a..4871b9bf3bf 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -69,19 +69,44 @@
#include "MOD_modifiertypes.h"
-ModifierTypeInfo *modifierType_getInfo(ModifierType type)
+static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL};
+static VirtualModifierData virtualModifierCommonData;
+
+void BKE_modifier_init(void)
{
- static ModifierTypeInfo *types[NUM_MODIFIER_TYPES] = {NULL};
- static int types_init = 1;
+ ModifierData *md;
- if (types_init) {
- modifier_type_init(types); /* MOD_utils.c */
- types_init = 0;
- }
+ /* Initialize modifier types */
+ modifier_type_init(modifier_types); /* MOD_utils.c */
+
+ /* Initialize global cmmon storage used for virtual modifier list */
+ md = modifier_new(eModifierType_Armature);
+ virtualModifierCommonData.amd = *((ArmatureModifierData *) md);
+ modifier_free(md);
+
+ md = modifier_new(eModifierType_Curve);
+ virtualModifierCommonData.cmd = *((CurveModifierData *) md);
+ modifier_free(md);
+
+ md = modifier_new(eModifierType_Lattice);
+ virtualModifierCommonData.lmd = *((LatticeModifierData *) md);
+ modifier_free(md);
+ md = modifier_new(eModifierType_ShapeKey);
+ virtualModifierCommonData.smd = *((ShapeKeyModifierData *) md);
+ modifier_free(md);
+
+ virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual;
+ virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual;
+ virtualModifierCommonData.lmd.modifier.mode |= eModifierMode_Virtual;
+ virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual;
+}
+
+ModifierTypeInfo *modifierType_getInfo(ModifierType type)
+{
/* type unsigned, no need to check < 0 */
- if (type < NUM_MODIFIER_TYPES && types[type]->name[0] != '\0') {
- return types[type];
+ if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') {
+ return modifier_types[type];
}
else {
return NULL;
@@ -289,7 +314,8 @@ void modifier_setError(ModifierData *md, const char *_format, ...)
*/
int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *lastPossibleCageIndex_r, int virtual_)
{
- ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob) : ob->modifiers.first;
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : ob->modifiers.first;
int i, cageIndex = -1;
if (lastPossibleCageIndex_r) {
@@ -435,74 +461,43 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in
/* NOTE: This is to support old files from before Blender supported modifiers,
* in some cases versioning code updates these so for new files this will
* return an empty list. */
-ModifierData *modifiers_getVirtualModifierList(Object *ob)
+ModifierData *modifiers_getVirtualModifierList(Object *ob, VirtualModifierData *virtualModifierData)
{
- /* Kinda hacky, but should be fine since we are never
- * re-entrant and avoid free hassles.
- */
- static ArmatureModifierData amd;
- static CurveModifierData cmd;
- static LatticeModifierData lmd;
- static ShapeKeyModifierData smd;
- static int init = 1;
ModifierData *md;
- if (init) {
- md = modifier_new(eModifierType_Armature);
- amd = *((ArmatureModifierData *) md);
- modifier_free(md);
-
- md = modifier_new(eModifierType_Curve);
- cmd = *((CurveModifierData *) md);
- modifier_free(md);
-
- md = modifier_new(eModifierType_Lattice);
- lmd = *((LatticeModifierData *) md);
- modifier_free(md);
-
- md = modifier_new(eModifierType_ShapeKey);
- smd = *((ShapeKeyModifierData *) md);
- modifier_free(md);
-
- amd.modifier.mode |= eModifierMode_Virtual;
- cmd.modifier.mode |= eModifierMode_Virtual;
- lmd.modifier.mode |= eModifierMode_Virtual;
- smd.modifier.mode |= eModifierMode_Virtual;
-
- init = 0;
- }
-
md = ob->modifiers.first;
+ *virtualModifierData = virtualModifierCommonData;
+
if (ob->parent) {
if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
- amd.object = ob->parent;
- amd.modifier.next = md;
- amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
- md = &amd.modifier;
+ virtualModifierData->amd.object = ob->parent;
+ virtualModifierData->amd.modifier.next = md;
+ virtualModifierData->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
+ md = &virtualModifierData->amd.modifier;
}
else if (ob->parent->type == OB_CURVE && ob->partype == PARSKEL) {
- cmd.object = ob->parent;
- cmd.defaxis = ob->trackflag + 1;
- cmd.modifier.next = md;
- md = &cmd.modifier;
+ virtualModifierData->cmd.object = ob->parent;
+ virtualModifierData->cmd.defaxis = ob->trackflag + 1;
+ virtualModifierData->cmd.modifier.next = md;
+ md = &virtualModifierData->cmd.modifier;
}
else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
- lmd.object = ob->parent;
- lmd.modifier.next = md;
- md = &lmd.modifier;
+ virtualModifierData->lmd.object = ob->parent;
+ virtualModifierData->lmd.modifier.next = md;
+ md = &virtualModifierData->lmd.modifier;
}
}
/* shape key modifier, not yet for curves */
if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) {
if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
- smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
+ virtualModifierData->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
else
- smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
+ virtualModifierData->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
- smd.modifier.next = md;
- md = &smd.modifier;
+ virtualModifierData->smd.modifier.next = md;
+ md = &virtualModifierData->smd.modifier;
}
return md;
@@ -513,7 +508,8 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
*/
Object *modifiers_isDeformedByArmature(Object *ob)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
ArmatureModifierData *amd = NULL;
/* return the first selected armature, this lets us use multiple armatures */
@@ -536,7 +532,8 @@ Object *modifiers_isDeformedByArmature(Object *ob)
*/
Object *modifiers_isDeformedByLattice(Object *ob)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
LatticeModifierData *lmd = NULL;
/* return the first selected lattice, this lets us use multiple lattices */
@@ -559,7 +556,8 @@ Object *modifiers_isDeformedByLattice(Object *ob)
*/
Object *modifiers_isDeformedByCurve(Object *ob)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
CurveModifierData *cmd = NULL;
/* return the first selected curve, this lets us use multiple curves */
@@ -579,7 +577,8 @@ Object *modifiers_isDeformedByCurve(Object *ob)
bool modifiers_usesArmature(Object *ob, bArmature *arm)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
for (; md; md = md->next) {
if (md->type == eModifierType_Armature) {
@@ -594,20 +593,21 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm)
bool modifier_isCorrectableDeformed(ModifierData *md)
{
- if (md->type == eModifierType_Armature)
- return true;
- if (md->type == eModifierType_ShapeKey)
- return true;
-
- return false;
+ ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ return (mti->deformMatricesEM != NULL);
}
-bool modifiers_isCorrectableDeformed(Object *ob)
+bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob)
{
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ int required_mode = eModifierMode_Realtime;
+
+ if (ob->mode == OB_MODE_EDIT)
+ required_mode |= eModifierMode_Editmode;
for (; md; md = md->next) {
- if (ob->mode == OB_MODE_EDIT && (md->mode & eModifierMode_Editmode) == 0) {
+ if (!modifier_isEnabled(scene, md, required_mode)) {
/* pass */
}
else if (modifier_isCorrectableDeformed(md)) {
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 290b0684e40..a9ff569e70a 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -52,7 +52,7 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
edges[j] = etable[ml->e];
}
- return BM_face_create(bm, verts, edges, mp->totloop, BM_CREATE_SKIP_CD);
+ return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD);
}
/**
@@ -232,8 +232,9 @@ BMEditMesh *DM_to_editbmesh(DerivedMesh *dm, BMEditMesh *existing, const bool do
BMesh *DM_to_bmesh(DerivedMesh *dm, const bool calc_face_normal)
{
BMesh *bm;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_DM(dm);
- bm = BM_mesh_create(&bm_mesh_allocsize_default);
+ bm = BM_mesh_create(&allocsize);
DM_to_bmesh_ex(dm, bm, calc_face_normal);
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index bf4a63c52a8..d9630a7343d 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -62,7 +62,6 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
-#include "BLI_mempool.h"
#include "BLI_threads.h"
#include "BKE_animsys.h"
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 32ca3ea6d5a..0cdcf4e7298 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -114,8 +114,8 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden,
BLI_bitmap *prev_hidden)
{
BLI_bitmap *subd;
- int hi_gridsize = ccg_gridsize(hi_level);
- int lo_gridsize = ccg_gridsize(lo_level);
+ int hi_gridsize = BKE_ccg_gridsize(hi_level);
+ int lo_gridsize = BKE_ccg_gridsize(lo_level);
int yh, xh, xl, yl, xo, yo, hi_ndx;
int offset, factor;
@@ -127,7 +127,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden,
subd = BLI_BITMAP_NEW(hi_gridsize * hi_gridsize, "MDisps.hidden upsample");
- factor = ccg_factor(lo_level, hi_level);
+ factor = BKE_ccg_factor(lo_level, hi_level);
offset = 1 << (hi_level - lo_level - 1);
/* low-res blocks */
@@ -173,12 +173,12 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden,
int new_level)
{
BLI_bitmap *new_hidden;
- int new_gridsize = ccg_gridsize(new_level);
- int old_gridsize = ccg_gridsize(old_level);
+ int new_gridsize = BKE_ccg_gridsize(new_level);
+ int old_gridsize = BKE_ccg_gridsize(old_level);
int x, y, factor, old_value;
BLI_assert(new_level <= old_level);
- factor = ccg_factor(new_level, old_level);
+ factor = BKE_ccg_factor(new_level, old_level);
new_hidden = BLI_BITMAP_NEW(new_gridsize * new_gridsize,
"downsample hidden");
@@ -246,7 +246,7 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level)
{
MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS,
CD_CALLOC, NULL, me->totloop);
- int gridsize = ccg_gridsize(level);
+ int gridsize = BKE_ccg_gridsize(level);
int gridarea = gridsize * gridsize;
int i, j, k;
@@ -594,7 +594,7 @@ static void multires_copy_dm_grid(CCGElem *gridA, CCGElem *gridB, CCGKey *keyA,
static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level)
{
if (level < gpm->level) {
- int gridsize = ccg_gridsize(level);
+ int gridsize = BKE_ccg_gridsize(level);
float *data = MEM_callocN(sizeof(float) * gridsize * gridsize,
"multires_grid_paint_mask_downsample");
int x, y;
@@ -1645,6 +1645,11 @@ void multires_free(Multires *mr)
}
}
+typedef struct IndexNode {
+ struct IndexNode *next, *prev;
+ int index;
+} IndexNode;
+
static void create_old_vert_face_map(ListBase **map, IndexNode **mem, const MultiresFace *mface,
const int totvert, const int totface)
{
diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c
index 1d662ae3116..3c499908bf7 100644
--- a/source/blender/blenkernel/intern/navmesh_conversion.c
+++ b/source/blender/blenkernel/intern/navmesh_conversion.c
@@ -38,6 +38,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_sort.h"
#include "BKE_navmesh_conversion.h"
#include "BKE_cdderivedmesh.h"
@@ -340,7 +341,7 @@ int buildNavMeshData(const int nverts, const float *verts,
trisMapping[i] = i;
context.recastData = recastData;
context.trisToFacesMap = trisToFacesMap;
- recast_qsort(trisMapping, ntris, sizeof(int), &context, compareByData);
+ BLI_qsort_r(trisMapping, ntris, sizeof(int), &context, compareByData);
/* search first valid triangle - triangle of convex polygon */
validTriStart = -1;
@@ -366,7 +367,7 @@ int buildNavMeshData(const int nverts, const float *verts,
/* create detailed mesh triangles - copy only valid triangles
* and reserve memory for adjacency info */
dtris = MEM_callocN(sizeof(unsigned short) * 3 * 2 * ndtris, "buildNavMeshData dtris");
- memset(dtris, 0xffff, sizeof(unsigned short) * 3 * 2 * ndtris);
+ memset(dtris, 0xff, sizeof(unsigned short) * 3 * 2 * ndtris);
for (i = 0; i < ndtris; i++) {
memcpy(dtris + 3 * 2 * i, tris + 3 * dtrisToTrisMap[i], sizeof(unsigned short) * 3);
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 5001aa01653..c0df306a3fa 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1107,7 +1107,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
* copying for internal use (threads for eg), where you wont want it to modify the
* scene data.
*/
-static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern, const short copy_previews)
+static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_id_user, bool do_make_extern, bool copy_previews)
{
bNodeTree *newtree;
bNode *node /*, *nnode */ /* UNUSED */, *last;
@@ -1116,13 +1116,17 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
if (ntree == NULL) return NULL;
- /* is ntree part of library? */
- for (newtree = G.main->nodetree.first; newtree; newtree = newtree->id.next)
- if (newtree == ntree) break;
- if (newtree) {
- newtree = BKE_libblock_copy(&ntree->id);
+ if (bmain) {
+ /* is ntree part of library? */
+ if (BLI_findindex(&bmain->nodetree, ntree) != -1)
+ newtree = BKE_libblock_copy(&ntree->id);
+ else
+ newtree = NULL;
}
- else {
+ else
+ newtree = NULL;
+
+ if (newtree == NULL) {
newtree = MEM_dupallocN(ntree);
newtree->id.lib = NULL; /* same as owning datablock id.lib */
BKE_libblock_copy_data(&newtree->id, &ntree->id, true); /* copy animdata and ID props */
@@ -1208,7 +1212,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user)
{
- return ntreeCopyTree_internal(ntree, do_id_user, TRUE, TRUE);
+ return ntreeCopyTree_internal(ntree, G.main, do_id_user, TRUE, TRUE);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
@@ -1590,6 +1594,8 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock, *nextsock;
+ char propname_esc[MAX_IDPROP_NAME * 2];
+ char prefix[MAX_IDPROP_NAME * 2];
/* extra free callback */
if (node->typeinfo && node->typeinfo->freefunc_api) {
@@ -1609,6 +1615,11 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
BLI_remlink(&ntree->nodes, node);
+ BLI_strescape(propname_esc, node->name, sizeof(propname_esc));
+ BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc);
+
+ BKE_animdata_fix_paths_remove((ID *)ntree, prefix);
+
if (ntree->typeinfo && ntree->typeinfo->free_node_cache)
ntree->typeinfo->free_node_cache(ntree, node);
@@ -1657,6 +1668,22 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *so
MEM_freeN(sock->default_value);
}
+static void free_localized_node_groups(bNodeTree *ntree)
+{
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP && node->id) {
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (BLI_findindex(&G.main->nodetree, ngroup) == -1) {
+ /* ntree is not in library, i.e. localized node group: free it */
+ ntreeFreeTree_ex(ngroup, false);
+ MEM_freeN(ngroup);
+ }
+ }
+ }
+}
+
/* do not free ntree itself here, BKE_libblock_free calls this function too */
void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
{
@@ -1683,6 +1710,9 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
}
}
+ /* XXX not nice, but needed to free localized node groups properly */
+ free_localized_node_groups(ntree);
+
/* unregister associated RNA types */
ntreeInterfaceTypeFree(ntree);
@@ -1932,8 +1962,14 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
/* Make full copy.
* Note: previews are not copied here.
*/
- ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE, FALSE);
-
+ ltree = ntreeCopyTree_internal(ntree, NULL, FALSE, FALSE, FALSE);
+
+ for (node = ltree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP && node->id) {
+ node->id = (ID *)ntreeLocalize((bNodeTree *)node->id);
+ }
+ }
+
if (adt) {
AnimData *ladt = BKE_animdata_from_id(&ltree->id);
@@ -1978,7 +2014,7 @@ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
/* we have to assume the editor already changed completely */
void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
{
- if (localtree && ntree) {
+ if (ntree && localtree) {
if (ntree->typeinfo->local_merge)
ntree->typeinfo->local_merge(localtree, ntree);
@@ -2285,7 +2321,7 @@ bNode *nodeGetActive(bNodeTree *ntree)
static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key, bNodeInstanceKey parent_key, bNodeTree *ntree, short idtype)
{
- if (parent_key.value == active_key.value) {
+ if (parent_key.value == active_key.value || active_key.value == 0) {
bNode *node;
for (node = ntree->nodes.first; node; node = node->next)
if (node->id && GS(node->id->name) == idtype)
@@ -2666,7 +2702,7 @@ void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP
void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key)
{
- return BLI_ghash_pop(hash->ghash, &key, NULL);
+ return BLI_ghash_popkey(hash->ghash, &key, NULL);
}
int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
@@ -3391,6 +3427,7 @@ static void registerCompositNodes(void)
register_node_type_cmp_mask();
register_node_type_cmp_trackpos();
+ register_node_type_cmp_planetrackdeform();
}
static void registerShaderNodes(void)
@@ -3448,6 +3485,7 @@ static void registerShaderNodes(void)
register_node_type_sh_bsdf_transparent();
register_node_type_sh_bsdf_velvet();
register_node_type_sh_bsdf_toon();
+ register_node_type_sh_bsdf_hair();
register_node_type_sh_emission();
register_node_type_sh_holdout();
//register_node_type_sh_volume_transparent();
@@ -3573,11 +3611,13 @@ void free_nodesystem(void)
}
if (nodetreetypes_hash) {
- NODE_TREE_TYPES_BEGIN(nt)
+ NODE_TREE_TYPES_BEGIN (nt)
+ {
if (nt->ext.free) {
nt->ext.free(nt->ext.data);
}
- NODE_TREE_TYPES_END
+ }
+ NODE_TREE_TYPES_END;
BLI_ghash_free(nodetreetypes_hash, NULL, ntree_free_type);
nodetreetypes_hash = NULL;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 962209bef87..8c2475369de 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -64,6 +64,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
+#include "BLI_kdtree.h"
#include "BLF_translation.h"
@@ -142,11 +143,9 @@ void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
void BKE_object_free_particlesystems(Object *ob)
{
- while (ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- BLI_remlink(&ob->particlesystem, psys);
-
+ ParticleSystem *psys;
+
+ while ((psys = BLI_pophead(&ob->particlesystem))) {
psys_free(ob, psys);
}
}
@@ -167,13 +166,24 @@ void BKE_object_free_bulletsoftbody(Object *ob)
}
}
+void BKE_object_free_curve_cache(Object *ob)
+{
+ if (ob->curve_cache) {
+ BKE_displist_free(&ob->curve_cache->disp);
+ BLI_freelistN(&ob->curve_cache->bev);
+ if (ob->curve_cache->path) {
+ free_path(ob->curve_cache->path);
+ }
+ MEM_freeN(ob->curve_cache);
+ ob->curve_cache = NULL;
+ }
+}
+
void BKE_object_free_modifiers(Object *ob)
{
- while (ob->modifiers.first) {
- ModifierData *md = ob->modifiers.first;
-
- BLI_remlink(&ob->modifiers, md);
-
+ ModifierData *md;
+
+ while ((md = BLI_pophead(&ob->modifiers))) {
modifier_free(md);
}
@@ -246,8 +256,14 @@ void BKE_object_free_derived_caches(Object *ob)
Mesh *me = ob->data;
if (me->bb) {
- MEM_freeN(me->bb);
- me->bb = NULL;
+ me->bb->flag |= BOUNDBOX_DIRTY;
+ }
+ }
+ else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ Curve *cu = ob->data;
+
+ if (cu->bb) {
+ cu->bb->flag |= BOUNDBOX_DIRTY;
}
}
@@ -267,7 +283,9 @@ void BKE_object_free_derived_caches(Object *ob)
ob->derivedDeform = NULL;
}
- BKE_displist_free(&ob->disp);
+ if (ob->curve_cache) {
+ BKE_displist_free(&ob->curve_cache->disp);
+ }
}
/* do not free object itself */
@@ -337,6 +355,14 @@ void BKE_object_free(Object *ob)
free_sculptsession(ob);
if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids);
+
+ /* Free runtime curves data. */
+ if (ob->curve_cache) {
+ BLI_freelistN(&ob->curve_cache->bev);
+ if (ob->curve_cache->path)
+ free_path(ob->curve_cache->path);
+ MEM_freeN(ob->curve_cache);
+ }
}
static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -617,7 +643,9 @@ void BKE_object_unlink(Object *ob)
for (lineset = (FreestyleLineSet *)srl->freestyleConfig.linesets.first;
lineset; lineset = lineset->next)
{
- BKE_unlink_linestyle_target_object(lineset->linestyle, ob);
+ if (lineset->linestyle) {
+ BKE_unlink_linestyle_target_object(lineset->linestyle, ob);
+ }
}
}
}
@@ -1256,8 +1284,6 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
- obn->disp.first = obn->disp.last = NULL;
-
if (ob->pd) {
obn->pd = MEM_dupallocN(ob->pd);
if (obn->pd->tex)
@@ -1279,7 +1305,10 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
obn->pc_ids.first = obn->pc_ids.last = NULL;
obn->mpath = NULL;
-
+
+ /* Copy runtime surve data. */
+ obn->curve_cache = NULL;
+
return obn;
}
@@ -1772,9 +1801,9 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
unit_m4(mat);
cu = par->data;
- if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+ if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
BKE_displist_make_curveTypes(scene, par, 0);
- if (cu->path == NULL) return;
+ if (par->curve_cache->path == NULL) return;
/* catch exceptions: feature for nla stride editing */
if (ob->ipoflag & OB_DISABLE_PATH) {
@@ -1805,7 +1834,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
/* time calculus is correct, now apply distance offset */
if (cu->flag & CU_OFFS_PATHDIST) {
- ctime += timeoffs / cu->path->totdist;
+ ctime += timeoffs / par->curve_cache->path->totdist;
/* restore */
SWAP(float, sf_orig, ob->sf);
@@ -1962,7 +1991,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
}
else if (par->type == OB_LATTICE) {
Lattice *latt = par->data;
- DispList *dl = BKE_displist_find(&par->disp, DL_VERTS);
+ DispList *dl = par->curve_cache ? BKE_displist_find(&par->curve_cache->disp, DL_VERTS) : NULL;
float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL;
int tot;
@@ -1986,29 +2015,23 @@ static void give_parvert(Object *par, int nr, float vec[3])
static void ob_parvert3(Object *ob, Object *par, float mat[4][4])
{
- float cmat[3][3], v1[3], v2[3], v3[3], q[4];
/* in local ob space */
- unit_m4(mat);
-
- if (ELEM4(par->type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE)) {
-
+ if (OB_TYPE_SUPPORT_PARVERT(par->type)) {
+ float cmat[3][3], v1[3], v2[3], v3[3], q[4];
+
give_parvert(par, ob->par1, v1);
give_parvert(par, ob->par2, v2);
give_parvert(par, ob->par3, v3);
-
+
tri_to_quat(q, v1, v2, v3);
quat_to_mat3(cmat, q);
copy_m4_m3(mat, cmat);
-
- if (ob->type == OB_CURVE) {
- copy_v3_v3(mat[3], v1);
- }
- else {
- add_v3_v3v3(mat[3], v1, v2);
- add_v3_v3(mat[3], v3);
- mul_v3_fl(mat[3], 1.0f / 3.0f);
- }
+
+ mid_v3_v3v3v3(mat[3], v1, v2, v3);
+ }
+ else {
+ unit_m4(mat);
}
}
@@ -2291,7 +2314,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
bb = BKE_mesh_boundbox_get(ob);
}
else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- bb = ob->bb ? ob->bb : ((Curve *)ob->data)->bb;
+ bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
bb = ob->bb;
@@ -2360,18 +2383,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
case OB_FONT:
case OB_SURF:
{
- Curve *cu = ob->data;
-
- /* Use the object bounding box so that modifier output
- * gets taken into account */
- if (ob->bb) {
- bb = *(ob->bb);
- }
- else {
- if (cu->bb == NULL)
- BKE_curve_texspace_calc(cu);
- bb = *(cu->bb);
- }
+ bb = *BKE_curve_boundbox_get(ob);
for (a = 0; a < 8; a++) {
mul_m4_v3(ob->obmat, bb.vec[a]);
@@ -2519,10 +2531,10 @@ void BKE_object_foreach_display_point(
func_cb(co, user_data);
}
}
- else if (ob->disp.first) {
+ else if (ob->curve_cache && ob->curve_cache->disp.first) {
DispList *dl;
- for (dl = ob->disp.first; dl; dl = dl->next) {
+ for (dl = ob->curve_cache->disp.first; dl; dl = dl->next) {
float *v3 = dl->verts;
int totvert = dl->nr;
int i;
@@ -2825,21 +2837,20 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
/* quick cache removed */
}
- /* the no-group proxy case, we call update */
- if (ob->proxy && ob->proxy_group == NULL) {
- /* set pointer in library proxy target, for copying, but restore it */
- ob->proxy->proxy_from = ob;
- // printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name);
- BKE_object_handle_update(scene, ob->proxy);
- }
-
ob->recalc &= ~OB_RECALC_ALL;
}
/* the case when this is a group proxy, object_update is called in group.c */
if (ob->proxy) {
+ /* set pointer in library proxy target, for copying, but restore it */
ob->proxy->proxy_from = ob;
// printf("set proxy pointer for later group stuff %s\n", ob->id.name);
+
+ /* the no-group proxy case, we call update */
+ if (ob->proxy_group == NULL) {
+ // printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name);
+ BKE_object_handle_update(scene, ob->proxy);
+ }
}
}
/* WARNING: "scene" here may not be the scene object actually resides in.
@@ -3158,8 +3169,9 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
}
else {
ModifierData *md;
+ VirtualModifierData virtualModifierData;
/* cloth */
- for (md = modifiers_getVirtualModifierList(ob);
+ for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
md = md->next)
{
@@ -3180,10 +3192,11 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
int BKE_object_is_deform_modified(Scene *scene, Object *ob)
{
ModifierData *md;
+ VirtualModifierData virtualModifierData;
int flag = 0;
/* cloth */
- for (md = modifiers_getVirtualModifierList(ob);
+ for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
md = md->next)
{
@@ -3205,8 +3218,9 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
bool BKE_object_is_animated(Scene *scene, Object *ob)
{
ModifierData *md;
+ VirtualModifierData virtualModifierData;
- for (md = modifiers_getVirtualModifierList(ob); md; md = md->next)
+ for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next)
if (modifier_dependsOnTime(md) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime) ||
modifier_isEnabled(scene, md, eModifierMode_Render)))
@@ -3248,7 +3262,7 @@ void BKE_object_relink(Object *ob)
ID_NEW(ob->proxy_group);
}
-MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, int use_default)
+MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default)
{
MovieClip *clip = use_default ? scene->clip : NULL;
bConstraint *con = ob->constraints.first, *scon = NULL;
@@ -3422,3 +3436,131 @@ void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
BKE_group_object_unlink(group, object, scene, base);
}
}
+
+/**
+ * Return a KDTree from the deformed object (in worldspace)
+ *
+ * \note Only mesh objects currently support deforming, others are TODO.
+ *
+ * \param ob
+ * \param r_tot
+ * \return The kdtree or NULL if it can't be created.
+ */
+KDTree *BKE_object_as_kdtree(Object *ob, int *r_tot)
+{
+ KDTree *tree = NULL;
+ unsigned int tot = 0;
+
+ switch (ob->type) {
+ case OB_MESH:
+ {
+ Mesh *me = ob->data;
+ unsigned int i;
+
+ DerivedMesh *dm = ob->derivedDeform ? ob->derivedDeform : ob->derivedFinal;
+ int *index;
+
+ if (dm && (index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))) {
+ MVert *mvert = dm->getVertArray(dm);
+ unsigned int totvert = dm->getNumVerts(dm);
+
+ /* tree over-allocs in case where some verts have ORIGINDEX_NONE */
+ tot = 0;
+ tree = BLI_kdtree_new(totvert);
+
+ /* we don't how how many verts from the DM we can use */
+ for (i = 0; i < totvert; i++) {
+ if (index[i] != ORIGINDEX_NONE) {
+ float co[3];
+ mul_v3_m4v3(co, ob->obmat, mvert[i].co);
+ BLI_kdtree_insert(tree, index[i], co, NULL);
+ tot++;
+ }
+ }
+ }
+ else {
+ MVert *mvert = me->mvert;
+
+ tot = me->totvert;
+ tree = BLI_kdtree_new(tot);
+
+ for (i = 0; i < tot; i++) {
+ float co[3];
+ mul_v3_m4v3(co, ob->obmat, mvert[i].co);
+ BLI_kdtree_insert(tree, i, co, NULL);
+ }
+ }
+
+ BLI_kdtree_balance(tree);
+ break;
+ }
+ case OB_CURVE:
+ case OB_SURF:
+ {
+ /* TODO: take deformation into account */
+ Curve *cu = ob->data;
+ unsigned int i, a;
+
+ Nurb *nu;
+
+ tot = BKE_nurbList_verts_count_without_handles(&cu->nurb);
+ tree = BLI_kdtree_new(tot);
+ i = 0;
+
+ nu = cu->nurb.first;
+ while (nu) {
+ if (nu->bezt) {
+ BezTriple *bezt;
+
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ float co[3];
+ mul_v3_m4v3(co, ob->obmat, bezt->vec[1]);
+ BLI_kdtree_insert(tree, i++, co, NULL);
+ bezt++;
+ }
+ }
+ else {
+ BPoint *bp;
+
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ float co[3];
+ mul_v3_m4v3(co, ob->obmat, bp->vec);
+ BLI_kdtree_insert(tree, i++, co, NULL);
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+
+ BLI_kdtree_balance(tree);
+ break;
+ }
+ case OB_LATTICE:
+ {
+ /* TODO: take deformation into account */
+ Lattice *lt = ob->data;
+ BPoint *bp;
+ unsigned int i;
+
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ tree = BLI_kdtree_new(tot);
+ i = 0;
+
+ for (bp = lt->def; i < tot; bp++) {
+ float co[3];
+ mul_v3_m4v3(co, ob->obmat, bp->vec);
+ BLI_kdtree_insert(tree, i++, co, NULL);
+ }
+
+ BLI_kdtree_balance(tree);
+ break;
+ }
+ }
+
+ *r_tot = tot;
+ return tree;
+}
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index bfec38419f1..77c5e57f382 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -73,12 +73,13 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
GHash *gh;
int i, step1 = 1;
//int defbase_tot = BLI_countlist(&ob->defbase);
+ VirtualModifierData virtualModifierData;
if (ob->defbase.first == NULL) {
return NULL;
}
- gh = BLI_ghash_str_new("BKE_objdef_validmap_get gh");
+ gh = BLI_ghash_str_new_ex("BKE_objdef_validmap_get gh", defbase_tot);
/* add all names to a hash table */
for (dg = ob->defbase.first; dg; dg = dg->next) {
@@ -88,7 +89,7 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
BLI_assert(BLI_ghash_size(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) : md->next) {
+ for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) {
if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual)))
continue;
@@ -100,11 +101,13 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
bPoseChannel *chan;
for (chan = pose->chanbase.first; chan; chan = chan->next) {
+ void **val_p;
if (chan->bone->flag & BONE_NO_DEFORM)
continue;
- if (BLI_ghash_remove(gh, chan->name, NULL, NULL)) {
- BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1));
+ val_p = BLI_ghash_lookup_p(gh, chan->name);
+ if (val_p) {
+ *val_p = SET_INT_IN_POINTER(1);
}
}
}
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 21a69910b4d..c1e43365a84 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -25,6 +25,9 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenkernel/intern/ocean.c
+ * \ingroup bke
+ */
#include <math.h>
#include <stdlib.h>
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 62ea16b9fb4..5c2789a2c1c 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -219,6 +219,9 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
if (read(file, data, filelen) == filelen) {
pf = newPackedFileMemory(data, filelen);
}
+ else {
+ MEM_freeN(data);
+ }
close(file);
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index b47a493581e..6bdfb22dc1a 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -359,8 +359,8 @@ int paint_is_bmesh_face_hidden(BMFace *f)
float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y)
{
- int factor = ccg_factor(level, gpm->level);
- int gridsize = ccg_gridsize(gpm->level);
+ int factor = BKE_ccg_factor(level, gpm->level);
+ int gridsize = BKE_ccg_gridsize(gpm->level);
return gpm->data[(y * factor) * gridsize + (x * factor)];
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 6b754743c11..24cf98d957d 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -221,12 +221,12 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys)
}
#endif
-Object *psys_get_lattice(ParticleSimulationData *sim)
+struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim)
{
- Object *lattice = NULL;
-
- if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
+ struct LatticeDeformData *lattice_deform_data = NULL;
+ if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
+ Object *lattice = NULL;
ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
for (; md; md = md->next) {
@@ -237,10 +237,10 @@ Object *psys_get_lattice(ParticleSimulationData *sim)
}
}
if (lattice)
- init_latt_deform(lattice, NULL);
+ lattice_deform_data = init_latt_deform(lattice, NULL);
}
- return lattice;
+ return lattice_deform_data;
}
void psys_disable_all(Object *ob)
{
@@ -1729,7 +1729,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_
return 0;
if (dm->deformedOnly || index_dmcache == DMCACHE_ISCHILD) {
- /* for meshes that are either only defined or for child particles, the
+ /* for meshes that are either only deformed or for child particles, the
* index and fw do not require any mapping, so we can directly use it */
if (from == PART_FROM_VERT) {
if (index >= dm->getNumVerts(dm))
@@ -1817,8 +1817,8 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
copy_v3_v3(orco, orcodata[mapindex]);
if (ornor) {
- dm->getVertNo(dm, mapindex, nor);
- normalize_v3(nor);
+ dm->getVertNo(dm, mapindex, ornor);
+ normalize_v3(ornor);
}
if (utan && vtan) {
@@ -1843,7 +1843,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache
if (nor)
copy_v3_v3(nor, tmpnor);
- normalize_v3(tmpnor);
+ normalize_v3(tmpnor); /* XXX Why not normalize tmpnor before copying it into nor??? -- mont29 */
mul_v3_fl(tmpnor, -foffset);
add_v3_v3(vec, tmpnor);
}
@@ -2513,7 +2513,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
ctx->cfra = cfra;
ctx->editupdate = editupdate;
- psys->lattice = psys_get_lattice(&ctx->sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim);
/* cache all relevant vertex groups if they exist */
ctx->vg_length = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_LENGTH);
@@ -2974,7 +2974,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
psys_free_path_cache(psys, psys->edit);
cache = psys->pathcache = psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps + 1);
- psys->lattice = psys_get_lattice(sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
ma = give_current_material(sim->ob, psys->part->omat);
if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT))
copy_v3_v3(col, &ma->r);
@@ -3079,9 +3079,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
}
/* lattices have to be calculated separately to avoid mixups between effector calculations */
- if (psys->lattice) {
+ if (psys->lattice_deform_data) {
for (k = 0, ca = cache[p]; k <= steps; k++, ca++)
- calc_latt_deform(psys->lattice, ca->co, 1.0f);
+ calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f);
}
}
@@ -3112,9 +3112,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
psys->totcached = totpart;
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice = NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
if (vg_effector)
@@ -4166,8 +4166,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
/* TODO: proper velocity handling */
}
- if (psys->lattice && edit == 0)
- calc_latt_deform(psys->lattice, state->co, 1.0f);
+ if (psys->lattice_deform_data && edit == 0)
+ calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
}
}
}
@@ -4402,8 +4402,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
unit_m4(mat);
do_child_modifiers(sim, NULL, key1, key1->rot, cpa, cpa->fuv, mat, state, t);
- if (psys->lattice)
- calc_latt_deform(sim->psys->lattice, state->co, 1.0f);
+ if (psys->lattice_deform_data)
+ calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
}
else {
if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
@@ -4461,8 +4461,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
}
- if (sim->psys->lattice)
- calc_latt_deform(sim->psys->lattice, state->co, 1.0f);
+ if (sim->psys->lattice_deform_data)
+ calc_latt_deform(sim->psys->lattice_deform_data, state->co, 1.0f);
}
return 1;
@@ -4678,9 +4678,9 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
sim.psys = psys;
sim.psmd = psys_get_modifier(ob, psys);
- psys->lattice = psys_get_lattice(&sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
- if (psys->lattice) {
+ if (psys->lattice_deform_data) {
ParticleData *pa = psys->particles;
HairKey *hkey;
int p, h;
@@ -4693,13 +4693,13 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
hkey = pa->hair;
for (h = 0; h < pa->totkey; h++, hkey++) {
mul_m4_v3(hairmat, hkey->co);
- calc_latt_deform(psys->lattice, hkey->co, 1.0f);
+ calc_latt_deform(psys->lattice_deform_data, hkey->co, 1.0f);
mul_m4_v3(imat, hkey->co);
}
}
- end_latt_deform(psys->lattice);
- psys->lattice = NULL;
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
/* protect the applied shape */
psys->flag |= PSYS_EDITED;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 16ea71204cc..526d54a97fa 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -70,6 +70,7 @@
#include "BLI_blenlib.h"
#include "BLI_kdtree.h"
#include "BLI_kdopbvh.h"
+#include "BLI_sort.h"
#include "BLI_threads.h"
#include "BLI_linklist.h"
@@ -814,7 +815,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0);
BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_n_nearest(ctx->tree,3,orco1,NULL,ptn);
+ maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,NULL,ptn,3);
for (w=0; w<maxw; w++) {
pa->verts[w]=ptn->num;
@@ -939,7 +940,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL);
BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,NULL,ptn);
+ maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,NULL,ptn,3);
maxd=ptn[maxw-1].dist;
/* mind=ptn[0].dist; */ /* UNUSED */
@@ -1010,12 +1011,11 @@ static void *distribute_threads_exec_cb(void *data)
return 0;
}
-/* not thread safe, but qsort doesn't take userdata argument */
-static int *COMPARE_ORIG_INDEX = NULL;
-static int distribute_compare_orig_index(const void *p1, const void *p2)
+static int distribute_compare_orig_index(void *user_data, const void *p1, const void *p2)
{
- int index1 = COMPARE_ORIG_INDEX[*(const int *)p1];
- int index2 = COMPARE_ORIG_INDEX[*(const int *)p2];
+ int *orig_index = (int *) user_data;
+ int index1 = orig_index[*(const int *)p1];
+ int index2 = orig_index[*(const int *)p2];
if (index1 < index2)
return -1;
@@ -1332,20 +1332,19 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
/* For hair, sort by origindex (allows optimization's in rendering), */
/* however with virtual parents the children need to be in random order. */
if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) {
- COMPARE_ORIG_INDEX = NULL;
+ int *orig_index = NULL;
if (from == PART_FROM_VERT) {
if (dm->numVertData)
- COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX);
+ orig_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
}
else {
if (dm->numTessFaceData)
- COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ orig_index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
}
- if (COMPARE_ORIG_INDEX) {
- qsort(particle_element, totpart, sizeof(int), distribute_compare_orig_index);
- COMPARE_ORIG_INDEX = NULL;
+ if (orig_index) {
+ BLI_qsort_r(particle_element, totpart, sizeof(int), orig_index, distribute_compare_orig_index);
}
}
@@ -1514,9 +1513,9 @@ void psys_threads_free(ParticleThread *threads)
if (ctx->vg_roughe)
MEM_freeN(ctx->vg_roughe);
- if (ctx->sim.psys->lattice) {
- end_latt_deform(ctx->sim.psys->lattice);
- ctx->sim.psys->lattice= NULL;
+ if (ctx->sim.psys->lattice_deform_data) {
+ end_latt_deform(ctx->sim.psys->lattice_deform_data);
+ ctx->sim.psys->lattice_deform_data = NULL;
}
/* distribution */
@@ -2485,7 +2484,7 @@ static EdgeHash *sph_springhash_build(ParticleSystem *psys)
ParticleSpring *spring;
int i = 0;
- springhash = BLI_edgehash_new();
+ springhash = BLI_edgehash_new_ex(__func__, psys->tot_fluidsprings);
for (i=0, spring=psys->fluid_springs; i<psys->tot_fluidsprings; i++, spring++)
BLI_edgehash_insert(springhash, spring->particle_index[0], spring->particle_index[1], SET_INT_IN_POINTER(i+1));
@@ -3314,9 +3313,14 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part
pce->inv_nor = -1;
- /* Initial step size should be small, but not too small or floating point
- * precision errors will appear. - z0r */
- dt_init = COLLISION_INIT_STEP * col->inv_total_time;
+ if (col->inv_total_time > 0.0f) {
+ /* Initial step size should be small, but not too small or floating point
+ * precision errors will appear. - z0r */
+ dt_init = COLLISION_INIT_STEP * col->inv_total_time;
+ }
+ else {
+ dt_init = 0.001f;
+ }
/* start from the beginning */
t0 = 0.f;
@@ -4108,7 +4112,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
invert_m4_m4(ob->imat, ob->obmat);
- psys->lattice= psys_get_lattice(sim);
+ psys->lattice_deform_data= psys_create_lattice_deform_data(sim);
if (psys->totpart==0) return;
@@ -4479,7 +4483,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
if (part->randsize > 0.0f)
pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1);
- psys->lattice= psys_get_lattice(sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
dietime = pa->dietime;
@@ -4494,9 +4498,9 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
else
pa->alive = PARS_ALIVE;
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice= NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
if (PSYS_FRAND(p) > disp)
@@ -4777,9 +4781,9 @@ static void system_step(ParticleSimulationData *sim, float cfra)
update_children(sim);
/* cleanup */
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice= NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 205159c94a1..45a29f6cc90 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -229,9 +229,10 @@ void pbvh_grow_nodes(PBVH *bvh, int totnode)
bvh->node_mem_count *= 1.33;
if (bvh->node_mem_count < totnode)
bvh->node_mem_count = totnode;
- bvh->nodes = MEM_callocN(sizeof(PBVHNode) * bvh->node_mem_count,
+ bvh->nodes = MEM_mallocN(sizeof(PBVHNode) * bvh->node_mem_count,
"bvh nodes");
memcpy(bvh->nodes, prev, bvh->totnode * sizeof(PBVHNode));
+ memset(bvh->nodes + bvh->totnode, 0, (bvh->node_mem_count - bvh->totnode) * sizeof(PBVHNode));
MEM_freeN(prev);
}
@@ -244,9 +245,13 @@ static int map_insert_vert(PBVH *bvh, GHash *map,
unsigned int *face_verts,
unsigned int *uniq_verts, int vertex)
{
- void *value, *key = SET_INT_IN_POINTER(vertex);
+ void *key, **value_p;
- if (!BLI_ghash_haskey(map, key)) {
+ key = SET_INT_IN_POINTER(vertex);
+ value_p = BLI_ghash_lookup_p(map, key);
+
+ if (value_p == NULL) {
+ void *value;
if (BLI_BITMAP_GET(bvh->vert_bitmap, vertex)) {
value = SET_INT_IN_POINTER(~(*face_verts));
++(*face_verts);
@@ -260,8 +265,9 @@ static int map_insert_vert(PBVH *bvh, GHash *map,
BLI_ghash_insert(map, key, value);
return GET_INT_FROM_POINTER(value);
}
- else
- return GET_INT_FROM_POINTER(BLI_ghash_lookup(map, key));
+ else {
+ return GET_INT_FROM_POINTER(*value_p);
+ }
}
/* Find vertices used by the faces in this node and update the draw buffers */
@@ -271,11 +277,12 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
GHash *map;
int i, j, totface;
- map = BLI_ghash_int_new("build_mesh_leaf_node gh");
-
node->uniq_verts = node->face_verts = 0;
totface = node->totprim;
+ /* reserve size is rough guess */
+ map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface);
+
node->face_vert_indices = MEM_callocN(sizeof(int) * 4 * totface,
"bvh node face vert indices");
@@ -607,9 +614,9 @@ void BKE_pbvh_free(PBVH *bvh)
if (node->bm_faces)
BLI_ghash_free(node->bm_faces, NULL, NULL);
if (node->bm_unique_verts)
- BLI_ghash_free(node->bm_unique_verts, NULL, NULL);
+ BLI_gset_free(node->bm_unique_verts, NULL);
if (node->bm_other_verts)
- BLI_ghash_free(node->bm_other_verts, NULL, NULL);
+ BLI_gset_free(node->bm_other_verts, NULL);
}
}
@@ -1307,8 +1314,8 @@ void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to
if (uniquevert) *uniquevert = node->uniq_verts;
break;
case PBVH_BMESH:
- tot = BLI_ghash_size(node->bm_unique_verts);
- if (totvert) *totvert = tot + BLI_ghash_size(node->bm_other_verts);
+ tot = BLI_gset_size(node->bm_unique_verts);
+ if (totvert) *totvert = tot + BLI_gset_size(node->bm_other_verts);
if (uniquevert) *uniquevert = tot;
break;
}
@@ -1859,9 +1866,10 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
vi->mverts = verts;
if (bvh->type == PBVH_BMESH) {
- BLI_ghashIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
- BLI_ghashIterator_init(&vi->bm_other_verts, node->bm_other_verts);
+ BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
+ BLI_gsetIterator_init(&vi->bm_other_verts, node->bm_other_verts);
vi->bm_vdata = &bvh->bm->vdata;
+ vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK);
}
vi->gh = NULL;
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index cd21f8ad968..98f2f7bcf24 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -18,6 +18,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenkernel/intern/pbvh_bmesh.c
+ * \ingroup bli
+ */
+
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -48,8 +52,8 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
PBVHNode *n = &bvh->nodes[node_index];
/* Create vert hash sets */
- n->bm_unique_verts = BLI_ghash_ptr_new("bm_unique_verts");
- n->bm_other_verts = BLI_ghash_ptr_new("bm_other_verts");
+ n->bm_unique_verts = BLI_gset_ptr_new("bm_unique_verts");
+ n->bm_other_verts = BLI_gset_ptr_new("bm_other_verts");
BB_reset(&n->vb);
@@ -67,13 +71,12 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
v = l_iter->v;
- if (!BLI_ghash_haskey(n->bm_unique_verts, v)) {
+ if (!BLI_gset_haskey(n->bm_unique_verts, v)) {
if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) {
- if (!BLI_ghash_haskey(n->bm_other_verts, v))
- BLI_ghash_insert(n->bm_other_verts, v, NULL);
+ BLI_gset_reinsert(n->bm_other_verts, v, NULL);
}
else {
- BLI_ghash_insert(n->bm_unique_verts, v, NULL);
+ BLI_gset_insert(n->bm_unique_verts, v);
BLI_ghash_insert(bvh->bm_vert_to_node, v, node_val);
}
}
@@ -92,7 +95,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
if (!G.background) {
int smooth = bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING;
n->draw_buffers = GPU_build_bmesh_buffers(smooth);
- n->flag |= PBVH_UpdateDrawBuffers;
+ n->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
}
}
@@ -101,6 +104,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
{
GHash *empty, *other;
GHashIterator gh_iter;
+ GSetIterator gs_iter;
PBVHNode *n, *c1, *c2;
BB cb;
float mid;
@@ -140,8 +144,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
c2 = &bvh->nodes[children + 1];
c1->flag |= PBVH_Leaf;
c2->flag |= PBVH_Leaf;
- c1->bm_faces = BLI_ghash_ptr_new("bm_faces");
- c2->bm_faces = BLI_ghash_ptr_new("bm_faces");
+ c1->bm_faces = BLI_ghash_ptr_new_ex("bm_faces", BLI_ghash_size(n->bm_faces) / 2);
+ c2->bm_faces = BLI_ghash_ptr_new_ex("bm_faces", BLI_ghash_size(n->bm_faces) / 2);
/* Partition the parent node's faces between the two children */
GHASH_ITER (gh_iter, n->bm_faces) {
@@ -177,11 +181,11 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
/* Mark this node's unique verts as unclaimed */
if (n->bm_unique_verts) {
- GHASH_ITER (gh_iter, n->bm_unique_verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, n->bm_unique_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
}
- BLI_ghash_free(n->bm_unique_verts, NULL, NULL);
+ BLI_gset_free(n->bm_unique_verts, NULL);
}
/* Unclaim faces */
@@ -192,7 +196,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
BLI_ghash_free(n->bm_faces, NULL, NULL);
if (n->bm_other_verts)
- BLI_ghash_free(n->bm_other_verts, NULL, NULL);
+ BLI_gset_free(n->bm_other_verts, NULL);
if (n->layer_disp)
MEM_freeN(n->layer_disp);
@@ -227,19 +231,26 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
{
GHash *prim_bbc;
+ GHash *bm_faces;
+ int bm_faces_size;
GHashIterator gh_iter;
+ BBC *bbc_array;
+ unsigned int i;
- if (BLI_ghash_size(bvh->nodes[node_index].bm_faces) <= bvh->leaf_limit) {
+ bm_faces = bvh->nodes[node_index].bm_faces;
+ bm_faces_size = BLI_ghash_size(bm_faces);
+ if (bm_faces_size <= bvh->leaf_limit) {
/* Node limit not exceeded */
return FALSE;
}
/* For each BMFace, store the AABB and AABB centroid */
- prim_bbc = BLI_ghash_ptr_new("prim_bbc");
+ prim_bbc = BLI_ghash_ptr_new_ex("prim_bbc", bm_faces_size);
+ bbc_array = MEM_callocN(sizeof(BBC) * bm_faces_size, "BBC");
- GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) {
+ GHASH_ITER_INDEX (gh_iter, bm_faces, i) {
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- BBC *bbc = MEM_callocN(sizeof(BBC), "BBC");
+ BBC *bbc = &bbc_array[i];
BMLoop *l_iter;
BMLoop *l_first;
@@ -255,7 +266,8 @@ static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
pbvh_bmesh_node_split(bvh, prim_bbc, node_index);
- BLI_ghash_free(prim_bbc, NULL, MEM_freeN);
+ BLI_ghash_free(prim_bbc, NULL, NULL);
+ MEM_freeN(bbc_array);
return TRUE;
}
@@ -278,12 +290,12 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index,
const float co[3],
const BMVert *example)
{
- BMVert *v = BM_vert_create(bvh->bm, co, example, 0);
+ BMVert *v = BM_vert_create(bvh->bm, co, example, BM_CREATE_NOP);
void *val = SET_INT_IN_POINTER(node_index);
BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode);
- BLI_ghash_insert(bvh->nodes[node_index].bm_unique_verts, v, NULL);
+ BLI_gset_insert(bvh->nodes[node_index].bm_unique_verts, v);
BLI_ghash_insert(bvh->bm_vert_to_node, v, val);
/* Log the new vertex */
@@ -302,9 +314,7 @@ static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index,
/* ensure we never add existing face */
BLI_assert(BM_face_exists(v_tri, 3, NULL) == false);
- f = BM_face_create(bvh->bm, v_tri, e_tri, 3, 0);
- // BM_elem_attrs_copy(bvh->bm, bvh->bm, f_example, f);
- f->mat_nr = f_example->mat_nr;
+ f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
if (!BLI_ghash_haskey(bvh->bm_face_to_node, f)) {
@@ -367,15 +377,14 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner,
BLI_assert(current_owner != new_owner);
/* Remove current ownership */
- BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
- BLI_ghash_remove(current_owner->bm_unique_verts, v, NULL, NULL);
+ BLI_gset_remove(current_owner->bm_unique_verts, v, NULL);
/* Set new ownership */
- BLI_ghash_insert(bvh->bm_vert_to_node, v,
- SET_INT_IN_POINTER(new_owner - bvh->nodes));
- BLI_ghash_insert(new_owner->bm_unique_verts, v, NULL);
- BLI_ghash_remove(new_owner->bm_other_verts, v, NULL, NULL);
- BLI_assert(!BLI_ghash_haskey(new_owner->bm_other_verts, v));
+ BLI_ghash_reinsert(bvh->bm_vert_to_node, v,
+ SET_INT_IN_POINTER(new_owner - bvh->nodes), NULL, NULL);
+ BLI_gset_insert(new_owner->bm_unique_verts, v);
+ BLI_gset_remove(new_owner->bm_other_verts, v, NULL);
+ BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v));
}
static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
@@ -386,18 +395,20 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
v_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
- BLI_ghash_remove(v_node->bm_unique_verts, v, NULL, NULL);
+ BLI_gset_remove(v_node->bm_unique_verts, v, NULL);
BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
/* Have to check each neighboring face's node */
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
- BLI_ghash_remove(f_node->bm_unique_verts, v, NULL, NULL);
- BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL);
+ /* Remove current ownership */
+ /* Should be handled above by vert_to_node removal, leaving just in case - psy-fi */
+ //BLI_ghash_remove(f_node->bm_unique_verts, v, NULL, NULL);
+ BLI_gset_remove(f_node->bm_other_verts, v, NULL);
- BLI_assert(!BLI_ghash_haskey(f_node->bm_unique_verts, v));
- BLI_assert(!BLI_ghash_haskey(f_node->bm_other_verts, v));
+ BLI_assert(!BLI_gset_haskey(f_node->bm_unique_verts, v));
+ BLI_assert(!BLI_gset_haskey(f_node->bm_other_verts, v));
}
}
@@ -417,7 +428,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
do {
v = l_iter->v;
if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) {
- if (BLI_ghash_haskey(f_node->bm_unique_verts, v)) {
+ if (BLI_gset_haskey(f_node->bm_unique_verts, v)) {
/* Find a different node that uses 'v' */
PBVHNode *new_node;
@@ -430,7 +441,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
}
else {
/* Remove from other verts */
- BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL);
+ BLI_gset_remove(f_node->bm_other_verts, v, NULL);
}
}
} while ((l_iter = l_iter->next) != l_first);
@@ -479,6 +490,13 @@ typedef struct {
float limit_len_squared;
} EdgeQueue;
+typedef struct {
+ EdgeQueue *q;
+ BLI_mempool *pool;
+ BMesh *bm;
+ int cd_vert_mask_offset;
+} EdgeQueueContext;
+
static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
{
BMVert *v_tri[3];
@@ -494,74 +512,73 @@ static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
return ((len_squared_v3v3(q->center, c) <= q->radius_squared));
}
-/* Return true if the vertex mask is less than 0.5, false otherwise */
-static int check_mask_half(BMesh *bm, BMVert *v)
+/* Return true if the vertex mask is less than 1.0, false otherwise */
+static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
{
- const float *mask;
-
- mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
- return ((*mask) < 0.5f);
+ return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f);
}
-static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e,
- float priority, BMesh *bm)
+static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e,
+ float priority)
{
BMVert **pair;
- /* Don't let topology update affect masked vertices. Unlike with
- * displacements, can't do 50% topology update, so instead set
- * (arbitrary) cutoff: if both vertices' masks are less than 50%,
- * topology update can happen. */
- if (check_mask_half(bm, e->v1) && check_mask_half(bm, e->v2)) {
- pair = BLI_mempool_alloc(pool);
+ /* Don't let topology update affect fully masked vertices. This used to
+ * have a 50% mask cutoff, with the reasoning that you can't do a 50%
+ * topology update. But this gives an ugly border in the mesh. The mask
+ * should already make the brush move the vertices only 50%, which means
+ * that topology updates will also happen less frequent, that should be
+ * enough. */
+ if (check_mask(eq_ctx, e->v1) || check_mask(eq_ctx, e->v2)) {
+ pair = BLI_mempool_alloc(eq_ctx->pool);
pair[0] = e->v1;
pair[1] = e->v2;
- BLI_heap_insert(q->heap, priority, pair);
+ BLI_heap_insert(eq_ctx->q->heap, priority, pair);
}
}
-static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
- BMEdge *e, BMesh *bm)
+static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx,
+ BMEdge *e)
{
const float len_sq = BM_edge_calc_length_squared(e);
- if (len_sq > q->limit_len_squared)
- edge_queue_insert(q, pool, e, 1.0f / len_sq, bm);
+ if (len_sq > eq_ctx->q->limit_len_squared)
+ edge_queue_insert(eq_ctx, e, 1.0f / len_sq);
}
-static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
- BMEdge *e, BMesh *bm)
+static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx,
+ BMEdge *e)
{
const float len_sq = BM_edge_calc_length_squared(e);
- if (len_sq < q->limit_len_squared)
- edge_queue_insert(q, pool, e, len_sq, bm);
+ if (len_sq < eq_ctx->q->limit_len_squared)
+ edge_queue_insert(eq_ctx, e, len_sq);
}
-static void long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool,
- BMFace *f, BMesh *bm)
+static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx,
+ BMFace *f)
{
- if (edge_queue_tri_in_sphere(q, f)) {
+ if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
BMLoop *l_iter;
BMLoop *l_first;
/* Check each edge of the face */
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- long_edge_queue_edge_add(q, pool, l_iter->e, bm);
+ long_edge_queue_edge_add(eq_ctx, l_iter->e);
} while ((l_iter = l_iter->next) != l_first);
}
}
-static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool,
- BMFace *f, BMesh *bm)
+static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx,
+ BMFace *f)
{
- if (edge_queue_tri_in_sphere(q, f)) {
+ if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
BMLoop *l_iter;
BMLoop *l_first;
/* Check each edge of the face */
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- short_edge_queue_edge_add(q, pool, l_iter->e, bm);
+ short_edge_queue_edge_add(eq_ctx, l_iter->e);
} while ((l_iter = l_iter->next) != l_first);
}
}
@@ -575,16 +592,16 @@ static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool,
*
* The highest priority (lowest number) is given to the longest edge.
*/
-static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
+static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
PBVH *bvh, const float center[3],
float radius)
{
int n;
- q->heap = BLI_heap_new();
- q->center = center;
- q->radius_squared = radius * radius;
- q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len;
+ eq_ctx->q->heap = BLI_heap_new();
+ eq_ctx->q->center = center;
+ eq_ctx->q->radius_squared = radius * radius;
+ eq_ctx->q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len;
for (n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
@@ -599,7 +616,7 @@ static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
GHASH_ITER (gh_iter, node->bm_faces) {
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- long_edge_queue_face_add(q, pool, f, bvh->bm);
+ long_edge_queue_face_add(eq_ctx, f);
}
}
}
@@ -614,16 +631,16 @@ static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
*
* The highest priority (lowest number) is given to the shortest edge.
*/
-static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
+static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
PBVH *bvh, const float center[3],
float radius)
{
int n;
- q->heap = BLI_heap_new();
- q->center = center;
- q->radius_squared = radius * radius;
- q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+ eq_ctx->q->heap = BLI_heap_new();
+ eq_ctx->q->center = center;
+ eq_ctx->q->radius_squared = radius * radius;
+ eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
for (n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
@@ -638,7 +655,7 @@ static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
GHASH_ITER (gh_iter, node->bm_faces) {
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- short_edge_queue_face_add(q, pool, f, bvh->bm);
+ short_edge_queue_face_add(eq_ctx, f);
}
}
}
@@ -653,12 +670,13 @@ static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE);
}
-static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
+static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
BMEdge *e, BLI_Buffer *edge_loops)
{
BMVert *v_new;
float mid[3];
int i, node_index;
+ const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK);
/* Get all faces adjacent to the edge */
pbvh_bmesh_edge_loops(edge_loops, e);
@@ -670,6 +688,15 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
e->v1));
v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1);
+ /* update paint mask */
+ if (cd_vert_mask_offset != -1) {
+ float mask_v1 = BM_ELEM_CD_GET_FLOAT(e->v1, cd_vert_mask_offset);
+ float mask_v2 = BM_ELEM_CD_GET_FLOAT(e->v2, cd_vert_mask_offset);
+ float mask_v_new = 0.5f*(mask_v1 + mask_v2);
+
+ BM_ELEM_CD_SET_FLOAT(v_new, cd_vert_mask_offset, mask_v_new);
+ }
+
/* For each face, add two new triangles and delete the original */
for (i = 0; i < edge_loops->count; i++) {
BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i);
@@ -686,7 +713,7 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
ni = GET_INT_FROM_POINTER(nip);
/* Ensure node gets redrawn */
- bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers;
+ bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
/* Find the vertex not in the edge */
v_opp = l_adj->prev->v;
@@ -706,7 +733,7 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
v_tri[2] = v_opp;
bm_edges_from_tri(bvh->bm, v_tri, e_tri);
f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
- long_edge_queue_face_add(q, pool, f_new, bvh->bm);
+ long_edge_queue_face_add(eq_ctx, f_new);
v_tri[0] = v_new;
v_tri[1] = v2;
@@ -715,17 +742,17 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
e_tri[2] = e_tri[1]; /* switched */
e_tri[1] = BM_edge_create(bvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
- long_edge_queue_face_add(q, pool, f_new, bvh->bm);
+ long_edge_queue_face_add(eq_ctx, f_new);
/* Delete original */
pbvh_bmesh_face_remove(bvh, f_adj);
BM_face_kill(bvh->bm, f_adj);
/* Ensure new vertex is in the node */
- if (!BLI_ghash_haskey(bvh->nodes[ni].bm_unique_verts, v_new) &&
- !BLI_ghash_haskey(bvh->nodes[ni].bm_other_verts, v_new))
+ if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new) &&
+ !BLI_gset_haskey(bvh->nodes[ni].bm_other_verts, v_new))
{
- BLI_ghash_insert(bvh->nodes[ni].bm_other_verts, v_new, NULL);
+ BLI_gset_insert(bvh->nodes[ni].bm_other_verts, v_new);
}
if (BM_vert_edge_count(v_opp) >= 9) {
@@ -733,7 +760,7 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
BMEdge *e2;
BM_ITER_ELEM (e2, &bm_iter, v_opp, BM_EDGES_OF_VERT) {
- long_edge_queue_edge_add(q, pool, e2, bvh->bm);
+ long_edge_queue_edge_add(eq_ctx, e2);
}
}
}
@@ -741,23 +768,22 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
BM_edge_kill(bvh->bm, e);
}
-static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q,
- BLI_mempool *pool,
+static int pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh,
BLI_Buffer *edge_loops)
{
int any_subdivided = FALSE;
- while (!BLI_heap_is_empty(q->heap)) {
- BMVert **pair = BLI_heap_popmin(q->heap);
+ while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
+ BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
BMEdge *e;
/* Check that the edge still exists */
if (!(e = BM_edge_exists(pair[0], pair[1]))) {
- BLI_mempool_free(pool, pair);
+ BLI_mempool_free(eq_ctx->pool, pair);
continue;
}
- BLI_mempool_free(pool, pair);
+ BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
/* Check that the edge's vertices are still in the PBVH. It's
@@ -770,12 +796,12 @@ static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q,
continue;
}
- if (BM_edge_calc_length_squared(e) <= q->limit_len_squared)
+ if (BM_edge_calc_length_squared(e) <= eq_ctx->q->limit_len_squared)
continue;
any_subdivided = TRUE;
- pbvh_bmesh_split_edge(bvh, q, pool, e, edge_loops);
+ pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops);
}
return any_subdivided;
@@ -846,10 +872,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1,
pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f);
/* Ensure that v1 is in the new face's node */
- if (!BLI_ghash_haskey(n->bm_unique_verts, v1) &&
- !BLI_ghash_haskey(n->bm_other_verts, v1))
+ if (!BLI_gset_haskey(n->bm_unique_verts, v1) &&
+ !BLI_gset_haskey(n->bm_other_verts, v1))
{
- BLI_ghash_insert(n->bm_other_verts, v1, NULL);
+ BLI_gset_insert(n->bm_other_verts, v1);
}
}
@@ -917,8 +943,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1,
BM_vert_kill(bvh->bm, v2);
}
-static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q,
- BLI_mempool *pool,
+static int pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
+ PBVH *bvh,
BLI_Buffer *edge_loops,
BLI_Buffer *deleted_faces)
{
@@ -928,14 +954,14 @@ static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q,
deleted_verts = BLI_ghash_ptr_new("deleted_verts");
- while (!BLI_heap_is_empty(q->heap)) {
- BMVert **pair = BLI_heap_popmin(q->heap);
+ while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
+ BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
BMEdge *e;
BMVert *v1, *v2;
v1 = pair[0];
v2 = pair[1];
- BLI_mempool_free(pool, pair);
+ BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
/* Check that the vertices/edge still exist */
@@ -1012,19 +1038,29 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
return hit;
}
+
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
{
int n;
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, node->bm_faces) {
- BM_face_normal_update(BLI_ghashIterator_getKey(&gh_iter));
- }
- GHASH_ITER (gh_iter, node->bm_unique_verts) {
- BM_vert_normal_update(BLI_ghashIterator_getKey(&gh_iter));
+ if (node->flag & PBVH_UpdateNormals) {
+ GHashIterator gh_iter;
+ GSetIterator gs_iter;
+
+ GHASH_ITER (gh_iter, node->bm_faces) {
+ BM_face_normal_update(BLI_ghashIterator_getKey(&gh_iter));
+ }
+ GSET_ITER (gs_iter, node->bm_unique_verts) {
+ BM_vert_normal_update(BLI_gsetIterator_getKey(&gs_iter));
+ }
+ /* This should be unneeded normally */
+ GSET_ITER (gs_iter, node->bm_other_verts) {
+ BM_vert_normal_update(BLI_gsetIterator_getKey(&gs_iter));
+ }
+ node->flag &= ~PBVH_UpdateNormals;
}
}
}
@@ -1059,7 +1095,7 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
n = bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
bvh->totnode = 1;
n->flag = PBVH_Leaf;
- n->bm_faces = BLI_ghash_ptr_new("bm_faces");
+ n->bm_faces = BLI_ghash_ptr_new_ex("bm_faces", bvh->bm->totface);
BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
BLI_ghash_insert(n->bm_faces, f, NULL);
}
@@ -1077,6 +1113,7 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
/* 2 is enough for edge faces - manifold edge */
BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2);
BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32);
+ const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK);
int modified = FALSE;
int n;
@@ -1085,8 +1122,10 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
EdgeQueue q;
BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
128, 128, 0);
- short_edge_queue_create(&q, queue_pool, bvh, center, radius);
- pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_loops,
+ EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset};
+
+ short_edge_queue_create(&eq_ctx, bvh, center, radius);
+ pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &edge_loops,
&deleted_faces);
BLI_heap_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
@@ -1096,8 +1135,10 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
EdgeQueue q;
BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
128, 128, 0);
- long_edge_queue_create(&q, queue_pool, bvh, center, radius);
- pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_loops);
+ EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset};
+
+ long_edge_queue_create(&eq_ctx, bvh, center, radius);
+ pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops);
BLI_heap_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
}
@@ -1136,14 +1177,15 @@ BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3])
void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
{
GHashIterator gh_iter;
+ GSetIterator gs_iter;
int i, totvert, tottri;
/* Skip if original coords/triangles are already saved */
if (node->bm_orco)
return;
- totvert = (BLI_ghash_size(node->bm_unique_verts) +
- BLI_ghash_size(node->bm_other_verts));
+ totvert = (BLI_gset_size(node->bm_unique_verts) +
+ BLI_gset_size(node->bm_other_verts));
tottri = BLI_ghash_size(node->bm_faces);
@@ -1152,14 +1194,14 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
/* Copy out the vertices and assign a temporary index */
i = 0;
- GHASH_ITER (gh_iter, node->bm_unique_verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, node->bm_unique_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
copy_v3_v3(node->bm_orco[i], v->co);
BM_elem_index_set(v, i); /* set_dirty! */
i++;
}
- GHASH_ITER (gh_iter, node->bm_other_verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, node->bm_other_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
copy_v3_v3(node->bm_orco[i], v->co);
BM_elem_index_set(v, i); /* set_dirty! */
i++;
@@ -1216,12 +1258,12 @@ void BKE_pbvh_node_mark_topology_update(PBVHNode *node)
node->flag |= PBVH_UpdateTopology;
}
-GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node)
+GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node)
{
return node->bm_unique_verts;
}
-GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node)
+GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node)
{
return node->bm_other_verts;
}
@@ -1250,6 +1292,27 @@ void bli_ghash_duplicate_key_check(GHash *gh)
}
}
+void bli_gset_duplicate_key_check(GSet *gs)
+{
+ GSetIterator gs_iter1, gs_iter2;
+
+ GSET_ITER (gs_iter1, gs) {
+ void *key1 = BLI_gsetIterator_getKey(&gs_iter1);
+ int dup = -1;
+
+ GSET_ITER (gs_iter2, gs) {
+ void *key2 = BLI_gsetIterator_getKey(&gs_iter2);
+
+ if (key1 == key2) {
+ dup++;
+ if (dup > 0) {
+ BLI_assert(!"duplicate in hash");
+ }
+ }
+ }
+ }
+}
+
void bmesh_print(BMesh *bm)
{
BMIter iter, siter;
@@ -1264,14 +1327,14 @@ void bmesh_print(BMesh *bm)
bm->totloop, bm->totface);
fprintf(stderr, "vertices:\n");
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
fprintf(stderr, " %d co=(%.3f %.3f %.3f) oflag=%x\n",
BM_elem_index_get(v), v->co[0], v->co[1], v->co[2],
v->oflags[bm->stackdepth - 1].f);
}
fprintf(stderr, "edges:\n");
- BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
fprintf(stderr, " %d v1=%d, v2=%d, oflag=%x\n",
BM_elem_index_get(e),
BM_elem_index_get(e->v1),
@@ -1280,7 +1343,7 @@ void bmesh_print(BMesh *bm)
}
fprintf(stderr, "faces:\n");
- BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
fprintf(stderr, " %d len=%d, oflag=%x\n",
BM_elem_index_get(f), f->len,
f->oflags[bm->stackdepth - 1].f);
@@ -1311,6 +1374,7 @@ void bmesh_print(BMesh *bm)
void pbvh_bmesh_print(PBVH *bvh)
{
GHashIterator gh_iter;
+ GSetIterator gs_iter;
int n;
fprintf(stderr, "\npbvh=%p\n", bvh);
@@ -1338,13 +1402,13 @@ void pbvh_bmesh_print(PBVH *bvh)
fprintf(stderr, " %d\n",
BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter)));
fprintf(stderr, " unique verts:\n");
- GHASH_ITER (gh_iter, node->bm_unique_verts)
+ GSET_ITER (gs_iter, node->bm_unique_verts)
fprintf(stderr, " %d\n",
- BM_elem_index_get((BMVert *)BLI_ghashIterator_getKey(&gh_iter)));
+ BM_elem_index_get((BMVert *)BLI_gsetIterator_getKey(&gs_iter)));
fprintf(stderr, " other verts:\n");
- GHASH_ITER (gh_iter, node->bm_other_verts)
+ GSET_ITER (gs_iter, node->bm_other_verts)
fprintf(stderr, " %d\n",
- BM_elem_index_get((BMVert *)BLI_ghashIterator_getKey(&gh_iter)));
+ BM_elem_index_get((BMVert *)BLI_gsetIterator_getKey(&gs_iter)));
}
}
@@ -1362,7 +1426,10 @@ void print_flag_factors(int flag)
void pbvh_bmesh_verify(PBVH *bvh)
{
GHashIterator gh_iter;
- int i;
+ GSetIterator gs_iter;
+ int i, vert_count = 0;
+ BMIter iter;
+ BMVert *vi;
/* Check faces */
BLI_assert(bvh->bm->totface == BLI_ghash_size(bvh->bm_face_to_node));
@@ -1385,17 +1452,17 @@ void pbvh_bmesh_verify(PBVH *bvh)
PBVHNode *nv;
/* Check that the vertex is in the node */
- BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v) ^
- BLI_ghash_haskey(n->bm_other_verts, v));
+ BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v) ^
+ BLI_gset_haskey(n->bm_other_verts, v));
/* Check that the vertex has a node owner */
nv = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
/* Check that the vertex's node knows it owns the vert */
- BLI_assert(BLI_ghash_haskey(nv->bm_unique_verts, v));
+ BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v));
/* Check that the vertex isn't duplicated as an 'other' vert */
- BLI_assert(!BLI_ghash_haskey(nv->bm_other_verts, v));
+ BLI_assert(!BLI_gset_haskey(nv->bm_other_verts, v));
}
}
@@ -1414,10 +1481,10 @@ void pbvh_bmesh_verify(PBVH *bvh)
BLI_assert(n->flag & PBVH_Leaf);
/* Check that the vert's node knows it owns the vert */
- BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v));
+ BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v));
/* Check that the vertex isn't duplicated as an 'other' vert */
- BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v));
+ BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v));
/* Check that the vert's node also contains one of the vert's
* adjacent faces */
@@ -1428,8 +1495,37 @@ void pbvh_bmesh_verify(PBVH *bvh)
}
}
BLI_assert(found);
+
+ #if 1
+ /* total freak stuff, check if node exists somewhere else */
+ /* Slow */
+ for (i = 0; i < bvh->totnode; i++) {
+ PBVHNode *n = &bvh->nodes[i];
+ if (i != ni && n->bm_unique_verts)
+ BLI_assert(!BLI_gset_haskey(n->bm_unique_verts, v));
+ }
+
+ #endif
}
+ #if 0
+ /* check that every vert belongs somewhere */
+ /* Slow */
+ BM_ITER_MESH (vi, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ bool has_unique = false;
+ for (i = 0; i < bvh->totnode; i++) {
+ PBVHNode *n = &bvh->nodes[i];
+ if ((n->bm_unique_verts != NULL) && BLI_gset_haskey(n->bm_unique_verts, vi))
+ has_unique = true;
+ }
+ BLI_assert(has_unique);
+ vert_count++;
+ }
+
+ /* if totvert differs from number of verts inside the hash. hash-totvert is checked above */
+ BLI_assert(vert_count == bvh->bm->totvert);
+ #endif
+
/* Check that node elements are recorded in the top level */
for (i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
@@ -1438,8 +1534,8 @@ void pbvh_bmesh_verify(PBVH *bvh)
/* Slow */
#if 0
bli_ghash_duplicate_key_check(n->bm_faces);
- bli_ghash_duplicate_key_check(n->bm_unique_verts);
- bli_ghash_duplicate_key_check(n->bm_other_verts);
+ bli_gset_duplicate_key_check(n->bm_unique_verts);
+ bli_gset_duplicate_key_check(n->bm_other_verts);
#endif
GHASH_ITER (gh_iter, n->bm_faces) {
@@ -1449,16 +1545,16 @@ void pbvh_bmesh_verify(PBVH *bvh)
BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes));
}
- GHASH_ITER (gh_iter, n->bm_unique_verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, n->bm_unique_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
void *nip = BLI_ghash_lookup(bvh->bm_vert_to_node, v);
BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
- BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v));
+ BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v));
BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes));
}
- GHASH_ITER (gh_iter, n->bm_other_verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, n->bm_other_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
BLI_assert(BM_vert_face_count(v) > 0);
}
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 4154b8e4799..89bfbc252a8 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -21,6 +21,10 @@
#ifndef __PBVH_INTERN_H__
#define __PBVH_INTERN_H__
+/** \file blender/blenkernel/intern/pbvh_intern.h
+ * \ingroup bli
+ */
+
/* Axis-aligned bounding box */
typedef struct {
float bmin[3], bmax[3];
@@ -101,8 +105,8 @@ struct PBVHNode {
/* Dyntopo */
GHash *bm_faces;
- GHash *bm_unique_verts;
- GHash *bm_other_verts;
+ GSet *bm_unique_verts;
+ GSet *bm_other_verts;
float (*bm_orco)[3];
int (*bm_ortri)[3];
int bm_tot_ortri;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 93f6965e97b..9891a8cde28 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -66,6 +66,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -227,6 +228,11 @@ static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
SoftBody *soft= soft_v;
return soft->totpoint;
}
+static void ptcache_softbody_error(void *UNUSED(soft_v), const char *UNUSED(message))
+{
+ /* ignored for now */
+}
+
/* Particle functions */
void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
{
@@ -405,6 +411,12 @@ static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
ParticleSystem *psys = psys_v;
return psys->totpart;
}
+
+static void ptcache_particle_error(void *UNUSED(psys_v), const char *UNUSED(message))
+{
+ /* ignored for now */
+}
+
static int ptcache_particle_totwrite(void *psys_v, int cfra)
{
ParticleSystem *psys = psys_v;
@@ -534,6 +546,12 @@ static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
return clmd->clothObject ? clmd->clothObject->numverts : 0;
}
+static void ptcache_cloth_error(void *cloth_v, const char *message)
+{
+ ClothModifierData *clmd= cloth_v;
+ modifier_setError(&clmd->modifier, "%s", message);
+}
+
#ifdef WITH_SMOKE
/* Smoke functions */
static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
@@ -548,6 +566,12 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
return 0;
}
+static void ptcache_smoke_error(void *smoke_v, const char *message)
+{
+ SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
+ modifier_setError(&smd->modifier, "%s", message);
+}
+
#define SMOKE_CACHE_VERSION "1.04"
static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
@@ -865,8 +889,10 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
return 1;
}
+
#else // WITH_SMOKE
static int ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; }
+static void ptcache_smoke_error(void *UNUSED(smoke_v), const char *UNUSED(message)) { }
static int ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
static int ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
#endif // WITH_SMOKE
@@ -879,6 +905,11 @@ static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
else return surface->data->total_points;
}
+static void ptcache_dynamicpaint_error(void *UNUSED(sd), const char *UNUSED(message))
+{
+ /* ignored for now */
+}
+
#define DPAINT_CACHE_VERSION "1.01"
static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
@@ -1055,6 +1086,11 @@ static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
return rbw->numbodies;
}
+static void ptcache_rigidbody_error(void *UNUSED(rb_v), const char *UNUSED(message))
+{
+ /* ignored for now */
+}
+
/* Creating ID's */
void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
{
@@ -1067,6 +1103,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->cache_ptr= &sb->pointcache;
pid->ptcaches= &sb->ptcaches;
pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
+ pid->error = ptcache_softbody_error;
pid->write_point = ptcache_softbody_write;
pid->read_point = ptcache_softbody_read;
@@ -1107,6 +1144,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->totpoint = ptcache_particle_totpoint;
pid->totwrite = ptcache_particle_totwrite;
+ pid->error = ptcache_particle_error;
pid->write_point = ptcache_particle_write;
pid->read_point = ptcache_particle_read;
@@ -1159,6 +1197,7 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->cache_ptr= &clmd->point_cache;
pid->ptcaches= &clmd->ptcaches;
pid->totpoint= pid->totwrite= ptcache_cloth_totpoint;
+ pid->error = ptcache_cloth_error;
pid->write_point = ptcache_cloth_write;
pid->read_point = ptcache_cloth_read;
@@ -1197,6 +1236,7 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo
pid->ptcaches= &(sds->ptcaches[0]);
pid->totpoint= pid->totwrite= ptcache_smoke_totpoint;
+ pid->error = ptcache_smoke_error;
pid->write_point = NULL;
pid->read_point = NULL;
@@ -1236,6 +1276,7 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu
pid->cache_ptr= &surface->pointcache;
pid->ptcaches= &surface->ptcaches;
pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint;
+ pid->error = ptcache_dynamicpaint_error;
pid->write_point = NULL;
pid->read_point = NULL;
@@ -1272,6 +1313,7 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->cache_ptr= &rbw->pointcache;
pid->ptcaches= &rbw->ptcaches;
pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
+ pid->error = ptcache_rigidbody_error;
pid->write_point = ptcache_rigidbody_write;
pid->read_point = ptcache_rigidbody_read;
@@ -2083,21 +2125,31 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra)
return 0;
}
- if (!ptcache_file_header_begin_read(pf))
+ if (!ptcache_file_header_begin_read(pf)) {
+ pid->error(pid->calldata, "Failed to read point cache file");
error = 1;
-
- if (!error && (pf->type != pid->type || !pid->read_header(pf)))
+ }
+ else if (pf->type != pid->type) {
+ pid->error(pid->calldata, "Point cache file has wrong type");
error = 1;
-
- if (!error && pf->totpoint != pid->totpoint(pid->calldata, cfra))
+ }
+ else if (!pid->read_header(pf)) {
+ pid->error(pid->calldata, "Failed to read point cache file header");
+ error = 1;
+ }
+ else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) {
+ pid->error(pid->calldata, "Number of points in cache does not match mesh");
error = 1;
+ }
if (!error) {
ptcache_file_pointers_init(pf);
// we have stream reading here
- if (!pid->read_stream(pf, pid->calldata))
+ if (!pid->read_stream(pf, pid->calldata)) {
+ pid->error(pid->calldata, "Failed to read point cache file data");
error = 1;
+ }
}
ptcache_file_close(pf);
@@ -2125,8 +2177,14 @@ static int ptcache_read(PTCacheID *pid, int cfra)
if (pm) {
int totpoint = pm->totpoint;
- if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
- totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra));
+ if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) {
+ int pid_totpoint = pid->totpoint(pid->calldata, cfra);
+
+ if (totpoint != pid_totpoint) {
+ pid->error(pid->calldata, "Number of points in cache does not match mesh");
+ totpoint = MIN2(totpoint, pid_totpoint);
+ }
+ }
BKE_ptcache_mem_pointers_init(pm);
@@ -2173,8 +2231,14 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
if (pm) {
int totpoint = pm->totpoint;
- if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0)
- totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra));
+ if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) {
+ int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra);
+
+ if (totpoint != pid_totpoint) {
+ pid->error(pid->calldata, "Number of points in cache does not match mesh");
+ totpoint = MIN2(totpoint, pid_totpoint);
+ }
+ }
BKE_ptcache_mem_pointers_init(pm);
@@ -2969,12 +3033,10 @@ void BKE_ptcache_free(PointCache *cache)
}
void BKE_ptcache_free_list(ListBase *ptcaches)
{
- PointCache *cache = ptcaches->first;
+ PointCache *cache;
- while (cache) {
- BLI_remlink(ptcaches, cache);
+ while ((cache = BLI_pophead(ptcaches))) {
BKE_ptcache_free(cache);
- cache = ptcaches->first;
}
}
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index 73f2a864e32..bb04d548a44 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -59,9 +59,8 @@ void BKE_bproperty_free(bProperty *prop)
void BKE_bproperty_free_list(ListBase *lb)
{
bProperty *prop;
-
- while ( (prop = lb->first) ) {
- BLI_remlink(lb, prop);
+
+ while ((prop = BLI_pophead(lb))) {
BKE_bproperty_free(prop);
}
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index f3276992381..42147be33e4 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -1166,7 +1166,7 @@ static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
if (ob) {
RigidBodyOb *rbo = ob->rigidbody_object;
/* reset kinematic state for transformed objects */
- if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) {
+ if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) {
RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
/* deactivate passive objects so they don't interfere with deactivation of active objects */
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 92f57a54a01..7c374fd5d78 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -63,8 +63,7 @@ void free_sensors(ListBase *lb)
{
bSensor *sens;
- while ((sens= lb->first)) {
- BLI_remlink(lb, sens);
+ while ((sens = BLI_pophead(lb))) {
free_sensor(sens);
}
}
@@ -113,9 +112,6 @@ void init_sensor(bSensor *sens)
case SENS_ALWAYS:
sens->pulse = 0;
break;
- case SENS_TOUCH:
- sens->data= MEM_callocN(sizeof(bTouchSensor), "touchsens");
- break;
case SENS_NEAR:
ns=sens->data= MEM_callocN(sizeof(bNearSensor), "nearsens");
ns->dist= 1.0;
@@ -227,9 +223,9 @@ void free_controllers(ListBase *lb)
{
bController *cont;
- while ((cont= lb->first)) {
- BLI_remlink(lb, cont);
- if (cont->slinks) MEM_freeN(cont->slinks);
+ while ((cont = BLI_pophead(lb))) {
+ if (cont->slinks)
+ MEM_freeN(cont->slinks);
free_controller(cont);
}
}
@@ -346,8 +342,7 @@ void free_actuators(ListBase *lb)
{
bActuator *act;
- while ((act= lb->first)) {
- BLI_remlink(lb, act);
+ while ((act = BLI_pophead(lb))) {
free_actuator(act);
}
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 1874523dac9..41e43c00457 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -44,6 +44,7 @@
#include "DNA_anim_types.h"
#include "DNA_group_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
@@ -429,7 +430,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.filtertype = R_FILTER_MITCH;
sce->r.size = 50;
- sce->r.im_format.planes = R_IMF_PLANES_RGB;
+ sce->r.im_format.planes = R_IMF_PLANES_RGBA;
sce->r.im_format.imtype = R_IMF_IMTYPE_PNG;
sce->r.im_format.depth = R_IMF_CHAN_DEPTH_8;
sce->r.im_format.quality = 90;
@@ -492,23 +493,10 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.border.ymax = 1.0f;
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
- sce->toolsettings->cornertype = 1;
- sce->toolsettings->degr = 90;
- sce->toolsettings->step = 9;
- sce->toolsettings->turn = 1;
- sce->toolsettings->extr_offs = 1;
sce->toolsettings->doublimit = 0.001;
- sce->toolsettings->segments = 32;
- sce->toolsettings->rings = 32;
- sce->toolsettings->vertices = 32;
- sce->toolsettings->uvcalc_radius = 1.0f;
- sce->toolsettings->uvcalc_cubesize = 1.0f;
- sce->toolsettings->uvcalc_mapdir = 1;
- sce->toolsettings->uvcalc_mapalign = 1;
sce->toolsettings->uvcalc_margin = 0.001f;
sce->toolsettings->unwrapper = 1;
sce->toolsettings->select_thresh = 0.01f;
- sce->toolsettings->jointrilimit = 0.8f;
sce->toolsettings->selectmode = SCE_SELECT_VERTEX;
sce->toolsettings->uv_selectmode = UV_SELECT_VERTEX;
@@ -1064,6 +1052,7 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
*/
static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
{
+ SceneRenderLayer *srl;
float ctime = BKE_scene_frame_get(scene);
/* scene itself */
@@ -1098,6 +1087,22 @@ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
if (adt && adt->drivers.first)
BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
}
+
+ /* freestyle */
+ for (srl = scene->r.layers.first; srl; srl = srl->next) {
+ FreestyleConfig *config = &srl->freestyleConfig;
+ FreestyleLineSet *lineset;
+
+ for (lineset = config->linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->linestyle) {
+ ID *lid = &lineset->linestyle->id;
+ AnimData *adt = BKE_animdata_from_id(lid);
+
+ if (adt && adt->drivers.first)
+ BKE_animsys_evaluate_animdata(scene, lid, adt, ctime, ADT_RECALC_DRIVERS);
+ }
+ }
+ }
}
/* deps hack - do extra recalcs at end */
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index fe2f52d79fd..c41c66ef561 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -47,6 +47,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BKE_idprop.h"
#include "BKE_screen.h"
/* ************ Spacetype/regiontype handling ************** */
@@ -111,7 +112,7 @@ ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid)
if (art->regionid == regionid)
return art;
- printf("Error, region type missing in - name:\"%s\", id:%d\n", st->name, st->spaceid);
+ printf("Error, region type %d missing in - name:\"%s\", id:%d\n", regionid, st->name, st->spaceid);
return st->regiontypes.first;
}
@@ -267,6 +268,8 @@ void BKE_spacedata_draw_locks(int set)
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)
{
+ uiList *uilst;
+
if (st) {
ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype);
@@ -285,6 +288,23 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
}
BLI_freelistN(&ar->panels);
+
+ for (uilst = ar->ui_lists.first; uilst; uilst = uilst->next) {
+ if (uilst->dyn_data) {
+ uiListDyn *dyn_data = uilst->dyn_data;
+ if (dyn_data->items_filter_flags) {
+ MEM_freeN(dyn_data->items_filter_flags);
+ }
+ if (dyn_data->items_filter_neworder) {
+ MEM_freeN(dyn_data->items_filter_neworder);
+ }
+ MEM_freeN(dyn_data);
+ }
+ if (uilst->properties) {
+ IDP_FreeProperty(uilst->properties);
+ MEM_freeN(uilst->properties);
+ }
+ }
BLI_freelistN(&ar->ui_lists);
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 34b19e3f357..dd7e847feaf 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -417,33 +417,41 @@ void BKE_sequencer_editing_free(Scene *scene)
static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf)
{
- IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
+ if (ibuf->rect_float) {
+ IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
+ }
}
void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_float)
{
const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
const char *to_colorspace = scene->sequencer_colorspace_settings.name;
+ const char *float_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
if (!ibuf->rect_float) {
- if (make_float && ibuf->rect) {
- /* when converting byte buffer to float in sequencer we need to make float
- * buffer be in sequencer's working space, which is currently only doable
- * from linear space.
- *
- */
-
- /*
- * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's
- */
-
- IMB_float_from_rect(ibuf);
+ if (ibuf->rect) {
+ const char *byte_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
+ if (make_float || !STREQ(to_colorspace, byte_colorspace)) {
+ /* If byte space is not in sequencer's working space, we deliver float color space,
+ * this is to to prevent data loss.
+ */
+
+ /* when converting byte buffer to float in sequencer we need to make float
+ * buffer be in sequencer's working space, which is currently only doable
+ * from linear space.
+ */
+
+ /*
+ * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's
+ */
+
+ IMB_float_from_rect(ibuf);
+ }
+ else {
+ return;
+ }
}
else {
- /* if there's only byte buffer in image it's already in compositor's working space,
- * nothing to do here
- */
-
return;
}
}
@@ -452,8 +460,10 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_
if (ibuf->rect)
imb_freerectImBuf(ibuf);
- IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, TRUE);
+ if (!STREQ(float_colorspace, to_colorspace)) {
+ IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace, true);
+ }
}
}
@@ -467,7 +477,7 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf)
if (to_colorspace && to_colorspace[0] != '\0') {
IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, TRUE);
+ from_colorspace, to_colorspace, true);
}
}
@@ -622,7 +632,7 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase
endofs = seq->start + seq->len - end;
sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs,
- seq->start + seq->len - endofs, startofs);
+ seq->start + seq->len - endofs, startofs + seq->anim_startofs);
}
}
}
@@ -654,8 +664,9 @@ void BKE_sequence_calc_disp(Scene *scene, Sequence *seq)
if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
BKE_sequencer_update_sound_bounds(scene, seq);
}
- else if (seq->type == SEQ_TYPE_META)
+ else if (seq->type == SEQ_TYPE_META) {
seq_update_sound_bounds_recursive(scene, seq);
+ }
}
void BKE_sequence_calc(Scene *scene, Sequence *seq)
@@ -865,8 +876,7 @@ void BKE_sequencer_sort(Scene *scene)
seqbase.first = seqbase.last = NULL;
effbase.first = effbase.last = NULL;
- while ( (seq = ed->seqbasep->first) ) {
- BLI_remlink(ed->seqbasep, seq);
+ while ((seq = BLI_pophead(ed->seqbasep))) {
if (seq->type & SEQ_TYPE_EFFECT) {
seqt = effbase.first;
@@ -2669,10 +2679,14 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
seq_rendersize_to_proxysize(context.preview_render_size));
- /* we don't need both (speed reasons)! */
- if (ibuf && ibuf->rect_float && ibuf->rect)
- imb_freerectImBuf(ibuf);
if (ibuf) {
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE);
+
+ /* we don't need both (speed reasons)! */
+ if (ibuf->rect_float && ibuf->rect) {
+ imb_freerectImBuf(ibuf);
+ }
+
seq->strip->stripdata->orig_width = ibuf->x;
seq->strip->stripdata->orig_height = ibuf->y;
}
@@ -3677,6 +3691,51 @@ bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene)
return offset ? false : true;
}
+/* Unlike _update_sound_ funcs, these ones take info from audaspace to update sequence length! */
+#ifdef WITH_AUDASPACE
+static bool sequencer_refresh_sound_length_recursive(Scene *scene, ListBase *seqbase)
+{
+ Sequence *seq;
+ bool changed = false;
+
+ for (seq = seqbase->first; seq; seq = seq->next) {
+ if (seq->type == SEQ_TYPE_META) {
+ if (sequencer_refresh_sound_length_recursive(scene, &seq->seqbase)) {
+ BKE_sequence_calc(scene, seq);
+ changed = true;
+ }
+ }
+ else if (seq->type == SEQ_TYPE_SOUND_RAM) {
+ AUD_SoundInfo info = AUD_getInfo(seq->sound->playback_handle);
+ int old = seq->len;
+ float fac;
+
+ seq->len = (int)ceil((double)info.length * FPS);
+ fac = (float)seq->len / (float)old;
+ old = seq->startofs;
+ seq->startofs *= fac;
+ seq->endofs *= fac;
+ seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */
+
+ BKE_sequence_calc(scene, seq);
+ changed = true;
+ }
+ }
+ return changed;
+}
+#endif
+
+void BKE_sequencer_refresh_sound_length(Scene *scene)
+{
+#ifdef WITH_AUDASPACE
+ if (scene->ed) {
+ sequencer_refresh_sound_length_recursive(scene, &scene->ed->seqbase);
+ }
+#else
+ (void)scene;
+#endif
+}
+
void BKE_sequencer_update_sound_bounds_all(Scene *scene)
{
Editing *ed = scene->ed;
@@ -3954,6 +4013,29 @@ Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, int recu
return NULL;
}
+/**
+ * Only use as last resort when the StripElem is available but no the Sequence.
+ * (needed for RNA)
+ */
+Sequence *BKE_sequencer_from_elem(ListBase *seqbase, StripElem *se)
+{
+ Sequence *iseq;
+
+ for (iseq = seqbase->first; iseq; iseq = iseq->next) {
+ Sequence *seq_found;
+ if ((iseq->strip && iseq->strip->stripdata) &&
+ (ARRAY_HAS_ITEM(se, iseq->strip->stripdata, iseq->len)))
+ {
+ break;
+ }
+ else if ((seq_found = BKE_sequencer_from_elem(&iseq->seqbase, se))) {
+ iseq = seq_found;
+ break;
+ }
+ }
+
+ return iseq;
+}
Sequence *BKE_sequencer_active_get(Scene *scene)
{
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index b9843ad0619..5c9c564998e 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -198,10 +198,10 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
* MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored)
* MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored)
*/
-int normal_projection_project_vertex(char options, const float vert[3], const float dir[3],
- const SpaceTransform *transf,
- BVHTree *tree, BVHTreeRayHit *hit,
- BVHTree_RayCastCallback callback, void *userdata)
+int BKE_shrinkwrap_project_normal(char options, const float vert[3],
+ const float dir[3], const SpaceTransform *transf,
+ BVHTree *tree, BVHTreeRayHit *hit,
+ BVHTree_RayCastCallback callback, void *userdata)
{
/* don't use this because this dist value could be incompatible
* this value used by the callback for comparing prev/new dist values.
@@ -368,14 +368,14 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
if (use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) {
if (auxData.tree) {
- normal_projection_project_vertex(0, tmp_co, tmp_no,
- &local2aux, auxData.tree, &hit,
- auxData.raycast_callback, &auxData);
+ BKE_shrinkwrap_project_normal(0, tmp_co, tmp_no,
+ &local2aux, auxData.tree, &hit,
+ auxData.raycast_callback, &auxData);
}
- normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no,
- &calc->local2target, treeData.tree, &hit,
- treeData.raycast_callback, &treeData);
+ BKE_shrinkwrap_project_normal(calc->smd->shrinkOpts, tmp_co, tmp_no,
+ &calc->local2target, treeData.tree, &hit,
+ treeData.raycast_callback, &treeData);
}
/* Project over negative direction of axis */
@@ -384,14 +384,14 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
negate_v3_v3(inv_no, tmp_no);
if (auxData.tree) {
- normal_projection_project_vertex(0, tmp_co, inv_no,
- &local2aux, auxData.tree, &hit,
- auxData.raycast_callback, &auxData);
+ BKE_shrinkwrap_project_normal(0, tmp_co, inv_no,
+ &local2aux, auxData.tree, &hit,
+ auxData.raycast_callback, &auxData);
}
- normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no,
- &calc->local2target, treeData.tree, &hit,
- treeData.raycast_callback, &treeData);
+ BKE_shrinkwrap_project_normal(calc->smd->shrinkOpts, tmp_co, inv_no,
+ &calc->local2target, treeData.tree, &hit,
+ treeData.raycast_callback, &treeData);
}
/* don't set the initial dist (which is more efficient),
@@ -506,7 +506,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
DerivedMesh *ss_mesh = NULL;
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
- /* remove loop dependencies on derived meshs (TODO should this be done elsewhere?) */
+ /* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) */
if (smd->target == ob) smd->target = NULL;
if (smd->auxTarget == ob) smd->auxTarget = NULL;
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index bb65955e3b5..fb0e22abf2a 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -1142,8 +1142,8 @@ static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_mult
/* values */
output->influence[index_out] = em1.influence[index_in];
- if (output->velocity) {
- output->velocity[index_out] = em1.velocity[index_in];
+ if (output->velocity && em1.velocity) {
+ copy_v3_v3(&output->velocity[index_out * 3], &em1.velocity[index_in * 3]);
}
}
@@ -1160,9 +1160,11 @@ static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_mult
else {
output->influence[index_out] = MAX2(em2->influence[index_in], output->influence[index_out]);
}
- if (output->velocity) {
+ if (output->velocity && em2->velocity) {
/* last sample replaces the velocity */
- output->velocity[index_out] = ADD_IF_LOWER(output->velocity[index_out], em2->velocity[index_in]);
+ output->velocity[index_out * 3] = ADD_IF_LOWER(output->velocity[index_out * 3], em2->velocity[index_in * 3]);
+ output->velocity[index_out * 3 + 1] = ADD_IF_LOWER(output->velocity[index_out * 3 + 1], em2->velocity[index_in * 3 + 1]);
+ output->velocity[index_out * 3 + 2] = ADD_IF_LOWER(output->velocity[index_out * 3 + 2], em2->velocity[index_in * 3 + 2]);
}
}
} // low res loop
@@ -2384,6 +2386,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
if (effectors)
{
float *density = smoke_get_density(sds->fluid);
+ float *fuel = smoke_get_fuel(sds->fluid);
float *force_x = smoke_get_force_x(sds->fluid);
float *force_y = smoke_get_force_y(sds->fluid);
float *force_z = smoke_get_force_z(sds->fluid);
@@ -2406,7 +2409,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
float voxelCenter[3] = {0, 0, 0}, vel[3] = {0, 0, 0}, retvel[3] = {0, 0, 0};
unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z);
- if ((density[index] < FLT_EPSILON) || obstacle[index])
+ if (((fuel ? MAX2(density[index], fuel[index]) : density[index]) < FLT_EPSILON) || obstacle[index])
continue;
vel[0] = velocity_x[index];
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 2f8eb7d9931..3910ef5cb69 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -427,6 +427,8 @@ void sound_update_fps(struct Scene *scene)
{
if (scene->sound_scene)
AUD_setSequencerFPS(scene->sound_scene, FPS);
+
+ BKE_sequencer_refresh_sound_length(scene);
}
void sound_update_scene_listener(struct Scene *scene)
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 35482d9553d..0de4541f9a3 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -298,7 +298,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
CCGVertHDL *fverts = NULL;
BLI_array_declare(fverts);
#endif
- EdgeHash *ehash;
+ EdgeSet *eset;
float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
@@ -334,7 +334,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
}
/* create edges */
- ehash = BLI_edgehash_new();
+ eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface));
for (i = 0; i < totface; i++) {
MPoly *mp = &((MPoly *) mpoly)[i];
@@ -359,7 +359,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
MVert *mv0 = mvert + (ml[j_next].v);
MVert *mv1 = mvert + (ml[j].v);
- if (!BLI_edgehash_haskey(ehash, v0, v1)) {
+ if (BLI_edgeset_reinsert(eset, v0, v1)) {
CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next);
CCGEdgeHDL ehdl = SET_INT_IN_POINTER(mp->loopstart + j_next);
float crease;
@@ -370,12 +370,11 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
crease = ccgSubSurf_getEdgeCrease(orige);
ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e);
- BLI_edgehash_insert(ehash, v0, v1, NULL);
}
}
}
- BLI_edgehash_free(ehash, NULL);
+ BLI_edgeset_free(eset);
/* create faces */
for (i = 0; i < totface; i++) {
@@ -1065,8 +1064,8 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
for (j = 0; j < mpoly[i].totloop; j++) {
const MDisps *md = &mdisps[mpoly[i].loopstart + j];
- int hidden_gridsize = ccg_gridsize(md->level);
- int factor = ccg_factor(level, md->level);
+ int hidden_gridsize = BKE_ccg_gridsize(md->level);
+ int factor = BKE_ccg_factor(level, md->level);
if (!md->hidden)
continue;
@@ -1108,8 +1107,8 @@ void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly,
if (!gpm->data)
continue;
- factor = ccg_factor(level, gpm->level);
- gpm_gridsize = ccg_gridsize(gpm->level);
+ factor = BKE_ccg_factor(level, gpm->level);
+ gpm_gridsize = BKE_ccg_gridsize(gpm->level);
for (y = 0; y < gridSize; y++) {
for (x = 0; x < gridSize; x++) {
@@ -1332,7 +1331,7 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
if (!ccgdm->ehash) {
MEdge *medge;
- ccgdm->ehash = BLI_edgehash_new();
+ ccgdm->ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData);
medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm);
for (i = 0; i < ccgdm->dm.numEdgeData; i++) {
@@ -3190,8 +3189,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.getVert = ccgDM_getFinalVert;
ccgdm->dm.getEdge = ccgDM_getFinalEdge;
ccgdm->dm.getTessFace = ccgDM_getFinalFace;
+
ccgdm->dm.getVertCo = ccgDM_getFinalVertCo;
ccgdm->dm.getVertNo = ccgDM_getFinalVertNo;
+
ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
@@ -3217,11 +3218,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
ccgdm->dm.getPolyMap = ccgDM_getPolyMap;
ccgdm->dm.getPBVH = ccgDM_getPBVH;
- ccgdm->dm.getTessFace = ccgDM_getFinalFace;
- ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
- ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
- ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
-
ccgdm->dm.calcNormals = ccgDM_calcNormals;
ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
@@ -3577,6 +3573,8 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
CCGDerivedMesh *result;
+ /* note: editmode calculation can only run once per
+ * modifier stack evaluation (uses freed cache) [#36299] */
if (flags & SUBSURF_FOR_EDIT_MODE) {
int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index f0c01e25598..be43aae1ed3 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1151,17 +1151,26 @@ void txt_pop_sel(Text *text)
text->selc = text->curc;
}
-void txt_order_cursors(Text *text)
+void txt_order_cursors(Text *text, const bool reverse)
{
if (!text) return;
if (!text->curl) return;
if (!text->sell) return;
- /* Flip so text->curl is before text->sell */
- if ((txt_get_span(text->curl, text->sell) < 0) ||
- (text->curl == text->sell && text->curc > text->selc))
- {
- txt_curs_swap(text);
+ /* Flip so text->curl is before/after text->sell */
+ if (reverse == false) {
+ if ((txt_get_span(text->curl, text->sell) < 0) ||
+ (text->curl == text->sell && text->curc > text->selc))
+ {
+ txt_curs_swap(text);
+ }
+ }
+ else {
+ if ((txt_get_span(text->curl, text->sell) > 0) ||
+ (text->curl == text->sell && text->curc < text->selc))
+ {
+ txt_curs_swap(text);
+ }
}
}
@@ -1181,7 +1190,7 @@ static void txt_delete_sel(Text *text)
if (!txt_has_sel(text)) return;
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
if (!undoing) {
buf = txt_sel_to_buf(text);
@@ -1305,7 +1314,7 @@ int txt_find_string(Text *text, const char *findstr, int wrap, int match_case)
if (!text || !text->curl || !text->sell) return 0;
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
tl = startl = text->sell;
@@ -1938,6 +1947,7 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s
void txt_do_undo(Text *text)
{
int op = text->undo_buf[text->undo_pos];
+ int prev_flags;
unsigned int linep, i;
unsigned int uchar;
unsigned int curln, selln;
@@ -2061,8 +2071,14 @@ void txt_do_undo(Text *text)
txt_move_to(text, selln, selc, 1);
if ((curln == selln) && (curc == selc)) {
+ /* disable tabs to spaces since moving right may involve skipping multiple spaces */
+ prev_flags = text->flags;
+ text->flags &= ~TXT_TABSTOSPACES;
+
for (i = 0; i < linep; i++)
txt_move_right(text, 1);
+
+ text->flags = prev_flags;
}
txt_delete_selected(text);
@@ -2833,7 +2849,7 @@ void txt_move_lines(struct Text *text, const int direction)
if (!text || !text->curl || !text->sell) return;
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
line_other = (direction == TXT_MOVE_LINE_DOWN) ? text->sell->next : text->curl->prev;
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index e2b7358525a..22b0fe7bc24 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -71,16 +71,16 @@
/* ****************** Mapping ******************* */
-TexMapping *add_tex_mapping(void)
+TexMapping *add_tex_mapping(int type)
{
TexMapping *texmap = MEM_callocN(sizeof(TexMapping), "TexMapping");
- default_tex_mapping(texmap);
+ default_tex_mapping(texmap, type);
return texmap;
}
-void default_tex_mapping(TexMapping *texmap)
+void default_tex_mapping(TexMapping *texmap, int type)
{
memset(texmap, 0, sizeof(TexMapping));
@@ -92,11 +92,12 @@ void default_tex_mapping(TexMapping *texmap)
texmap->projy = PROJ_Y;
texmap->projz = PROJ_Z;
texmap->mapping = MTEX_FLAT;
+ texmap->type = type;
}
void init_tex_mapping(TexMapping *texmap)
{
- float smat[3][3], rmat[3][3], mat[3][3], proj[3][3];
+ float smat[4][4], rmat[4][4], tmat[4][4], proj[4][4], size[3];
if (texmap->projx == PROJ_X && texmap->projy == PROJ_Y && texmap->projz == PROJ_Z &&
is_zero_v3(texmap->loc) && is_zero_v3(texmap->rot) && is_one_v3(texmap->size))
@@ -107,7 +108,8 @@ void init_tex_mapping(TexMapping *texmap)
}
else {
/* axis projection */
- zero_m3(proj);
+ zero_m4(proj);
+ proj[3][3] = 1.0f;
if (texmap->projx != PROJ_N)
proj[texmap->projx - 1][0] = 1.0f;
@@ -117,19 +119,50 @@ void init_tex_mapping(TexMapping *texmap)
proj[texmap->projz - 1][2] = 1.0f;
/* scale */
- size_to_mat3(smat, texmap->size);
+ copy_v3_v3(size, texmap->size);
+
+ if (ELEM(texmap->type, TEXMAP_TYPE_TEXTURE, TEXMAP_TYPE_NORMAL)) {
+ /* keep matrix invertible */
+ if (fabsf(size[0]) < 1e-5f)
+ size[0] = signf(size[0]) * 1e-5f;
+ if (fabsf(size[1]) < 1e-5f)
+ size[1] = signf(size[1]) * 1e-5f;
+ if (fabsf(size[2]) < 1e-5f)
+ size[2] = signf(size[2]) * 1e-5f;
+ }
+ size_to_mat4(smat, texmap->size);
+
/* rotation */
- /* TexMapping rotation are now in radians. */
- eul_to_mat3(rmat, texmap->rot);
-
- /* compose it all */
- mul_m3_m3m3(mat, rmat, smat);
- mul_m3_m3m3(mat, proj, mat);
-
+ eul_to_mat4(rmat, texmap->rot);
+
/* translation */
- copy_m4_m3(texmap->mat, mat);
- copy_v3_v3(texmap->mat[3], texmap->loc);
+ unit_m4(tmat);
+ copy_v3_v3(tmat[3], texmap->loc);
+
+ if (texmap->type == TEXMAP_TYPE_TEXTURE) {
+ /* to transform a texture, the inverse transform needs
+ * to be applied to the texture coordinate */
+ mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ invert_m4(texmap->mat);
+ }
+ else if (texmap->type == TEXMAP_TYPE_POINT) {
+ /* forward transform */
+ mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ }
+ else if (texmap->type == TEXMAP_TYPE_VECTOR) {
+ /* no translation for vectors */
+ mul_m4_m4m4(texmap->mat, rmat, smat);
+ }
+ else if (texmap->type == TEXMAP_TYPE_NORMAL) {
+ /* no translation for normals, and inverse transpose */
+ mul_m4_m4m4(texmap->mat, rmat, smat);
+ invert_m4(texmap->mat);
+ transpose_m4(texmap->mat);
+ }
+
+ /* projection last */
+ mul_m4_m4m4(texmap->mat, texmap->mat, proj);
texmap->flag &= ~TEXMAP_UNIT_MATRIX;
}
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 4c363292898..b8711f6e5f6 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -103,6 +103,18 @@ static void tracking_tracks_free(ListBase *tracks)
BLI_freelistN(tracks);
}
+/* Free the whole list of plane tracks, list's head and tail are set to NULL. */
+static void tracking_plane_tracks_free(ListBase *plane_tracks)
+{
+ MovieTrackingPlaneTrack *plane_track;
+
+ for (plane_track = plane_tracks->first; plane_track; plane_track = plane_track->next) {
+ BKE_tracking_plane_track_free(plane_track);
+ }
+
+ BLI_freelistN(plane_tracks);
+}
+
/* Free reconstruction structures, only frees contents of a structure,
* (if structure is allocated in heap, it shall be handled outside).
*
@@ -122,6 +134,7 @@ static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruc
static void tracking_object_free(MovieTrackingObject *object)
{
tracking_tracks_free(&object->tracks);
+ tracking_plane_tracks_free(&object->plane_tracks);
tracking_reconstruction_free(&object->reconstruction);
}
@@ -173,6 +186,7 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
void BKE_tracking_free(MovieTracking *tracking)
{
tracking_tracks_free(&tracking->tracks);
+ tracking_plane_tracks_free(&tracking->plane_tracks);
tracking_reconstruction_free(&tracking->reconstruction);
tracking_objects_free(&tracking->objects);
@@ -198,7 +212,7 @@ void BKE_tracking_settings_init(MovieTracking *tracking)
tracking->settings.default_algorithm_flag |= TRACK_ALGORITHM_FLAG_USE_BRUTE;
tracking->settings.dist = 1;
tracking->settings.object_distance = 1;
- tracking->settings.reconstruction_success_threshold = 1e-3;
+ tracking->settings.reconstruction_success_threshold = 1e-3f;
tracking->stabilization.scaleinf = 1.0f;
tracking->stabilization.locinf = 1.0f;
@@ -221,6 +235,18 @@ ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
return &tracking->tracks;
}
+/* Get list base of active object's plane tracks. */
+ListBase *BKE_tracking_get_active_plane_tracks(MovieTracking *tracking)
+{
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+
+ if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+ return &object->plane_tracks;
+ }
+
+ return &tracking->plane_tracks;
+}
+
/* Get reconstruction data of active object. */
MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking)
{
@@ -475,7 +501,7 @@ void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingOb
}
/* Check whether there're any tracks in the clipboard. */
-int BKE_tracking_clipboard_has_tracks(void)
+bool BKE_tracking_clipboard_has_tracks(void)
{
return tracking_clipboard.tracks.first != NULL;
}
@@ -652,7 +678,7 @@ void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag
*
* NOTE: frame number should be in clip space, not scene space.
*/
-int BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr)
+bool BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr)
{
return BKE_tracking_marker_get_exact(track, framenr) != NULL;
}
@@ -661,7 +687,7 @@ int BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framen
*
* NOTE: frame number should be in clip space, not scene space.
*/
-int BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr)
+bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr)
{
MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
@@ -996,7 +1022,7 @@ float *BKE_tracking_track_get_mask(int frame_width, int frame_height,
}
/* area - which part of marker should be selected. see TRACK_AREA_* constants */
-void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend)
+void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, bool extend)
{
if (extend) {
BKE_tracking_track_flag_set(track, area, SELECT);
@@ -1025,6 +1051,17 @@ void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area)
BKE_tracking_track_flag_clear(track, area, SELECT);
}
+void BKE_tracking_tracks_deselect_all(ListBase *tracksbase)
+{
+ MovieTrackingTrack *track;
+
+ for (track = tracksbase->first; track; track = track->next) {
+ if ((track->flag & TRACK_HIDDEN) == 0) {
+ BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+ }
+ }
+}
+
/*********************** Marker *************************/
MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker)
@@ -1264,6 +1301,296 @@ void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float
add_v2_v2(pos, track->offset);
}
+/*********************** Plane Track *************************/
+
+/* Creates new plane track out of selected point tracks */
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, ListBase *plane_tracks_base,
+ ListBase *tracks, int framenr)
+{
+ MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingPlaneMarker plane_marker;
+ MovieTrackingTrack *track;
+ float tracks_min[2], tracks_max[2];
+ int track_index, num_selected_tracks = 0;
+
+ (void) tracking; /* Ignored. */
+
+ /* Use bounding box of selected markers as an initial size of plane. */
+ INIT_MINMAX2(tracks_min, tracks_max);
+ for (track = tracks->first; track; track = track->next) {
+ if (TRACK_SELECTED(track)) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ float pattern_min[2], pattern_max[2];
+ BKE_tracking_marker_pattern_minmax(marker, pattern_min, pattern_max);
+ add_v2_v2(pattern_min, marker->pos);
+ add_v2_v2(pattern_max, marker->pos);
+ minmax_v2v2_v2(tracks_min, tracks_max, pattern_min);
+ minmax_v2v2_v2(tracks_min, tracks_max, pattern_max);
+ num_selected_tracks++;
+ }
+ }
+
+ if (num_selected_tracks < 4) {
+ return NULL;
+ }
+
+ /* Allocate new plane track. */
+ plane_track = MEM_callocN(sizeof(MovieTrackingPlaneTrack), "new plane track");
+
+ /* Use some default name. */
+ strcpy(plane_track->name, "Plane Track");
+
+ /* Use selected tracks from given list as a plane. */
+ plane_track->point_tracks = MEM_mallocN(sizeof(MovieTrackingTrack *) * num_selected_tracks, "new plane tracks array");
+ for (track = tracks->first, track_index = 0; track; track = track->next) {
+ if (TRACK_SELECTED(track)) {
+ plane_track->point_tracks[track_index] = track;
+ track_index++;
+ }
+ }
+ plane_track->point_tracksnr = num_selected_tracks;
+
+ /* Setup new plane marker and add it to the track. */
+ plane_marker.framenr = framenr;
+ plane_marker.flag = 0;
+
+ copy_v2_v2(plane_marker.corners[0], tracks_min);
+ copy_v2_v2(plane_marker.corners[2], tracks_max);
+
+ plane_marker.corners[1][0] = tracks_max[0];
+ plane_marker.corners[1][1] = tracks_min[1];
+ plane_marker.corners[3][0] = tracks_min[0];
+ plane_marker.corners[3][1] = tracks_max[1];
+
+ BKE_tracking_plane_marker_insert(plane_track, &plane_marker);
+
+ /* Put new plane track to the list, ensure it's name is unique. */
+ BLI_addtail(plane_tracks_base, plane_track);
+ BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
+
+ return plane_track;
+}
+
+void BKE_tracking_plane_track_unique_name(ListBase *plane_tracks_base, MovieTrackingPlaneTrack *plane_track)
+{
+ BLI_uniquename(plane_tracks_base, plane_track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Plane Track"), '.',
+ offsetof(MovieTrackingPlaneTrack, name), sizeof(plane_track->name));
+}
+
+/* Free specified plane track, only frees contents of a structure
+ * (if track is allocated in heap, it shall be handled outside).
+ *
+ * All the pointers inside track becomes invalid after this call.
+ */
+void BKE_tracking_plane_track_free(MovieTrackingPlaneTrack *plane_track)
+{
+ if (plane_track->markers) {
+ MEM_freeN(plane_track->markers);
+ }
+
+ MEM_freeN(plane_track->point_tracks);
+}
+
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *tracking,
+ MovieTrackingObject *object,
+ const char *name)
+{
+ ListBase *plane_tracks_base = BKE_tracking_object_get_plane_tracks(tracking, object);
+ MovieTrackingPlaneTrack *plane_track;
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (!strcmp(plane_track->name, name)) {
+ return plane_track;
+ }
+ }
+
+ return NULL;
+}
+
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking)
+{
+ ListBase *plane_tracks_base;
+
+ if (tracking->act_plane_track == NULL) {
+ return NULL;
+ }
+
+ plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+
+ /* Check that active track is in current plane tracks list */
+ if (BLI_findindex(plane_tracks_base, tracking->act_plane_track) >= 0) {
+ return tracking->act_plane_track;
+ }
+
+ return NULL;
+}
+
+void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
+{
+ MovieTrackingPlaneTrack *plane_track;
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ plane_track->flag &= ~SELECT;
+ }
+}
+
+/*********************** Plane Marker *************************/
+
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker)
+{
+ MovieTrackingPlaneMarker *old_plane_marker = NULL;
+
+ if (plane_track->markersnr)
+ old_plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, plane_marker->framenr);
+
+ if (old_plane_marker) {
+ /* Simply replace settings in existing marker. */
+ *old_plane_marker = *plane_marker;
+
+ return old_plane_marker;
+ }
+ else {
+ int a = plane_track->markersnr;
+
+ /* Find position in array where to add new marker. */
+ /* TODO(sergey): we coud use bisect to speed things up. */
+ while (a--) {
+ if (plane_track->markers[a].framenr < plane_marker->framenr) {
+ break;
+ }
+ }
+
+ plane_track->markersnr++;
+ plane_track->markers = MEM_reallocN(plane_track->markers,
+ sizeof(MovieTrackingPlaneMarker) * plane_track->markersnr);
+
+ /* Shift array to "free" space for new marker. */
+ memmove(plane_track->markers + a + 2, plane_track->markers + a + 1,
+ (plane_track->markersnr - a - 2) * sizeof(MovieTrackingPlaneMarker));
+
+ /* Put new marker to an array. */
+ plane_track->markers[a + 1] = *plane_marker;
+ plane_track->last_marker = a + 1;
+
+ return &plane_track->markers[a + 1];
+ }
+}
+
+void BKE_tracking_plane_marker_delete(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+ int a = 0;
+
+ while (a < plane_track->markersnr) {
+ if (plane_track->markers[a].framenr == framenr) {
+ if (plane_track->markersnr > 1) {
+ memmove(plane_track->markers + a, plane_track->markers + a + 1,
+ (plane_track->markersnr - a - 1) * sizeof(MovieTrackingPlaneMarker));
+ plane_track->markersnr--;
+ plane_track->markers = MEM_reallocN(plane_track->markers,
+ sizeof(MovieTrackingMarker) * plane_track->markersnr);
+ }
+ else {
+ MEM_freeN(plane_track->markers);
+ plane_track->markers = NULL;
+ plane_track->markersnr = 0;
+ }
+
+ break;
+ }
+
+ a++;
+ }
+}
+
+/* TODO(sergey): The next couple of functions are really quite the same as point marker version,
+ * would be nice to de-duplicate them somehow..
+ */
+
+/* Get a plane marker at given frame,
+ * If there's no such marker, closest one from the left side will be returned.
+ */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+ int a = plane_track->markersnr - 1;
+
+ if (!plane_track->markersnr)
+ return NULL;
+
+ /* Approximate pre-first framenr marker with first marker. */
+ if (framenr < plane_track->markers[0].framenr) {
+ return &plane_track->markers[0];
+ }
+
+ if (plane_track->last_marker < plane_track->markersnr) {
+ a = plane_track->last_marker;
+ }
+
+ if (plane_track->markers[a].framenr <= framenr) {
+ while (a < plane_track->markersnr && plane_track->markers[a].framenr <= framenr) {
+ if (plane_track->markers[a].framenr == framenr) {
+ plane_track->last_marker = a;
+
+ return &plane_track->markers[a];
+ }
+ a++;
+ }
+
+ /* If there's no marker for exact position, use nearest marker from left side. */
+ return &plane_track->markers[a - 1];
+ }
+ else {
+ while (a >= 0 && plane_track->markers[a].framenr >= framenr) {
+ if (plane_track->markers[a].framenr == framenr) {
+ plane_track->last_marker = a;
+
+ return &plane_track->markers[a];
+ }
+
+ a--;
+ }
+
+ /* If there's no marker for exact position, use nearest marker from left side. */
+ return &plane_track->markers[a];
+ }
+
+ return NULL;
+}
+
+/* Get a plane marker at exact given frame, if there's no marker at the frame,
+ * NULL will be returned.
+ */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+ if (plane_marker->framenr != framenr) {
+ return NULL;
+ }
+
+ return plane_marker;
+}
+
+/* Ensure there's a marker for the given frame. */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+ if (plane_marker->framenr != framenr) {
+ MovieTrackingPlaneMarker plane_marker_new;
+
+ plane_marker_new = *plane_marker;
+ plane_marker_new.framenr = framenr;
+
+ plane_marker = BKE_tracking_plane_marker_insert(plane_track, &plane_marker_new);
+ }
+
+ return plane_marker;
+}
+
/*********************** Object *************************/
MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name)
@@ -1295,17 +1622,17 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char
return object;
}
-int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object)
+bool BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object)
{
MovieTrackingTrack *track;
int index = BLI_findindex(&tracking->objects, object);
if (index == -1)
- return FALSE;
+ return false;
if (object->flag & TRACKING_OBJECT_CAMERA) {
/* object used for camera solving can't be deleted */
- return FALSE;
+ return false;
}
track = object->tracks.first;
@@ -1328,7 +1655,7 @@ int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *obj
BKE_tracking_dopesheet_tag_update(tracking);
- return TRUE;
+ return true;
}
void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
@@ -1379,6 +1706,15 @@ ListBase *BKE_tracking_object_get_tracks(MovieTracking *tracking, MovieTrackingO
return &object->tracks;
}
+ListBase *BKE_tracking_object_get_plane_tracks(MovieTracking *tracking, MovieTrackingObject *object)
+{
+ if (object->flag & TRACKING_OBJECT_CAMERA) {
+ return &tracking->plane_tracks;
+ }
+
+ return &object->plane_tracks;
+}
+
MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(MovieTracking *tracking,
MovieTrackingObject *object)
{
@@ -1550,7 +1886,7 @@ static void cameraIntrinscisOptionsFromTracking(libmv_CameraIntrinsicsOptions *c
camera_intrinsics_options->k3 = camera->k3;
camera_intrinsics_options->image_width = calibration_width;
- camera_intrinsics_options->image_height = (double) (calibration_height * aspy);
+ camera_intrinsics_options->image_height = (int) (calibration_height * aspy);
}
MovieDistortion *BKE_tracking_distortion_new(void)
@@ -1592,7 +1928,7 @@ MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
}
ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, ImBuf *ibuf,
- int calibration_width, int calibration_height, float overscan, int undistort)
+ int calibration_width, int calibration_height, float overscan, bool undistort)
{
ImBuf *resibuf;
@@ -1684,7 +2020,7 @@ ImBuf *BKE_tracking_undistort_frame(MovieTracking *tracking, ImBuf *ibuf, int ca
camera->intrinsics = BKE_tracking_distortion_new();
return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width,
- calibration_height, overscan, TRUE);
+ calibration_height, overscan, true);
}
ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width,
@@ -1696,7 +2032,7 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int cali
camera->intrinsics = BKE_tracking_distortion_new();
return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width,
- calibration_height, overscan, FALSE);
+ calibration_height, overscan, false);
}
void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2])
@@ -1717,8 +2053,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r
BKE_tracking_undistort_v2(tracking, pos, warped_pos);
- delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
- delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+ delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
/* top edge */
pos[0] = a;
@@ -1726,8 +2062,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r
BKE_tracking_undistort_v2(tracking, pos, warped_pos);
- delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
- delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+ delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
if (a >= rect->xmax)
break;
@@ -1743,8 +2079,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r
BKE_tracking_undistort_v2(tracking, pos, warped_pos);
- delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
- delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+ delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
/* right edge */
pos[0] = rect->xmax;
@@ -1752,8 +2088,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r
BKE_tracking_undistort_v2(tracking, pos, warped_pos);
- delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
- delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+ delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
if (a >= rect->ymax)
break;
@@ -1762,7 +2098,7 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r
/*********************** Image sampling *************************/
-static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
+static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, bool grayscale)
{
BKE_tracking_disable_channels(ibuf, track->flag & TRACK_DISABLE_RED,
track->flag & TRACK_DISABLE_GREEN,
@@ -1771,7 +2107,7 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g
ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf,
MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int from_anchor, int use_mask, int num_samples_x, int num_samples_y,
+ bool from_anchor, bool use_mask, int num_samples_x, int num_samples_y,
float pos[2])
{
ImBuf *pattern_ibuf;
@@ -1834,7 +2170,7 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea
}
ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int anchored, int disable_channels)
+ bool anchored, bool disable_channels)
{
ImBuf *pattern_ibuf, *search_ibuf;
float pat_min[2], pat_max[2];
@@ -1849,7 +2185,7 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo
if (search_ibuf) {
pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker,
- anchored, FALSE, num_samples_x, num_samples_y, NULL);
+ anchored, false, num_samples_x, num_samples_y, NULL);
IMB_freeImBuf(search_ibuf);
}
@@ -1861,7 +2197,7 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo
}
ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int anchored, int disable_channels)
+ bool anchored, bool disable_channels)
{
ImBuf *searchibuf;
int x, y, w, h;
@@ -1893,7 +2229,7 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov
(track->flag & TRACK_DISABLE_GREEN) ||
(track->flag & TRACK_DISABLE_BLUE))
{
- disable_imbuf_channels(searchibuf, track, TRUE);
+ disable_imbuf_channels(searchibuf, track, true);
}
}
@@ -1904,8 +2240,8 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov
* better tracks sometimes. however, instead of simply zeroing the channels
* out, do a partial grayscale conversion so the display is better.
*/
-void BKE_tracking_disable_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue,
- int grayscale)
+void BKE_tracking_disable_channels(ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue,
+ bool grayscale)
{
int x, y;
float scale;
@@ -1969,7 +2305,7 @@ void BKE_tracking_disable_channels(ImBuf *ibuf, int disable_red, int disable_gre
typedef struct TracksMap {
char object_name[MAX_NAME];
- int is_camera;
+ bool is_camera;
int num_tracks;
int customdata_size;
@@ -1982,7 +2318,7 @@ typedef struct TracksMap {
int ptr;
} TracksMap;
-static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
+static TracksMap *tracks_map_new(const char *object_name, bool is_camera, int num_tracks, int customdata_size)
{
TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap");
@@ -2034,8 +2370,6 @@ static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *c
static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
{
MovieTrackingTrack *track;
- MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingTrack *rot_track = tracking->stabilization.rot_track;
ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
ListBase *old_tracks;
int a;
@@ -2059,61 +2393,49 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
* of currently operating tracks (if needed)
*/
for (a = 0; a < map->num_tracks; a++) {
- int replace_sel = 0, replace_rot = 0;
- MovieTrackingTrack *new_track, *old;
+ MovieTrackingTrack *old_track;
+ bool mapped_to_old = false;
track = &map->tracks[a];
/* find original of operating track in list of previously displayed tracks */
- old = BLI_ghash_lookup(map->hash, track);
- if (old) {
- MovieTrackingTrack *cur = old_tracks->first;
-
- while (cur) {
- if (cur == old)
- break;
+ old_track = BLI_ghash_lookup(map->hash, track);
+ if (old_track) {
+ if (BLI_findindex(old_tracks, old_track) != -1) {
+ BLI_remlink(old_tracks, old_track);
- cur = cur->next;
- }
+ /* Copy flags like selection back to the track map. */
+ track->flag = old_track->flag;
+ track->pat_flag = old_track->pat_flag;
+ track->search_flag = old_track->search_flag;
- /* original track was found, re-use flags and remove this track */
- if (cur) {
- if (cur == act_track)
- replace_sel = 1;
- if (cur == rot_track)
- replace_rot = 1;
+ /* Copy all the rest settings back from the map to the actual tracks. */
+ MEM_freeN(old_track->markers);
+ *old_track = *track;
+ old_track->markers = MEM_dupallocN(old_track->markers);
- track->flag = cur->flag;
- track->pat_flag = cur->pat_flag;
- track->search_flag = cur->search_flag;
+ BLI_addtail(&tracks, old_track);
- BKE_tracking_track_free(cur);
- BLI_freelinkN(old_tracks, cur);
+ mapped_to_old = true;
}
}
- new_track = tracking_track_duplicate(track);
-
- BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */
- BLI_ghash_insert(map->hash, track, new_track);
-
- if (replace_sel) /* update current selection in clip */
- tracking->act_track = new_track;
+ if (mapped_to_old == false) {
+ MovieTrackingTrack *new_track = tracking_track_duplicate(track);
- if (replace_rot) /* update track used for rotation stabilization */
- tracking->stabilization.rot_track = new_track;
+ /* Update old-new track mapping */
+ BLI_ghash_remove(map->hash, track, NULL, NULL);
+ BLI_ghash_insert(map->hash, track, new_track);
- BLI_addtail(&tracks, new_track);
+ BLI_addtail(&tracks, new_track);
+ }
}
/* move all tracks, which aren't operating */
track = old_tracks->first;
while (track) {
MovieTrackingTrack *next = track->next;
-
- track->next = track->prev = NULL;
BLI_addtail(&new_tracks, track);
-
track = next;
}
@@ -2176,13 +2498,13 @@ typedef struct MovieTrackingContext {
MovieClip *clip;
int clip_flag;
- int frames;
+ int frames, first_frame;
bool first_time;
MovieTrackingSettings settings;
TracksMap *tracks_map;
- short backwards, sequence;
+ bool backwards, sequence;
int sync_frame;
} MovieTrackingContext;
@@ -2216,6 +2538,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
context->backwards = backwards;
context->sync_frame = user->framenr;
context->first_time = true;
+ context->first_frame = user->framenr;
context->sequence = sequence;
/* count */
@@ -2355,7 +2678,7 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track,
float *gray_pixels;
int width, height;
- searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE);
+ searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, false, true);
if (!searchibuf) {
*width_r = 0;
@@ -2528,7 +2851,7 @@ static bool track_context_update_reference(MovieTrackingContext *context, TrackC
}
/* Fill in libmv tracker options structure with settings need to be used to perform track. */
-static void tracking_configure_tracker(MovieTrackingTrack *track, float *mask,
+static void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
libmv_TrackRegionOptions *options)
{
options->motion_model = track->motion_model;
@@ -2551,19 +2874,24 @@ static void tracking_configure_tracker(MovieTrackingTrack *track, float *mask,
static bool tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker,
int frame_width, int frame_height)
{
- float pat_min[2], pat_max[2], dim[2], margin[2];
+ float pat_min[2], pat_max[2];
+ float margin_left, margin_top, margin_right, margin_bottom;
+ float normalized_track_margin[2];
/* margin from frame boundaries */
BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
- sub_v2_v2v2(dim, pat_max, pat_min);
- margin[0] = margin[1] = max_ff(dim[0], dim[1]) / 2.0f;
- margin[0] = max_ff(margin[0], (float)track->margin / frame_width);
- margin[1] = max_ff(margin[1], (float)track->margin / frame_height);
+ normalized_track_margin[0] = (float)track->margin / frame_width;
+ normalized_track_margin[1] = (float)track->margin / frame_height;
+
+ margin_left = max_ff(-pat_min[0], normalized_track_margin[0]);
+ margin_top = max_ff( pat_max[1], normalized_track_margin[1]);
+ margin_right = max_ff( pat_max[0], normalized_track_margin[0]);
+ margin_bottom = max_ff(-pat_min[1], normalized_track_margin[1]);
/* do not track markers which are too close to boundary */
- if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] ||
- marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1])
+ if (marker->pos[0] < margin_left || marker->pos[0] > 1.0f - margin_right ||
+ marker->pos[1] < margin_bottom || marker->pos[1] > 1.0f - margin_top)
{
return false;
}
@@ -2703,7 +3031,7 @@ static bool configure_and_run_tracker(ImBuf *destination_ibuf, MovieTrackingTrac
/* Track all the tracks from context one more frame,
* returns FALSe if nothing was tracked.
*/
-int BKE_tracking_context_step(MovieTrackingContext *context)
+bool BKE_tracking_context_step(MovieTrackingContext *context)
{
ImBuf *destination_ibuf;
int frame_delta = context->backwards ? -1 : 1;
@@ -2717,7 +3045,7 @@ int BKE_tracking_context_step(MovieTrackingContext *context)
/* Nothing to track, avoid unneeded frames reading to save time and memory. */
if (!map_size)
- return FALSE;
+ return false;
/* Get an image buffer for frame we're tracking to. */
context->user.framenr += frame_delta;
@@ -2725,7 +3053,7 @@ int BKE_tracking_context_step(MovieTrackingContext *context)
destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user,
context->clip_flag, MOVIECLIP_CACHE_SKIP);
if (!destination_ibuf)
- return FALSE;
+ return false;
frame_width = destination_ibuf->x;
frame_height = destination_ibuf->y;
@@ -2787,12 +3115,50 @@ int BKE_tracking_context_step(MovieTrackingContext *context)
return ok;
}
+void BKE_tracking_context_finish(MovieTrackingContext *context)
+{
+ MovieClip *clip = context->clip;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ MovieTrackingPlaneTrack *plane_track;
+ int map_size = tracks_map_get_size(context->tracks_map);
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ int i;
+ for (i = 0; i < map_size; i++) {
+ TrackContext *track_context = NULL;
+ MovieTrackingTrack *track, *old_track;
+ bool do_update = false;
+ int j;
+
+ tracks_map_get_indexed_element(context->tracks_map, i, &track, (void **)&track_context);
+
+ old_track = BLI_ghash_lookup(context->tracks_map->hash, track);
+ for (j = 0; j < plane_track->point_tracksnr; j++) {
+ if (plane_track->point_tracks[j] == old_track) {
+ do_update = true;
+ break;
+ }
+ }
+
+ if (do_update) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame);
+ break;
+ }
+ }
+ }
+ }
+}
+
/* Refine marker's position using previously known keyframe.
* Direction of searching for a keyframe depends on backwards flag,
* which means if backwards is false, previous keyframe will be as
* reference.
*/
-void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker, int backwards)
+void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker, bool backwards)
{
MovieTrackingMarker *reference_marker = NULL;
ImBuf *reference_ibuf, *destination_ibuf;
@@ -2810,7 +3176,7 @@ void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, Movi
BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
- /* Get an image buffer for reference frame, also gets referecnce marker.
+ /* Get an image buffer for reference frame, also gets reference marker.
*
* Usually tracking_context_get_reference_ibuf will return current frame
* if marker is keyframed, which is correct for normal tracking. But here
@@ -2863,18 +3229,238 @@ void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, Movi
IMB_freeImBuf(destination_ibuf);
}
+/*********************** Plane tracking *************************/
+
+typedef double Vec2[2];
+
+static int point_markers_correspondences_on_both_image(MovieTrackingPlaneTrack *plane_track, int frame1, int frame2,
+ Vec2 **x1_r, Vec2 **x2_r)
+{
+ int i, correspondence_index;
+ Vec2 *x1, *x2;
+
+ *x1_r = x1 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x1");
+ *x2_r = x2 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x2");
+
+ for (i = 0, correspondence_index = 0; i < plane_track->point_tracksnr; i++) {
+ MovieTrackingTrack *point_track = plane_track->point_tracks[i];
+ MovieTrackingMarker *point_marker1, *point_marker2;
+
+ point_marker1 = BKE_tracking_marker_get_exact(point_track, frame1);
+ point_marker2 = BKE_tracking_marker_get_exact(point_track, frame2);
+
+ if (point_marker1 != NULL && point_marker2 != NULL) {
+ /* Here conversion from float to double happens. */
+ x1[correspondence_index][0] = point_marker1->pos[0];
+ x1[correspondence_index][1] = point_marker1->pos[1];
+
+ x2[correspondence_index][0] = point_marker2->pos[0];
+ x2[correspondence_index][1] = point_marker2->pos[1];
+
+ correspondence_index++;
+ }
+ }
+
+ return correspondence_index;
+}
+
+/* TODO(sergey): Make it generic function available for everyone. */
+BLI_INLINE void mat3f_from_mat3d(float mat_float[3][3], double mat_double[3][3])
+{
+ /* Keep it stupid simple for better data flow in CPU. */
+ mat_float[0][0] = mat_double[0][0];
+ mat_float[0][1] = mat_double[0][1];
+ mat_float[0][2] = mat_double[0][2];
+
+ mat_float[1][0] = mat_double[1][0];
+ mat_float[1][1] = mat_double[1][1];
+ mat_float[1][2] = mat_double[1][2];
+
+ mat_float[2][0] = mat_double[2][0];
+ mat_float[2][1] = mat_double[2][1];
+ mat_float[2][2] = mat_double[2][2];
+}
+
+/* NOTE: frame number should be in clip space, not scene space */
+static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track, int start_frame,
+ int direction, bool retrack)
+{
+ MovieTrackingPlaneMarker *start_plane_marker = BKE_tracking_plane_marker_get(plane_track, start_frame);
+ MovieTrackingPlaneMarker *keyframe_plane_marker = NULL;
+ MovieTrackingPlaneMarker new_plane_marker;
+ int current_frame, frame_delta = direction > 0 ? 1 : -1;
+
+ if (plane_track->flag & PLANE_TRACK_AUTOKEY) {
+ /* Find a keyframe in given direction. */
+ for (current_frame = start_frame; ; current_frame += frame_delta) {
+ MovieTrackingPlaneMarker *next_plane_marker =
+ BKE_tracking_plane_marker_get_exact(plane_track, current_frame + frame_delta);
+
+ if (next_plane_marker == NULL) {
+ break;
+ }
+
+ if ((next_plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
+ keyframe_plane_marker = next_plane_marker;
+ break;
+ }
+ }
+ }
+ else {
+ start_plane_marker->flag |= PLANE_MARKER_TRACKED;
+ }
+
+ new_plane_marker = *start_plane_marker;
+ new_plane_marker.flag |= PLANE_MARKER_TRACKED;
+
+ for (current_frame = start_frame; ; current_frame += frame_delta) {
+ MovieTrackingPlaneMarker *next_plane_marker =
+ BKE_tracking_plane_marker_get_exact(plane_track, current_frame + frame_delta);
+ Vec2 *x1, *x2;
+ int i, num_correspondences;
+ double H_double[3][3];
+ float H[3][3];
+
+ /* As soon as we meet keyframed plane, we stop updating the sequence. */
+ if (next_plane_marker && (next_plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
+ /* Don't override keyframes if track is in auto-keyframe mode */
+ if (plane_track->flag & PLANE_TRACK_AUTOKEY) {
+ break;
+ }
+ }
+
+ num_correspondences =
+ point_markers_correspondences_on_both_image(plane_track, current_frame, current_frame + frame_delta,
+ &x1, &x2);
+
+ if (num_correspondences < 4) {
+ MEM_freeN(x1);
+ MEM_freeN(x2);
+
+ break;
+ }
+
+ libmv_homography2DFromCorrespondencesEuc(x1, x2, num_correspondences, H_double);
+
+ mat3f_from_mat3d(H, H_double);
+
+ for (i = 0; i < 4; i++) {
+ float vec[3] = {0.0f, 0.0f, 1.0f}, vec2[3];
+ copy_v2_v2(vec, new_plane_marker.corners[i]);
+
+ /* Apply homography */
+ mul_v3_m3v3(vec2, H, vec);
+
+ /* Normalize. */
+ vec2[0] /= vec2[2];
+ vec2[1] /= vec2[2];
+
+ copy_v2_v2(new_plane_marker.corners[i], vec2);
+ }
+
+ new_plane_marker.framenr = current_frame + frame_delta;
+
+ if (!retrack && keyframe_plane_marker &&
+ next_plane_marker &&
+ (plane_track->flag & PLANE_TRACK_AUTOKEY))
+ {
+ float fac = ((float) next_plane_marker->framenr - start_plane_marker->framenr) /
+ ((float) keyframe_plane_marker->framenr - start_plane_marker->framenr);
+
+ fac = 3 * fac * fac - 2 * fac * fac * fac;
+
+ for (i = 0; i < 4; i++) {
+ interp_v2_v2v2(new_plane_marker.corners[i], new_plane_marker.corners[i],
+ next_plane_marker->corners[i], fac);
+ }
+ }
+
+ BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker);
+
+ MEM_freeN(x1);
+ MEM_freeN(x2);
+ }
+}
+
+/* NOTE: frame number should be in clip space, not scene space */
+void BKE_tracking_track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track, int start_frame)
+{
+ track_plane_from_existing_motion(plane_track, start_frame, 1, false);
+ track_plane_from_existing_motion(plane_track, start_frame, -1, false);
+}
+
+static MovieTrackingPlaneMarker *find_plane_keyframe(MovieTrackingPlaneTrack *plane_track,
+ int start_frame, int direction)
+{
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, start_frame);
+ int index = plane_marker - plane_track->markers;
+ int frame_delta = direction > 0 ? 1 : -1;
+
+ while (index >= 0 && index < plane_track->markersnr) {
+ if ((plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
+ return plane_marker;
+ }
+ plane_marker += frame_delta;
+ }
+
+ return NULL;
+}
+
+void BKE_tracking_retrack_plane_from_existing_motion_at_segment(MovieTrackingPlaneTrack *plane_track, int start_frame)
+{
+ MovieTrackingPlaneMarker *prev_plane_keyframe, *next_plane_keyframe;
+
+ prev_plane_keyframe = find_plane_keyframe(plane_track, start_frame, -1);
+ next_plane_keyframe = find_plane_keyframe(plane_track, start_frame, 1);
+
+ if (prev_plane_keyframe != NULL && next_plane_keyframe != NULL) {
+ /* First we track from left keyframe to the right one without any blending. */
+ track_plane_from_existing_motion(plane_track, prev_plane_keyframe->framenr, 1, true);
+
+ /* And then we track from the right keyframe to the left one, so shape blends in nicely */
+ track_plane_from_existing_motion(plane_track, next_plane_keyframe->framenr, -1, false);
+ }
+ else if (prev_plane_keyframe != NULL) {
+ track_plane_from_existing_motion(plane_track, prev_plane_keyframe->framenr, 1, true);
+ }
+ else if (next_plane_keyframe != NULL) {
+ track_plane_from_existing_motion(plane_track, next_plane_keyframe->framenr, -1, true);
+ }
+}
+
+BLI_INLINE void float_corners_to_double(/*const*/ float corners[4][2], double double_corners[4][2])
+{
+ copy_v2db_v2fl(double_corners[0], corners[0]);
+ copy_v2db_v2fl(double_corners[1], corners[1]);
+ copy_v2db_v2fl(double_corners[2], corners[2]);
+ copy_v2db_v2fl(double_corners[3], corners[3]);
+}
+
+void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners[4][2], /*const*/ float corners[4][2], float H[3][3])
+{
+ Vec2 x1[4], x2[4];
+ double H_double[3][3];
+
+ float_corners_to_double(reference_corners, x1);
+ float_corners_to_double(corners, x2);
+
+ libmv_homography2DFromCorrespondencesEuc(x1, x2, 4, H_double);
+
+ mat3f_from_mat3d(H, H_double);
+}
+
/*********************** Camera solving *************************/
typedef struct MovieReconstructContext {
struct libmv_Tracks *tracks;
bool select_keyframes;
int keyframe1, keyframe2;
- short refine_flags;
+ int refine_flags;
struct libmv_Reconstruction *reconstruction;
char object_name[MAX_NAME];
- int is_camera;
+ bool is_camera;
short motion_flag;
float focal_length;
@@ -2888,7 +3474,7 @@ typedef struct MovieReconstructContext {
TracksMap *tracks_map;
float success_threshold;
- int use_fallback_reconstruction;
+ bool use_fallback_reconstruction;
int sfra, efra;
} MovieReconstructContext;
@@ -2957,7 +3543,7 @@ static void reconstruct_retrieve_libmv_intrinsics(MovieReconstructContext *conte
* Actually, this also copies reconstructed cameras
* from libmv to movie clip datablock.
*/
-static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking)
+static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking)
{
struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction;
MovieTrackingReconstruction *reconstruction = NULL;
@@ -2999,7 +3585,7 @@ static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, M
track->flag &= ~TRACK_HAS_BUNDLE;
ok = false;
- printf("No bundle for track #%d '%s'\n", tracknr, track->name);
+ printf("Unable to reconstruct position for track #%d '%s'\n", tracknr, track->name);
}
track = track->next;
@@ -3134,12 +3720,12 @@ static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, M
}
/* Perform early check on whether everything is fine to start reconstruction. */
-int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object,
- char *error_msg, int error_size)
+bool BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object,
+ char *error_msg, int error_size)
{
if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) {
/* TODO: check for number of tracks? */
- return TRUE;
+ return true;
}
else if ((tracking->settings.reconstruction_flag & TRACKING_USE_KEYFRAME_SELECTION) == 0) {
/* automatic keyframe selection does not require any pre-process checks */
@@ -3148,16 +3734,16 @@ int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObje
N_("At least 8 common tracks on both of keyframes are needed for reconstruction"),
error_size);
- return FALSE;
+ return false;
}
}
#ifndef WITH_LIBMV
BLI_strncpy(error_msg, N_("Blender is compiled without motion tracking library"), error_size);
- return FALSE;
+ return false;
#endif
- return TRUE;
+ return true;
}
/* Create context for camera/object motion reconstruction.
@@ -3264,7 +3850,6 @@ static void reconstruct_update_solve_cb(void *customdata, double progress, const
BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message);
}
-
/* FIll in camera intrinsics structure from reconstruction context. */
static void camraIntrincicsOptionsFromContext(libmv_CameraIntrinsicsOptions *camera_intrinsics_options,
MovieReconstructContext *context)
@@ -3352,7 +3937,7 @@ void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *
/* Finish reconstruction process by copying reconstructed data
* to an actual movie clip datablock.
*/
-int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking)
+bool BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking)
{
MovieTrackingReconstruction *reconstruction;
MovieTrackingObject *object;
@@ -3377,9 +3962,9 @@ int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTr
reconstruction->flag |= TRACKING_RECONSTRUCTED;
if (!reconstruct_retrieve_libmv(context, tracking))
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
static void tracking_scale_reconstruction(ListBase *tracksbase, MovieTrackingReconstruction *reconstruction,
@@ -3544,7 +4129,7 @@ static unsigned char *detect_get_frame_ucharbuf(ImBuf *ibuf)
/* Detect features using FAST detector */
void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
- int place_outside_layer)
+ bool place_outside_layer)
{
struct libmv_Features *features;
unsigned char *pixels = detect_get_frame_ucharbuf(ibuf);
@@ -3556,14 +4141,14 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImB
detect_retrieve_libmv_features(tracking, tracksbase, features,
framenr, ibuf->x, ibuf->y, layer,
- place_outside_layer ? true : false);
+ place_outside_layer);
libmv_featuresDestroy(features);
}
/*********************** 2D stabilization *************************/
-/* Claculate median point of markers of tracks marked as used for
+/* Calculate median point of markers of tracks marked as used for
* 2D stabilization.
*
* NOTE: frame number should be in clip space, not scene space
@@ -3601,7 +4186,7 @@ static bool stabilization_median_point_get(MovieTracking *tracking, int framenr,
*
* NOTE: frame number should be in clip space, not scene space
*/
-static void stabilization_calculate_data(MovieTracking *tracking, int framenr, float width, float height,
+static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height,
float firstmedian[2], float median[2],
float translation[2], float *scale, float *angle)
{
@@ -3631,7 +4216,7 @@ static void stabilization_calculate_data(MovieTracking *tracking, int framenr, f
b[0] *= width;
b[1] *= height;
- *angle = -atan2(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]);
+ *angle = -atan2f(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]);
*angle *= stab->rotinf;
/* convert to rotation around image center */
@@ -3691,8 +4276,8 @@ static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, i
BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, 1.0f, angle, mat);
- si = sin(angle);
- co = cos(angle);
+ si = sinf(angle);
+ co = cosf(angle);
for (i = 0; i < 4; i++) {
int j;
@@ -3831,7 +4416,7 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf
float tloc[2], tscale, tangle;
MovieTrackingStabilization *stab = &tracking->stabilization;
ImBuf *tmpibuf;
- float width = ibuf->x, height = ibuf->y;
+ int width = ibuf->x, height = ibuf->y;
float aspect = tracking->camera.pixel_aspect;
float mat[4][4];
int j, filter = tracking->stabilization.filter;
@@ -3893,7 +4478,7 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf
for (j = 0; j < tmpibuf->y; j++) {
int i;
for (i = 0; i < tmpibuf->x; i++) {
- float vec[3] = {i, j, 0};
+ float vec[3] = {i, j, 0.0f};
mul_v3_m4v3(vec, mat, vec);
@@ -3920,7 +4505,7 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf
* stabilization data and used for easy coordinate
* transformation.
*
- * NOTE: The reaosn it is 4x4 matrix is because it's
+ * NOTE: The reason it is 4x4 matrix is because it's
* used for OpenGL drawing directly.
*/
void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect,
@@ -4170,7 +4755,7 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking)
/* Sot dopesheet channels using given method (name, average error, total coverage,
* longest tracked segment) and could also inverse the list if it's enabled.
*/
-static void tracking_dopesheet_channels_sort(MovieTracking *tracking, int sort_method, int inverse)
+static void tracking_dopesheet_channels_sort(MovieTracking *tracking, int sort_method, bool inverse)
{
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
@@ -4307,7 +4892,7 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking)
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
short sort_method = dopesheet->sort_method;
- short inverse = dopesheet->flag & TRACKING_DOPE_SORT_INVERSE;
+ bool inverse = (dopesheet->flag & TRACKING_DOPE_SORT_INVERSE) != 0;
if (dopesheet->ok)
return;
diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c
new file mode 100644
index 00000000000..d1e9da72208
--- /dev/null
+++ b/source/blender/blenkernel/intern/treehash.c
@@ -0,0 +1,164 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation 2013
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file treehash.c
+ * \ingroup bke
+ *
+ * Tree hash for the outliner space.
+ */
+
+#include <stdlib.h>
+
+#include "BKE_treehash.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_mempool.h"
+
+#include "DNA_outliner_types.h"
+
+#include "MEM_guardedalloc.h"
+
+typedef struct TseGroup
+{
+ TreeStoreElem **elems;
+ int size;
+ int allocated;
+} TseGroup;
+
+/* Allocate structure for TreeStoreElements;
+ * Most of elements in treestore have no duplicates,
+ * so there is no need to preallocate memory for more than one pointer */
+static TseGroup *tse_group_create(void)
+{
+ TseGroup *tse_group = MEM_mallocN(sizeof(TseGroup), "TseGroup");
+ tse_group->elems = MEM_mallocN(sizeof(TreeStoreElem *), "TseGroupElems");
+ tse_group->size = 0;
+ tse_group->allocated = 1;
+ return tse_group;
+}
+
+static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
+{
+ if (tse_group->size == tse_group->allocated) {
+ tse_group->allocated *= 2;
+ tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated);
+ }
+ tse_group->elems[tse_group->size] = elem;
+ tse_group->size++;
+}
+
+static void tse_group_free(TseGroup *tse_group)
+{
+ MEM_freeN(tse_group->elems);
+ MEM_freeN(tse_group);
+}
+
+static unsigned int tse_hash(const void *ptr)
+{
+ const TreeStoreElem *tse = ptr;
+ unsigned int hash;
+ BLI_assert(tse->type || !tse->nr);
+ hash = BLI_ghashutil_inthash(SET_INT_IN_POINTER((tse->nr << 16) + tse->type));
+ hash ^= BLI_ghashutil_inthash(tse->id);
+ return hash;
+}
+
+static int tse_cmp(const void *a, const void *b)
+{
+ const TreeStoreElem *tse_a = a;
+ const TreeStoreElem *tse_b = b;
+ return tse_a->type != tse_b->type || tse_a->nr != tse_b->nr || tse_a->id != tse_b->id;
+}
+
+static void fill_treehash(void *treehash, BLI_mempool *treestore)
+{
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+ BLI_mempool_iternew(treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ BKE_treehash_add_element(treehash, tselem);
+ }
+}
+
+void *BKE_treehash_create_from_treestore(BLI_mempool *treestore)
+{
+ GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_count(treestore));
+ fill_treehash(treehash, treestore);
+ return treehash;
+}
+
+static void free_treehash_group(void *key)
+{
+ tse_group_free(key);
+}
+
+void *BKE_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore)
+{
+ BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore));
+ fill_treehash(treehash, treestore);
+ return treehash;
+}
+
+void BKE_treehash_add_element(void *treehash, TreeStoreElem *elem)
+{
+ TseGroup *group = BLI_ghash_lookup(treehash, elem);
+ if (!group) {
+ group = tse_group_create();
+ BLI_ghash_insert(treehash, elem, group);
+ }
+ tse_group_add(group, elem);
+}
+
+static TseGroup *BKE_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id)
+{
+ TreeStoreElem tse_template;
+ tse_template.type = type;
+ tse_template.nr = type ? nr : 0; // we're picky! :)
+ tse_template.id = id;
+ return BLI_ghash_lookup(th, &tse_template);
+}
+
+TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id)
+{
+ TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id);
+ if (group) {
+ int i;
+ for (i = 0; i < group->size; i++) {
+ if (!group->elems[i]->used) {
+ return group->elems[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id)
+{
+ TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id);
+ return group ? group->elems[0] : NULL;
+}
+
+void BKE_treehash_free(void *treehash)
+{
+ BLI_ghash_free(treehash, NULL, free_treehash_group);
+}
diff --git a/source/blender/blenlib/BLI_alloca.h b/source/blender/blenlib/BLI_alloca.h
index b93f5b7123e..06c3e8d8996 100644
--- a/source/blender/blenlib/BLI_alloca.h
+++ b/source/blender/blenlib/BLI_alloca.h
@@ -19,6 +19,7 @@
*/
#ifndef __BLI_ALLOCA_H__
+#define __BLI_ALLOCA_H__
/** \file BLI_alloca.h
* \ingroup bli
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index 566fc95eb4f..4110c85c2a5 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -13,7 +13,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h
index ca98d28cc40..bcdc97cdaa7 100644
--- a/source/blender/blenlib/BLI_bitmap.h
+++ b/source/blender/blenlib/BLI_bitmap.h
@@ -26,6 +26,10 @@
#ifndef __BLI_BITMAP_H__
#define __BLI_BITMAP_H__
+/** \file BLI_bitmap.h
+ * \ingroup bli
+ */
+
typedef unsigned int BLI_bitmap;
/* warning: the bitmap does not keep track of its own size or check
@@ -54,17 +58,17 @@ typedef unsigned int BLI_bitmap;
/* get the value of a single bit at '_index' */
#define BLI_BITMAP_GET(_bitmap, _index) \
((_bitmap)[(_index) >> BLI_BITMAP_POWER] & \
- (1 << ((_index) & BLI_BITMAP_MASK)))
+ (1u << ((_index) & BLI_BITMAP_MASK)))
/* set the value of a single bit at '_index' */
#define BLI_BITMAP_SET(_bitmap, _index) \
((_bitmap)[(_index) >> BLI_BITMAP_POWER] |= \
- (1 << ((_index) & BLI_BITMAP_MASK)))
+ (1u << ((_index) & BLI_BITMAP_MASK)))
/* clear the value of a single bit at '_index' */
#define BLI_BITMAP_CLEAR(_bitmap, _index) \
((_bitmap)[(_index) >> BLI_BITMAP_POWER] &= \
- ~(1 << ((_index) & BLI_BITMAP_MASK)))
+ ~(1u << ((_index) & BLI_BITMAP_MASK)))
/* set or clear the value of a single bit at '_index' */
#define BLI_BITMAP_MODIFY(_bitmap, _index, _set) \
diff --git a/source/blender/blenlib/BLI_boxpack2d.h b/source/blender/blenlib/BLI_boxpack2d.h
index 3bc486054f5..8316987dfcd 100644
--- a/source/blender/blenlib/BLI_boxpack2d.h
+++ b/source/blender/blenlib/BLI_boxpack2d.h
@@ -46,7 +46,7 @@ typedef struct BoxPack {
struct BoxVert *v[4];
} BoxPack;
-void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *tot_height);
+void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *tot_height);
#endif
diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
index 461b56e157f..9c4b4b00b24 100644
--- a/source/blender/blenlib/BLI_buffer.h
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -21,21 +21,23 @@
#ifndef __BLI_BUFFER_H__
#define __BLI_BUFFER_H__
-/* Note: this more or less fills same purpose as BLI_array, but makes
+/** \file BLI_buffer.h
+ * \ingroup bli
+ *
+ * \note this more or less fills same purpose as BLI_array, but makes
* it much easier to resize the array outside of the function it was
- * declared in since */
-
-/* Usage examples:
+ * declared in since.
*
- * {
- * BLI_buffer_declare_static(int, my_int_array, BLI_BUFFER_NOP, 32);
+ * Usage examples:
+ * \code
+ * BLI_buffer_declare_static(int, my_int_array, BLI_BUFFER_NOP, 32);
*
- * BLI_buffer_append(my_int_array, int, 42);
- * assert(my_int_array.count == 1);
- * assert(BLI_buffer_at(my_int_array, int, 0) == 42);
+ * BLI_buffer_append(my_int_array, int, 42);
+ * assert(my_int_array.count == 1);
+ * assert(BLI_buffer_at(my_int_array, int, 0) == 42);
*
- * BLI_buffer_free(&my_int_array);
- * }
+ * BLI_buffer_free(&my_int_array);
+ * \endcode
*/
typedef struct {
diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h
index 8a0442c8bc8..8d5ea91c422 100644
--- a/source/blender/blenlib/BLI_callbacks.h
+++ b/source/blender/blenlib/BLI_callbacks.h
@@ -18,7 +18,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/BLI_callbacks.h
+/** \file BLI_callbacks.h
* \ingroup bli
*/
@@ -43,6 +43,8 @@ typedef enum {
BLI_CB_EVT_SAVE_POST,
BLI_CB_EVT_SCENE_UPDATE_PRE,
BLI_CB_EVT_SCENE_UPDATE_POST,
+ BLI_CB_EVT_GAME_PRE,
+ BLI_CB_EVT_GAME_POST,
BLI_CB_EVT_TOT
} eCbEvent;
@@ -61,8 +63,4 @@ void BLI_callback_add(bCallbackFuncStore *funcstore, eCbEvent evt);
void BLI_callback_global_init(void);
void BLI_callback_global_finalize(void);
-
-/* This is blenlib internal only, unrelated to above */
-void callLocalErrorCallBack(const char *msg);
-
#endif /* __BLI_CALLBACKS_H__ */
diff --git a/source/blender/blenlib/BLI_compiler_attrs.h b/source/blender/blenlib/BLI_compiler_attrs.h
new file mode 100644
index 00000000000..fc16e7dbba6
--- /dev/null
+++ b/source/blender/blenlib/BLI_compiler_attrs.h
@@ -0,0 +1,88 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_COMPILER_ATTRS_H__
+#define __BLI_COMPILER_ATTRS_H__
+
+/** \file BLI_compiler_attrs.h
+ * \ingroup bli
+ */
+
+/* hint to make sure function result is actually used */
+#ifdef __GNUC__
+# define ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+# define ATTR_WARN_UNUSED_RESULT
+#endif
+
+/* hint to mark function arguments expected to be non-null
+ * if no arguments are given to the macro, all of pointer
+ * arguments owuld be expected to be non-null
+ */
+#ifdef __GNUC__
+# define ATTR_NONNULL(args ...) __attribute__((nonnull(args)))
+#else
+# define ATTR_NONNULL(...)
+#endif
+
+/* hint to mark function as it wouldn't return */
+#if defined(__GNUC__) || defined(__clang__)
+# define ATTR_NORETURN __attribute__((noreturn))
+#else
+# define ATTR_NORETURN
+#endif
+
+/* hint to treat any non-null function return value cannot alias any other pointer */
+#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403))
+# define ATTR_MALLOC __attribute__((malloc))
+#else
+# define ATTR_MALLOC
+#endif
+
+/* the function return value points to memory (2 args for 'size * tot') */
+#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403))
+# define ATTR_ALLOC_SIZE(args ...) __attribute__((alloc_size(args)))
+#else
+# define ATTR_ALLOC_SIZE(...)
+#endif
+
+/* ensures a NULL terminating argument as the n'th last argument of a variadic function */
+#ifdef __GNUC__
+# define ATTR_SENTINEL(arg_pos) __attribute__((sentinel(arg_pos)))
+#else
+# define ATTR_SENTINEL(arg_pos)
+#endif
+
+/* hint to compiler that function uses printf-style format string */
+#ifdef __GNUC__
+# define ATTR_PRINTF_FORMAT(format_param, dots_param) __attribute__((format(printf, format_param, dots_param)))
+#else
+# define ATTR_PRINTF_FORMAT(format_param, dots_param)
+#endif
+
+#endif /* __BLI_COMPILER_ATTRS_H__ */
diff --git a/source/blender/compositor/operations/COM_MixBlendOperation.h b/source/blender/blenlib/BLI_convexhull2d.h
index ce3f187a5e2..4b82071ede8 100644
--- a/source/blender/compositor/operations/COM_MixBlendOperation.h
+++ b/source/blender/blenlib/BLI_convexhull2d.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * ***** 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
@@ -15,31 +15,20 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * ***** END GPL LICENSE BLOCK *****
*/
-#ifndef _COM_MixBlendOperation_h
-#define _COM_MixBlendOperation_h
-#include "COM_MixBaseOperation.h"
+#ifndef __BLI_CONVEXHULL2D_H__
+#define __BLI_CONVEXHULL2D_H__
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
+/** \file BLI_convexhull2d.h
+ * \ingroup bli
*/
-class MixBlendOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixBlendOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-};
-#endif
+int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points[]);
+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__ */
diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h
index 833c416c1c1..61bdf23cec1 100644
--- a/source/blender/blenlib/BLI_dynstr.h
+++ b/source/blender/blenlib/BLI_dynstr.h
@@ -40,6 +40,8 @@
#include <stdarg.h>
+#include "BLI_compiler_attrs.h"
+
struct DynStr;
/** The abstract DynStr type */
@@ -75,16 +77,8 @@ void BLI_dynstr_nappend(DynStr *ds, const char *cstr, int len);
* \param ds The DynStr to append to.
* \param format The printf format string to use.
*/
-void BLI_dynstr_appendf(DynStr *ds, const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
-;
-void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 0)))
-#endif
-;
+void BLI_dynstr_appendf(DynStr *ds, const char *format, ...) ATTR_PRINTF_FORMAT(2, 3);
+void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args) ATTR_PRINTF_FORMAT(2, 0);
/**
* Find the length of a DynStr.
diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h
index 9ece3afde37..2ca011871d8 100644
--- a/source/blender/blenlib/BLI_edgehash.h
+++ b/source/blender/blenlib/BLI_edgehash.h
@@ -29,6 +29,8 @@
* \brief A general unordered 2-int pair hash table ADT.
*/
+#include "BLI_compiler_attrs.h"
+
struct EdgeHash;
struct EdgeHashIterator;
typedef struct EdgeHash EdgeHash;
@@ -36,60 +38,60 @@ typedef struct EdgeHashIterator EdgeHashIterator;
typedef void (*EdgeHashFreeFP)(void *key);
-EdgeHash *BLI_edgehash_new(void);
-void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp);
+enum {
+ EDGEHASH_FLAG_ALLOW_DUPES = (1 << 0), /* only checked for in debug mode */
+};
-/* Insert edge (v0,v1) into hash with given value, does
- * not check for duplicates.
- */
+EdgeHash *BLI_edgehash_new_ex(const char *info,
+ const unsigned int nentries_reserve);
+EdgeHash *BLI_edgehash_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp);
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val);
-
-/* Return value for given edge (v0,v1), or NULL if
- * if key does not exist in hash. (If need exists
- * to differentiate between key-value being NULL and
- * lack of key then see BLI_edgehash_lookup_p().
- */
-void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1);
-
-/* Return pointer to value for given edge (v0,v1),
- * or NULL if key does not exist in hash.
- */
-void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1);
-
-/* Return boolean true/false if edge (v0,v1) in hash. */
-bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1);
-
-/* Return number of keys in hash. */
-int BLI_edgehash_size(EdgeHash *eh);
-
-/* Remove all edges from hash. */
+bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val);
+void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT;
+void **BLI_edgehash_lookup_p(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;
+void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp,
+ const unsigned int nentries_reserve);
void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp);
+void BLI_edgehash_flag_set(EdgeHash *eh, unsigned int flag);
+void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned int 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(gh) times before becoming done.
- */
-EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh);
-
-/* Free an EdgeHashIterator. */
+EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
void BLI_edgehashIterator_free(EdgeHashIterator *ehi);
-
-/* Retrieve the key from an iterator. */
void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r);
+void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) ATTR_WARN_UNUSED_RESULT;
+void **BLI_edgehashIterator_getValue_p(EdgeHashIterator *ehi) ATTR_WARN_UNUSED_RESULT;
+void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val);
+void BLI_edgehashIterator_step(EdgeHashIterator *ehi);
+bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi) ATTR_WARN_UNUSED_RESULT;
-/* Retrieve the value from an iterator. */
-void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi);
+#define BLI_EDGEHASH_SIZE_GUESS_FROM_LOOPS(totloop) ((totloop) / 2)
+#define BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly) ((totpoly) * 2)
-/* Set the value for an iterator. */
-void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val);
+/* *** EdgeSet *** */
-/* Steps the iterator to the next index. */
-void BLI_edgehashIterator_step(EdgeHashIterator *ehi);
+struct EdgeSet;
+struct EdgeSetIterator;
+typedef struct EdgeSet EdgeSet;
+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;
+bool BLI_edgeset_reinsert(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;
+void BLI_edgeset_free(EdgeSet *es);
+
+/* rely on inline api for now */
+BLI_INLINE EdgeSetIterator *BLI_edgesetIterator_new(EdgeSet *gs) { return (EdgeSetIterator *)BLI_edgehashIterator_new((EdgeHash *)gs); }
+BLI_INLINE void BLI_edgesetIterator_free(EdgeSetIterator *esi) { BLI_edgehashIterator_free((EdgeHashIterator *)esi); }
+BLI_INLINE void BLI_edgesetIterator_getKey(EdgeSetIterator *esi, unsigned int *v0_r, unsigned int *v1_r) { BLI_edgehashIterator_getKey((EdgeHashIterator *)esi, v0_r, v1_r); }
+BLI_INLINE void BLI_edgesetIterator_step(EdgeSetIterator *esi) { BLI_edgehashIterator_step((EdgeHashIterator *)esi); }
+BLI_INLINE bool BLI_edgesetIterator_isDone(EdgeSetIterator *esi) { return BLI_edgehashIterator_isDone((EdgeHashIterator *)esi); }
-/* Determine if an iterator is done. */
-bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi);
-#endif
+#endif /* __BLI_EDGEHASH_H__ */
diff --git a/source/blender/blenlib/BLI_endian_switch.h b/source/blender/blenlib/BLI_endian_switch.h
index f48b1b072c3..35242fecf4a 100644
--- a/source/blender/blenlib/BLI_endian_switch.h
+++ b/source/blender/blenlib/BLI_endian_switch.h
@@ -27,35 +27,28 @@
* \ingroup bli
*/
-#ifdef __GNUC__
-# define ATTR_ENDIAN_SWITCH \
- __attribute__((nonnull(1)))
-#else
-# define ATTR_ENDIAN_SWITCH
-#endif
+#include "BLI_compiler_attrs.h"
/* BLI_endian_switch_inline.h */
-BLI_INLINE void BLI_endian_switch_int16(short *val) ATTR_ENDIAN_SWITCH;
-BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) ATTR_ENDIAN_SWITCH;
-BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_ENDIAN_SWITCH;
-BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_ENDIAN_SWITCH;
-BLI_INLINE void BLI_endian_switch_float(float *val) ATTR_ENDIAN_SWITCH;
-BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ATTR_ENDIAN_SWITCH;
-BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_ENDIAN_SWITCH;
-BLI_INLINE void BLI_endian_switch_double(double *val) ATTR_ENDIAN_SWITCH;
+BLI_INLINE void BLI_endian_switch_int16(short *val) ATTR_NONNULL(1);
+BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) ATTR_NONNULL(1);
+BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_NONNULL(1);
+BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_NONNULL(1);
+BLI_INLINE void BLI_endian_switch_float(float *val) ATTR_NONNULL(1);
+BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ATTR_NONNULL(1);
+BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_NONNULL(1);
+BLI_INLINE void BLI_endian_switch_double(double *val) ATTR_NONNULL(1);
/* endian_switch.c */
-void BLI_endian_switch_int16_array(short *val, const int size) ATTR_ENDIAN_SWITCH;
-void BLI_endian_switch_uint16_array(unsigned short *val, const int size) ATTR_ENDIAN_SWITCH;
-void BLI_endian_switch_int32_array(int *val, const int size) ATTR_ENDIAN_SWITCH;
-void BLI_endian_switch_uint32_array(unsigned int *val, const int size) ATTR_ENDIAN_SWITCH;
-void BLI_endian_switch_float_array(float *val, const int size) ATTR_ENDIAN_SWITCH;
-void BLI_endian_switch_int64_array(int64_t *val, const int size) ATTR_ENDIAN_SWITCH;
-void BLI_endian_switch_uint64_array(uint64_t *val, const int size) ATTR_ENDIAN_SWITCH;
-void BLI_endian_switch_double_array(double *val, const int size) ATTR_ENDIAN_SWITCH;
+void BLI_endian_switch_int16_array(short *val, const int size) ATTR_NONNULL(1);
+void BLI_endian_switch_uint16_array(unsigned short *val, const int size) ATTR_NONNULL(1);
+void BLI_endian_switch_int32_array(int *val, const int size) ATTR_NONNULL(1);
+void BLI_endian_switch_uint32_array(unsigned int *val, const int size) ATTR_NONNULL(1);
+void BLI_endian_switch_float_array(float *val, const int size) ATTR_NONNULL(1);
+void BLI_endian_switch_int64_array(int64_t *val, const int size) ATTR_NONNULL(1);
+void BLI_endian_switch_uint64_array(uint64_t *val, const int size) ATTR_NONNULL(1);
+void BLI_endian_switch_double_array(double *val, const int size) ATTR_NONNULL(1);
#include "BLI_endian_switch_inline.h"
-#undef ATTR_ENDIAN_SWITCH
-
#endif /* __BLI_ENDIAN_SWITCH_H__ */
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 0a6d95df40a..ca82086b529 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -43,6 +43,12 @@ extern "C" {
/* for size_t (needed on windows) */
#include <stddef.h>
+#include <limits.h> /* for PATH_MAX */
+
+#ifndef PATH_MAX
+# define PATH_MAX 4096
+#endif
+
struct gzFile;
/* Common */
diff --git a/source/blender/blenlib/BLI_fnmatch.h b/source/blender/blenlib/BLI_fnmatch.h
index 6c466759010..f69f5b39869 100644
--- a/source/blender/blenlib/BLI_fnmatch.h
+++ b/source/blender/blenlib/BLI_fnmatch.h
@@ -28,6 +28,8 @@
extern "C" {
#endif
+#if defined WIN32 && !defined _LIBC || defined __sun
+
#if defined(__cplusplus) || (defined(__STDC__) && __STDC__)
#undef __P
#define __P(protos) protos
@@ -65,6 +67,13 @@ extern "C" {
extern int fnmatch __P((const char *__pattern, const char *__string,
int __flags));
+#else
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+# endif
+# include <fnmatch.h>
+#endif /* defined WIN32 && !defined _LIBC || defined __sun */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 3ad0e18c8d7..e5a93691ad0 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -33,6 +33,9 @@
* \brief A general (pointer -> pointer) hash table ADT
*/
+#include "BLI_sys_types.h" /* for bool */
+#include "BLI_compiler_attrs.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -42,97 +45,51 @@ typedef int (*GHashCmpFP) (const void *a, const void *b);
typedef void (*GHashKeyFreeFP) (void *key);
typedef void (*GHashValFreeFP) (void *val);
-typedef struct Entry {
- struct Entry *next;
-
- void *key, *val;
-} Entry;
-
-typedef struct GHash {
- GHashHashFP hashfp;
- GHashCmpFP cmpfp;
-
- Entry **buckets;
- struct BLI_mempool *entrypool;
- unsigned int nbuckets;
- unsigned int nentries, cursize;
-} GHash;
+typedef struct GHash GHash;
typedef struct GHashIterator {
GHash *gh;
- unsigned int curBucket;
struct Entry *curEntry;
+ unsigned int curBucket;
} GHashIterator;
+enum {
+ GHASH_FLAG_ALLOW_DUPES = (1 << 0), /* only checked for in debug mode */
+};
+
/* *** */
-GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info);
+GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
+ const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_insert(GHash *gh, void *key, void *val);
-void *BLI_ghash_lookup(GHash *gh, const void *key);
+bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
+void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
-void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp);
-bool BLI_ghash_haskey(GHash *gh, const void *key);
-int BLI_ghash_size(GHash *gh);
+void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ const unsigned int nentries_reserve);
+void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT;
+bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
+int BLI_ghash_size(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);
/* *** */
-/**
- * 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.
- *
- * \param gh The GHash to iterate over.
- * \return Pointer to a new DynStr.
- */
-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.
- *
- * \param ghi The GHashIterator to initialize.
- * \param gh The GHash to iterate over.
- */
-void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh);
-/**
- * Free a GHashIterator.
- *
- * \param ghi The iterator to free.
- */
-void BLI_ghashIterator_free(GHashIterator *ghi);
+GHashIterator *BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
-/**
- * Retrieve the key from an iterator.
- *
- * \param ghi The iterator.
- * \return The key at the current index, or NULL if the
- * iterator is done.
- */
-void *BLI_ghashIterator_getKey(GHashIterator *ghi);
-/**
- * Retrieve the value from an iterator.
- *
- * \param ghi The iterator.
- * \return The value at the current index, or NULL if the
- * iterator is done.
- */
-void *BLI_ghashIterator_getValue(GHashIterator *ghi);
-/**
- * Steps the iterator to the next index.
- *
- * \param ghi The iterator.
- */
-void BLI_ghashIterator_step(GHashIterator *ghi);
-/**
- * Determine if an iterator is done (has reached the end of
- * the hash table).
- *
- * \param ghi The iterator.
- * \return True if done, False otherwise.
- */
-bool BLI_ghashIterator_done(GHashIterator *ghi);
+void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh);
+void BLI_ghashIterator_free(GHashIterator *ghi);
+
+void *BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT;
+void *BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT;
+void **BLI_ghashIterator_getValue_p(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT;
+
+void BLI_ghashIterator_step(GHashIterator *ghi);
+bool BLI_ghashIterator_done(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT;
#define GHASH_ITER(gh_iter_, ghash_) \
for (BLI_ghashIterator_init(&gh_iter_, ghash_); \
@@ -155,10 +112,18 @@ int BLI_ghashutil_strcmp(const void *a, const void *b);
unsigned int BLI_ghashutil_inthash(const void *ptr);
int BLI_ghashutil_intcmp(const void *a, const void *b);
-GHash *BLI_ghash_ptr_new(const char *info);
-GHash *BLI_ghash_str_new(const char *info);
-GHash *BLI_ghash_int_new(const char *info);
-GHash *BLI_ghash_pair_new(const char *info);
+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;
@@ -170,6 +135,62 @@ unsigned int BLI_ghashutil_pairhash(const void *ptr);
int BLI_ghashutil_paircmp(const void *a, const void *b);
void BLI_ghashutil_pairfree(void *ptr);
+
+/* *** */
+
+typedef struct GSet GSet;
+
+typedef GHashHashFP GSetHashFP;
+typedef GHashCmpFP GSetCmpFP;
+typedef GHashKeyFreeFP GSetKeyFreeFP;
+
+/* 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;
+int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT;
+void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp);
+void BLI_gset_insert(GSet *gh, void *key);
+bool BLI_gset_reinsert(GSet *gh, void *key, GSetKeyFreeFP keyfreefp);
+bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT;
+bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp);
+void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp,
+ const unsigned int nentries_reserve);
+void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp);
+
+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_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;
+
+/* rely on inline api for now */
+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); }
+BLI_INLINE void *BLI_gsetIterator_getKey(GSetIterator *gsi) { return BLI_ghashIterator_getKey((GHashIterator *)gsi); }
+BLI_INLINE void BLI_gsetIterator_step(GSetIterator *gsi) { BLI_ghashIterator_step((GHashIterator *)gsi); }
+BLI_INLINE bool BLI_gsetIterator_done(GSetIterator *gsi) { return BLI_ghashIterator_done((GHashIterator *)gsi); }
+
+#define GSET_ITER(gs_iter_, gset_) \
+ for (BLI_gsetIterator_init(&gs_iter_, gset_); \
+ BLI_gsetIterator_done(&gs_iter_) == false; \
+ BLI_gsetIterator_step(&gs_iter_))
+
+#define GSET_ITER_INDEX(gs_iter_, gset_, i_) \
+ for (BLI_gsetIterator_init(&gs_iter_, gset_), i_ = 0; \
+ BLI_gsetIterator_done(&gs_iter_) == false; \
+ BLI_gsetIterator_step(&gs_iter_), i_++)
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_jitter.h b/source/blender/blenlib/BLI_jitter.h
index 432bf73ad90..936a5260a68 100644
--- a/source/blender/blenlib/BLI_jitter.h
+++ b/source/blender/blenlib/BLI_jitter.h
@@ -33,8 +33,8 @@
*/
void BLI_jitter_init(float *jitarr, int num);
-void BLI_jitterate1(float *jit1, float *jit2, int num, float rad1);
-void BLI_jitterate2(float *jit1, float *jit2, int num, float rad2);
+void BLI_jitterate1(float *jit1, float *jit2, int num, float radius1);
+void BLI_jitterate2(float *jit1, float *jit2, int num, float radius2);
#endif
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index 8441413fba9..b55ab432a12 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -87,7 +87,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis);
void BLI_bvhtree_free(BVHTree *tree);
/* construct: first insert points, then call balance */
-int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints);
+void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints);
void BLI_bvhtree_balance(BVHTree *tree);
/* update: first update points/nodes, then call update_tree to refit the bounding volumes */
diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h
index b687d98e6ad..e3c81021351 100644
--- a/source/blender/blenlib/BLI_kdtree.h
+++ b/source/blender/blenlib/BLI_kdtree.h
@@ -31,6 +31,8 @@
* \author Brecht van Lommel
*/
+#include "BLI_compiler_attrs.h"
+
struct KDTree;
typedef struct KDTree KDTree;
@@ -40,22 +42,19 @@ typedef struct KDTreeNearest {
float co[3];
} KDTreeNearest;
-/* Creates or free a kdtree */
-KDTree *BLI_kdtree_new(int maxsize);
+KDTree *BLI_kdtree_new(unsigned int maxsize);
void BLI_kdtree_free(KDTree *tree);
-/* Construction: first insert points, then call balance. Normal is optional. */
-void BLI_kdtree_insert(KDTree *tree, int index, const float co[3], const float nor[3]);
-void BLI_kdtree_balance(KDTree *tree);
-
-/* Find nearest returns index, and -1 if no node is found.
- * Find n nearest returns number of points found, with results in nearest.
- * Normal is optional, but if given will limit results to points in normal direction from co. */
-int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], KDTreeNearest *nearest);
-int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const float nor[3], KDTreeNearest *nearest);
-
-/* Range search returns number of points found, with results in nearest */
-/* Normal is optional, but if given will limit results to points in normal direction from co. */
-/* Remember to free nearest after use! */
-int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const float nor[3], KDTreeNearest **nearest);
-#endif
+void BLI_kdtree_insert(KDTree *tree, int index, const float co[3], const float nor[3]) ATTR_NONNULL(1, 3);
+void BLI_kdtree_balance(KDTree *tree) ATTR_NONNULL(1);
+
+int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3],
+ KDTreeNearest *r_nearest) ATTR_NONNULL(1, 2);
+int BLI_kdtree_find_nearest_n(KDTree *tree, const float co[3], const float nor[3],
+ KDTreeNearest *r_nearest,
+ unsigned int n) ATTR_NONNULL(1, 2, 4);
+int BLI_kdtree_range_search(KDTree *tree, const float co[3], const float nor[3],
+ KDTreeNearest **r_nearest,
+ float range) ATTR_NONNULL(1, 2, 4) ATTR_WARN_UNUSED_RESULT;
+
+#endif /* __BLI_KDTREE_H__ */
diff --git a/source/blender/blenlib/BLI_lasso.h b/source/blender/blenlib/BLI_lasso.h
index 0addd463a70..28f21e5bd85 100644
--- a/source/blender/blenlib/BLI_lasso.h
+++ b/source/blender/blenlib/BLI_lasso.h
@@ -34,8 +34,8 @@
struct rcti;
-void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const short moves);
-bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves, const int sx, const int sy, const int error_value);
-bool BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, int x0, int y0, int x1, int y1, const int error_value);
+void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const unsigned int moves);
+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
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
index 3e7fdc8bf75..2ca363ee780 100644
--- a/source/blender/blenlib/BLI_linklist.h
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -36,6 +36,7 @@
*/
struct MemArena;
+struct BLI_mempool;
typedef void (*LinkNodeFreeFP)(void *link);
typedef void (*LinkNodeApplyFP)(void *link, void *userdata);
@@ -53,13 +54,26 @@ struct LinkNode *BLI_linklist_find(struct LinkNode *list, int index);
void BLI_linklist_reverse(struct LinkNode **listp);
+void BLI_linklist_prepend_nlink(struct LinkNode **listp, void *ptr, struct LinkNode *nlink);
void BLI_linklist_prepend(struct LinkNode **listp, void *ptr);
-void BLI_linklist_append(struct LinkNode **listp, void *ptr);
void BLI_linklist_prepend_arena(struct LinkNode **listp, void *ptr, struct MemArena *ma);
+void BLI_linklist_prepend_pool(struct LinkNode **listp, void *ptr, struct BLI_mempool *mempool);
+
+void BLI_linklist_append_nlink(LinkNode **listp, void *ptr, LinkNode *nlink);
+void BLI_linklist_append(struct LinkNode **listp, void *ptr);
+void BLI_linklist_append_arena(LinkNode **listp, void *ptr, struct MemArena *ma);
+void BLI_linklist_append_pool(LinkNode **listp, void *ptr, struct BLI_mempool *mempool);
+
+void *BLI_linklist_pop(struct LinkNode **listp);
+void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool);
void BLI_linklist_insert_after(struct LinkNode **listp, void *ptr);
void BLI_linklist_free(struct LinkNode *list, LinkNodeFreeFP freefunc);
void BLI_linklist_freeN(struct LinkNode *list);
+void BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool);
void BLI_linklist_apply(struct LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata);
-#endif
+#define BLI_linklist_prepend_alloca(listp, ptr) \
+ BLI_linklist_prepend_nlink(listp, ptr, alloca(sizeof(LinkNode)))
+
+#endif /* __BLI_LINKLIST_H__ */
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
new file mode 100644
index 00000000000..ca050883018
--- /dev/null
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -0,0 +1,159 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * 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 *****
+ */
+
+#ifndef __BLI_LINKLIST_STACK_H__
+#define __BLI_LINKLIST_STACK_H__
+
+/** \file BLI_linklist_stack.h
+ * \ingroup bli
+ * \brief BLI_LINKSTACK_*** wrapper macros for using a \a LinkNode
+ * to store a stack of pointers, using a single linked list
+ * allocated from a mempool.
+ *
+ * \note These macros follow STACK_* macros defined in 'BLI_utildefines.h'
+ * and should be kept (mostly) interchangeable.
+ *
+ * \note _##var##_type is a dummy var only used for typechecks.
+ */
+
+/* -------------------------------------------------------------------- */
+/* Linked Stack using BLI_mempool
+ *
+ * Uses mempool for storage.
+ */
+
+/** \name Linked Stack (mempool)
+ * \{ */
+
+#define BLI_LINKSTACK_DECLARE(var, type) \
+ LinkNode *var; \
+ BLI_mempool *_##var##_pool; \
+ type _##var##_type
+
+#define BLI_LINKSTACK_INIT(var) { \
+ var = NULL; \
+ _##var##_pool = BLI_mempool_create(sizeof(LinkNode), 1, 64, 0); \
+} (void)0
+
+#define BLI_LINKSTACK_SIZE(var) \
+ BLI_mempool_count(_##var##_pool)
+
+/* check for typeof() */
+#ifdef __GNUC__
+#define BLI_LINKSTACK_PUSH(var, ptr) ( \
+ CHECK_TYPE_INLINE(ptr, typeof(_##var##_type)), \
+ BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+#define BLI_LINKSTACK_POP(var) \
+ (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+#define BLI_LINKSTACK_POP_ELSE(var, r) \
+ (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+#else /* non gcc */
+#define BLI_LINKSTACK_PUSH(var, ptr) ( \
+ BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+#define BLI_LINKSTACK_POP(var) \
+ (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+#define BLI_LINKSTACK_POP_ELSE(var, r) \
+ (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+#endif /* gcc check */
+
+#define BLI_LINKSTACK_SWAP(var_a, var_b) { \
+ CHECK_TYPE_PAIR(_##var_a##_type, _##var_b##_type); \
+ SWAP(LinkNode *, var_a, var_b); \
+ SWAP(BLI_mempool *, _##var_a##_pool, _##var_b##_pool); \
+} (void)0
+
+#define BLI_LINKSTACK_FREE(var) { \
+ BLI_mempool_destroy(_##var##_pool); \
+ _##var##_pool = NULL; (void)_##var##_pool; \
+ var = NULL; (void)var; \
+ (void)&(_##var##_type); \
+} (void)0
+
+#include "BLI_linklist.h"
+#include "BLI_mempool.h"
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Linked Stack, using stack memory (alloca)
+ *
+ * alloca never frees, pop'd items are stored in a free-list for reuse.
+ * only use for lists small enough to fit on the stack.
+ */
+
+
+/** \name Linked Stack (alloca)
+ * \{ */
+
+#ifdef __GNUC__
+# define _BLI_SMALLSTACK_CAST(var) (typeof(_##var##_type))
+#else
+# define _BLI_SMALLSTACK_CAST(var)
+#endif
+
+#define BLI_SMALLSTACK_DECLARE(var, type) \
+ LinkNode *_##var##_stack = NULL, *_##var##_free = NULL, *_##var##_temp = NULL; \
+ type _##var##_type
+
+#define BLI_SMALLSTACK_PUSH(var, data) \
+{ \
+ CHECK_TYPE_PAIR(data, _##var##_type); \
+ if (_##var##_free) { \
+ _##var##_temp = _##var##_free; \
+ _##var##_free = _##var##_free->next; \
+ } \
+ else { \
+ _##var##_temp = alloca(sizeof(LinkNode)); \
+ } \
+ _##var##_temp->next = _##var##_stack; \
+ _##var##_temp->link = data; \
+ _##var##_stack = _##var##_temp; \
+} (void)0
+
+/* internal use, no null check */
+#define _BLI_SMALLSTACK_DEL(var) \
+ (void)((_##var##_temp = _##var##_stack->next), \
+ (_##var##_stack->next = _##var##_free), \
+ (_##var##_free = _##var##_stack), \
+ (_##var##_stack = _##var##_temp)) \
+
+/* check for typeof() */
+#define BLI_SMALLSTACK_POP(var) \
+ (_BLI_SMALLSTACK_CAST(var) ((_##var##_stack) ? \
+ (_BLI_SMALLSTACK_DEL(var), (_##var##_free->link)) : NULL))
+
+#define BLI_SMALLSTACK_FREE(var) { \
+ (void)&(_##var##_type); \
+} (void)0
+
+#include "BLI_alloca.h"
+
+/** \} */
+
+#endif /* __BLI_LINKLIST_STACK_H__ */
+
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index 4c7ddf7ba66..0927620a2c6 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -60,6 +60,8 @@ void BLI_freelistN(struct ListBase *listbase);
void BLI_addtail(struct ListBase *listbase, void *vlink);
void BLI_remlink(struct ListBase *listbase, void *vlink);
bool BLI_remlink_safe(struct ListBase *listbase, void *vlink);
+void *BLI_pophead(ListBase *listbase);
+void *BLI_poptail(ListBase *listbase);
void BLI_addhead(struct ListBase *listbase, void *vlink);
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink);
@@ -72,7 +74,8 @@ void BLI_freelinkN(struct ListBase *listbase, void *vlink);
void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src);
void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src);
void BLI_reverselist(struct ListBase *lb);
-void BLI_rotatelist(struct ListBase *lb, void *vlink);
+void BLI_rotatelist_first(struct ListBase *lb, void *vlink);
+void BLI_rotatelist_last(struct ListBase *lb, void *vlink);
/* create a generic list node containing link to provided data */
struct LinkData *BLI_genericNodeN(void *data);
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 69dbd3253f0..1cb28d25b6c 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -222,6 +222,7 @@ MINLINE int power_of_2_max_i(int n);
MINLINE int power_of_2_min_i(int n);
MINLINE int divide_round_i(int a, int b);
+MINLINE int mod_i(int i, int n);
MINLINE float shell_angle_to_dist(const float angle);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 6cb7103be9b..f815716148b 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -34,6 +34,7 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
#include "BLI_math_inline.h"
#if BLI_MATH_DO_INLINE
@@ -61,6 +62,14 @@ float area_quad_v3(const float a[3], const float b[3], const float c[3], const f
float area_poly_v3(int nr, float verts[][3], const float normal[3]);
float area_poly_v2(int nr, float verts[][2]);
+/********************************* Planes **********************************/
+
+void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3]);
+void plane_to_point_normal_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3]);
+MINLINE float plane_point_side_v3(const float plane[4], const float co[3]);
+
+/********************************* Volume **********************************/
+
float volume_tetrahedron_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
int is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
@@ -73,15 +82,15 @@ float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const
float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2]);
void closest_to_line_segment_v2(float closest[2], const float p[2], const float l1[2], const float l2[2]);
-float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3]);
-float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]);
+float dist_squared_to_plane_v3(const float p[3], const float plane[4]);
+float dist_to_plane_v3(const float p[3], const float plane[4]);
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]);
float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]);
float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3]);
float closest_to_line_v3(float r[3], const float p[3], const float l1[3], const float l2[3]);
float closest_to_line_v2(float r[2], const float p[2], const float l1[2], const float l2[2]);
void closest_to_line_segment_v3(float r[3], const float p[3], const float l1[3], const float l2[3]);
-void closest_to_plane_v3(float r[3], const float plane_co[3], const float plane_no_unit[3], const float pt[3]);
+void closest_to_plane_v3(float close_r[3], const float plane[4], const float pt[3]);
/* Set 'r' to the point in triangle (t1, t2, t3) closest to point 'p' */
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3], const float t2[3], const float t3[3]);
@@ -89,6 +98,10 @@ void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3],
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]);
float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]);
+
+float line_plane_factor_v3(const float plane_co[3], const float plane_no[3],
+ const float l1[3], const float l2[3]);
+
void limit_dist_v3(float v1[3], float v2[3], const float dist);
/******************************* Intersection ********************************/
@@ -120,8 +133,9 @@ bool isect_ray_plane_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, const int clip);
+bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]);
bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3],
- const float plane_co[3], const float plane_no[3], const bool no_flip);
+ const float plane_co[3], const float plane_no[3]);
void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
const float plane_a_co[3], const float plane_a_no[3],
@@ -130,6 +144,9 @@ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
/* line/ray triangle */
bool isect_line_tri_v3(const float p1[3], const float p2[3],
const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]);
+bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2], const float epsilon);
bool isect_ray_tri_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]);
bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
@@ -138,8 +155,8 @@ bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon);
/* point in polygon */
-bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr);
-bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr);
+bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, const bool use_holes);
+bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr, const bool use_holes);
int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], const float c[2], const float d[2]);
@@ -171,7 +188,10 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4]);
bool clip_segment_v3_plane_n(float p1[3], float p2[3], float plane_array[][4], const int plane_tot);
void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData);
-
+void fill_poly_v2i_n(
+ const int xmin, const int ymin, const int xmax, const int ymax,
+ const int polyXY[][2], const int polyCorners,
+ void (*callback)(int, int, void *), void *userData);
/****************************** Interpolation ********************************/
/* tri or quad, d can be NULL */
@@ -277,11 +297,7 @@ float form_factor_hemi_poly(float p[3], float n[3],
bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]);
void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]);
-float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3])
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-#endif
-;
+float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE int max_axis_v3(const float vec[3]);
MINLINE int min_axis_v3(const float vec[3]);
diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h
index 21975763779..43ef64214ad 100644
--- a/source/blender/blenlib/BLI_math_interp.h
+++ b/source/blender/blenlib/BLI_math_interp.h
@@ -26,8 +26,12 @@
*
*/
-#ifndef BLI_MATH_INTERP
-#define BLI_MATH_INTERP
+#ifndef __BLI_MATH_INTERP_H__
+#define __BLI_MATH_INTERP_H__
+
+/** \file BLI_math_interp.h
+ * \ingroup bli
+ */
void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height,
int components, float u, float v);
@@ -41,4 +45,4 @@ void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width
void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height,
int components, float u, float v);
-#endif
+#endif /* __BLI_MATH_INTERP_H__ */
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index c305cc9a030..b04af44156f 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -94,6 +94,8 @@ void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]);
void mul_project_m4_v3(float M[4][4], float vec[3]);
void mul_v2_project_m4_v3(float r[2], float M[4][4], const float vec[3]);
+void mul_m3_v2(float m[3][3], float r[2]);
+void mul_v2_m3v2(float r[2], float m[3][3], float v[2]);
void mul_m3_v3(float M[3][3], float r[3]);
void mul_v3_m3v3(float r[3], float M[3][3], const float a[3]);
void mul_v2_m3v3(float r[2], float M[3][3], const float a[3]);
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index b3702d10d87..42161279bfd 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -66,7 +66,7 @@ float normalize_qt(float q[4]);
float normalize_qt_qt(float q1[4], const float q2[4]);
/* comparison */
-int is_zero_qt(float q[4]);
+bool is_zero_qt(const float q[4]);
/* interpolation */
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], const float t);
@@ -104,7 +104,8 @@ void quat_to_axis_angle(float axis[3], float *angle, const float q[4]);
void mat3_to_axis_angle(float axis[3], float *angle, float M[3][3]);
void mat4_to_axis_angle(float axis[3], float *angle, float M[4][4]);
-void single_axis_angle_to_mat3(float R[3][3], const char axis, const float angle);
+void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle);
+void angle_to_mat2(float R[2][2], const float angle);
/******************************** XYZ Eulers *********************************/
@@ -163,13 +164,13 @@ typedef struct DualQuat {
float scale_weight;
} DualQuat;
-void copy_dq_dq(DualQuat *r, DualQuat *dq);
+void copy_dq_dq(DualQuat *r, const DualQuat *dq);
void normalize_dq(DualQuat *dq, float totw);
-void add_weighted_dq_dq(DualQuat *r, DualQuat *dq, float weight);
+void add_weighted_dq_dq(DualQuat *r, const DualQuat *dq, float weight);
void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq);
void mat4_to_dquat(DualQuat *r, float base[4][4], float M[4][4]);
-void dquat_to_mat4(float R[4][4], DualQuat *dq);
+void dquat_to_mat4(float R[4][4], const DualQuat *dq);
void quat_apply_track(float quat[4], short axis, short upflag);
void vec_apply_track(float vec[3], short axis);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index e163c06440c..675ba88fc72 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -34,6 +34,7 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
#include "BLI_math_inline.h"
/************************************* Init ***********************************/
@@ -43,11 +44,6 @@ extern "C" {
# pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
-#ifdef __GNUC__
-# define UNUSED_RESULT_ATTR __attribute__((warn_unused_result))
-#else
-# define UNUSED_RESULT_ATTR
-#endif
MINLINE void zero_v2(float r[2]);
MINLINE void zero_v3(float r[3]);
@@ -117,10 +113,10 @@ MINLINE void mul_v3_v3(float r[3], const float a[3]);
MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void mul_v4_fl(float r[4], float f);
MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f);
-MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) UNUSED_RESULT_ATTR;
-MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) UNUSED_RESULT_ATTR;
-MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) UNUSED_RESULT_ATTR;
-MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) UNUSED_RESULT_ATTR;
+MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f);
MINLINE void madd_v3_v3v3(float r[3], const float a[3], const float b[3]);
@@ -139,10 +135,10 @@ MINLINE void negate_v4_v4(float r[4], const float a[3]);
MINLINE void negate_v3_short(short r[3]);
-MINLINE float dot_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR;
-MINLINE float dot_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR;
+MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float cross_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR;
+MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]);
@@ -151,20 +147,20 @@ MINLINE void star_m3_v3(float rmat[3][3], float a[3]);
/*********************************** Length **********************************/
-MINLINE float len_squared_v2(const float v[2]) UNUSED_RESULT_ATTR;
-MINLINE float len_squared_v3(const float v[3]) UNUSED_RESULT_ATTR;
-MINLINE float len_manhattan_v2(const float v[2]) UNUSED_RESULT_ATTR;
-MINLINE int len_manhattan_v2_int(const int v[2]) UNUSED_RESULT_ATTR;
-MINLINE float len_manhattan_v3(const float v[3]) UNUSED_RESULT_ATTR;
-MINLINE float len_v2(const float a[2]) UNUSED_RESULT_ATTR;
-MINLINE float len_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR;
-MINLINE float len_squared_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR;
-MINLINE float len_squared_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR;
-MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR;
-MINLINE int len_manhattan_v2v2_int(const int a[2], const int b[2]) UNUSED_RESULT_ATTR;
-MINLINE float len_manhattan_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR;
-MINLINE float len_v3(const float a[3]) UNUSED_RESULT_ATTR;
-MINLINE float len_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR;
+MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_manhattan_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE int len_manhattan_v2_int(const int v[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE int len_manhattan_v2v2_int(const int a[2], const int b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_manhattan_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float normalize_v2(float r[2]);
MINLINE float normalize_v2_v2(float r[2], const float a[2]);
@@ -196,35 +192,41 @@ void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]);
/********************************* Comparison ********************************/
-MINLINE int is_zero_v3(const float a[3]) UNUSED_RESULT_ATTR;
-MINLINE int is_zero_v4(const float a[4]) UNUSED_RESULT_ATTR;
-MINLINE int is_one_v3(const float a[3]) UNUSED_RESULT_ATTR;
+MINLINE bool is_zero_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool is_zero_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT;
+
+MINLINE bool is_finite_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool is_finite_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool is_finite_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT;
+
+MINLINE bool is_one_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE int equals_v2v2(const float v1[2], const float v2[2]) UNUSED_RESULT_ATTR;
-MINLINE int equals_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR;
-MINLINE int compare_v2v2(const float a[2], const float b[2], const float limit) UNUSED_RESULT_ATTR;
-MINLINE int compare_v3v3(const float a[3], const float b[3], const float limit) UNUSED_RESULT_ATTR;
-MINLINE int compare_len_v3v3(const float a[3], const float b[3], const float limit) UNUSED_RESULT_ATTR;
+MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_v2v2(const float a[2], const float b[2], const float limit) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_len_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
-MINLINE int compare_v4v4(const float a[4], const float b[4], const float limit) UNUSED_RESULT_ATTR;
-MINLINE int equals_v4v4(const float a[4], const float b[4]) UNUSED_RESULT_ATTR;
+MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) UNUSED_RESULT_ATTR;
+MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) ATTR_WARN_UNUSED_RESULT;
/********************************** Angles ***********************************/
/* - angle with 2 arguments is angle between vector */
/* - angle with 3 arguments is angle between 3 points at the middle point */
/* - angle_normalized_* is faster equivalent if vectors are normalized */
-float angle_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR;
-float angle_signed_v2v2(const float v1[2], const float v2[2]) UNUSED_RESULT_ATTR;
-float angle_v2v2v2(const float a[2], const float b[2], const float c[2]) UNUSED_RESULT_ATTR;
-float angle_normalized_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR;
-float angle_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR;
-float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) UNUSED_RESULT_ATTR;
-float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) UNUSED_RESULT_ATTR;
-float angle_normalized_v3v3(const float v1[3], const float v2[3]) UNUSED_RESULT_ATTR;
-float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) UNUSED_RESULT_ATTR;
+float angle_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+float angle_signed_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT;
+float angle_v2v2v2(const float a[2], const float b[2], const float c[2]) ATTR_WARN_UNUSED_RESULT;
+float angle_normalized_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT;
+float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) ATTR_WARN_UNUSED_RESULT;
+float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT;
+float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT;
void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3]);
void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
void angle_poly_v3(float *angles, const float *verts[3], int len);
@@ -260,7 +262,7 @@ void axis_sort_v3(const float axis_values[3], int r_axis_order[3]);
/***************************** Array Functions *******************************/
/* attempted to follow fixed length vertex functions. names could be improved*/
-double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) UNUSED_RESULT_ATTR;
+double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) ATTR_WARN_UNUSED_RESULT;
float normalize_vn_vn(float *array_tar, const float *array_src, const int size);
float normalize_vn(float *array_tar, const int size);
void range_vn_i(int *array_tar, const int size, const int start);
@@ -291,7 +293,6 @@ void fill_vn_fl(float *array_tar, const int size, const float val);
#ifdef BLI_MATH_GCC_WARN_PRAGMA
# pragma GCC diagnostic pop
#endif
-#undef UNUSED_RESULT_ATTR
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
index d54dab42e05..9ff4883c89c 100644
--- a/source/blender/blenlib/BLI_memarena.h
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -41,62 +41,28 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
/* A reasonable standard buffer size, big
* enough to not cause much internal fragmentation,
* small enough not to waste resources
*/
#define BLI_MEMARENA_STD_BUFSIZE (1 << 14)
-/* some GNU attributes are only available from GCC 4.3 */
-#define MEM_GNU_ATTRIBUTES (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403))
-
struct MemArena;
typedef struct MemArena MemArena;
-struct MemArena *BLI_memarena_new(const int bufsize, const char *name)
-#if MEM_GNU_ATTRIBUTES
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull(2)))
-#endif
-;
-
-void BLI_memarena_free(struct MemArena *ma)
-#if MEM_GNU_ATTRIBUTES
-__attribute__((nonnull(1)))
-#endif
-;
-
-void BLI_memarena_use_malloc(struct MemArena *ma)
-#if MEM_GNU_ATTRIBUTES
-__attribute__((nonnull(1)))
-#endif
-;
-void BLI_memarena_use_calloc(struct MemArena *ma)
-#if MEM_GNU_ATTRIBUTES
-__attribute__((nonnull(1)))
-#endif
-;
-
-void BLI_memarena_use_align(struct MemArena *ma, const int align)
-#if MEM_GNU_ATTRIBUTES
-__attribute__((nonnull(1)))
-#endif
-;
+struct MemArena *BLI_memarena_new(const int bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC;
+void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1);
+void BLI_memarena_use_malloc(struct MemArena *ma) ATTR_NONNULL(1);
+void BLI_memarena_use_calloc(struct MemArena *ma) ATTR_NONNULL(1);
+void BLI_memarena_use_align(struct MemArena *ma, const int align) ATTR_NONNULL(1);
+void *BLI_memarena_alloc(struct MemArena *ma, int size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2);
-void *BLI_memarena_alloc(struct MemArena *ma, int size)
-#if MEM_GNU_ATTRIBUTES
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull(1)))
-__attribute__((alloc_size(2)))
-#endif
-;
+void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1);
#ifdef __cplusplus
}
#endif
-
-#endif
-
+#endif /* __BLI_MEMARENA_H__ */
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 1c470d59062..3fab77f2cb2 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -39,6 +39,8 @@ extern "C"
{
#endif
+#include "BLI_compiler_attrs.h"
+
struct BLI_mempool;
struct BLI_mempool_chunk;
@@ -48,81 +50,33 @@ typedef struct BLI_mempool BLI_mempool;
* first four bytes of the elements never contain the character string
* 'free'. use with care.*/
-BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-#endif
-;
-void *BLI_mempool_alloc(BLI_mempool *pool)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull(1)))
-#endif
-;
-void *BLI_mempool_calloc(BLI_mempool *pool)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull(1)))
-#endif
-;
-void BLI_mempool_free(BLI_mempool *pool, void *addr)
-#ifdef __GNUC__
-__attribute__((nonnull(1, 2)))
-#endif
-;
-void BLI_mempool_destroy(BLI_mempool *pool)
-#ifdef __GNUC__
-__attribute__((nonnull(1)))
-#endif
-;
-int BLI_mempool_count(BLI_mempool *pool)
-#ifdef __GNUC__
-__attribute__((nonnull(1)))
-#endif
-;
-void *BLI_mempool_findelem(BLI_mempool *pool, int index)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull(1)))
-#endif
-;
-void BLI_mempool_as_table(BLI_mempool *pool, void **data)
-#ifdef __GNUC__
-__attribute__((nonnull(1, 2)))
-#endif
-;
-
-void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull(1, 2)))
-#endif
-;
+BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem,
+ unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+void *BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void *BLI_mempool_calloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void BLI_mempool_free(BLI_mempool *pool, void *addr) ATTR_NONNULL(1, 2);
+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);
+void *BLI_mempool_findelem(BLI_mempool *pool, unsigned int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
-void BLI_mempool_as_array(BLI_mempool *pool, void *data)
-#ifdef __GNUC__
-__attribute__((nonnull(1, 2)))
-#endif
-;
+void BLI_mempool_as_table(BLI_mempool *pool, void **data) ATTR_NONNULL(1, 2);
+void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
+void BLI_mempool_as_array(BLI_mempool *pool, void *data) ATTR_NONNULL(1, 2);
+void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
-void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull(1, 2)))
+#ifdef DEBUG
+void BLI_mempool_set_memory_debug(void);
#endif
-;
/** iteration stuff. note: this may easy to produce bugs with **/
/* private structure */
typedef struct BLI_mempool_iter {
BLI_mempool *pool;
struct BLI_mempool_chunk *curchunk;
- int curindex;
+ unsigned int curindex;
} BLI_mempool_iter;
/* flag */
@@ -131,17 +85,8 @@ enum {
BLI_MEMPOOL_ALLOW_ITER = (1 << 1)
};
-void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
-#ifdef __GNUC__
-__attribute__((nonnull(1, 2)))
-#endif
-;
-void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull(1)))
-#endif
-;
+void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL();
+void *BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index cb812fe8595..d4c5d5fed9f 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -35,6 +35,8 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
struct ListBase;
struct direntry;
@@ -90,17 +92,9 @@ void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t d
void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen);
void BLI_split_file_part(const char *string, char *file, const size_t filelen);
void BLI_path_append(char *__restrict dst, const size_t maxlen,
- const char *__restrict file)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+ const char *__restrict file) ATTR_NONNULL();
void BLI_join_dirfile(char *__restrict string, const size_t maxlen,
- const char *__restrict dir, const char *__restrict file)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+ const char *__restrict dir, const char *__restrict file) ATTR_NONNULL();
const char *BLI_path_basename(const char *path);
typedef enum bli_rebase_state {
@@ -122,6 +116,7 @@ bool BLI_testextensie_array(const char *str, const char **ext_array);
bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch);
bool BLI_replace_extension(char *path, size_t maxlen, const char *ext);
bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext);
+bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename);
void BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, short name_offs, short len);
bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
void *arg, const char * defname, char delim, char *name, short name_len);
@@ -131,11 +126,7 @@ void BLI_stringenc(char *string, const char *head, const char *tail, unsigned sh
int BLI_split_name_num(char *left, int *nr, const char *name, const char delim);
/* make sure path separators conform to system one */
-void BLI_clean(char *path)
-#ifdef __GNUC__
-__attribute__((nonnull(1)))
-#endif
-;
+void BLI_clean(char *path) ATTR_NONNULL();
/**
* dir can be any input, like from buttons, and this function
@@ -181,11 +172,7 @@ bool BLI_path_is_rel(const char *path);
# define BLI_path_ncmp strncmp
#endif
-void BLI_char_switch(char *string, char from, char to)
-#ifdef __GNUC__
-__attribute__((nonnull(1)))
-#endif
-;
+void BLI_char_switch(char *string, char from, char to) ATTR_NONNULL();
/* Initialize path to program executable */
void BLI_init_program_path(const char *argv0);
diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h
index 21197670640..e7d2130e473 100644
--- a/source/blender/blenlib/BLI_scanfill.h
+++ b/source/blender/blenlib/BLI_scanfill.h
@@ -46,20 +46,13 @@ typedef struct ScanFillContext {
ListBase filledgebase;
ListBase fillfacebase;
- /* simple optimization for allocating thousands of small memory blocks
- * only to be used within loops, and not by one function at a time
- * free in the end, with argument '-1'
- */
-#define MEM_ELEM_BLOCKSIZE 16384
- struct mem_elements *melem__cur;
- int melem__offs; /* the current free address */
- ListBase melem__lb;
-
/* private */
struct ScanFillVertLink *_scdata;
+ struct MemArena *arena;
} ScanFillContext;
-/* note; changing this also might affect the undo copy in editmesh.c */
+#define BLI_SCANFILL_ARENA_SIZE 16384
+
typedef struct ScanFillVert {
struct ScanFillVert *next, *prev;
union {
@@ -68,10 +61,10 @@ typedef struct ScanFillVert {
intptr_t l;
unsigned int u;
} tmp;
- float co[3]; /* vertex location */
- float xy[2]; /* 2D copy of vertex location (using dominant axis) */
- unsigned int keyindex; /* original index #, for restoring key information */
- short poly_nr;
+ float co[3]; /* vertex location */
+ float xy[2]; /* 2D projection of vertex location */
+ unsigned int keyindex; /* index, caller can use how it likes to match the scanfill result with own data */
+ unsigned short poly_nr;
unsigned char edge_tot; /* number of edges using this vertex */
unsigned char f;
} ScanFillVert;
@@ -79,7 +72,7 @@ typedef struct ScanFillVert {
typedef struct ScanFillEdge {
struct ScanFillEdge *next, *prev;
struct ScanFillVert *v1, *v2;
- short poly_nr;
+ unsigned short poly_nr;
unsigned char f;
union {
unsigned char c;
@@ -91,7 +84,7 @@ typedef struct ScanFillFace {
struct ScanFillVert *v1, *v2, *v3;
} ScanFillFace;
-/* scanfill.c: used in displist only... */
+/* scanfill.c */
struct ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]);
struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2);
@@ -108,11 +101,14 @@ enum {
BLI_SCANFILL_CALC_HOLES = (1 << 2)
};
void BLI_scanfill_begin(ScanFillContext *sf_ctx);
-int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag);
-int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag,
+unsigned int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag);
+unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag,
const float nor_proj[3]);
void BLI_scanfill_end(ScanFillContext *sf_ctx);
+void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, struct MemArena *arena);
+void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, struct MemArena *arena);
+
/* These callbacks are needed to make the lib finction properly */
void BLI_setErrorCallBack(void (*f)(const char *));
diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h
index 275599a612c..4f5446043da 100644
--- a/source/blender/blenlib/BLI_smallhash.h
+++ b/source/blender/blenlib/BLI_smallhash.h
@@ -37,6 +37,8 @@
/* based on a doubling non-chaining approach */
+#include "BLI_compiler_attrs.h"
+
typedef struct {
uintptr_t key;
void *val;
@@ -59,27 +61,15 @@ typedef struct {
unsigned int i;
} SmallHashIter;
-#ifdef __GNUC__
-# define ATTR_NONULL_FIRST __attribute__((nonnull(1)))
-# define ATTR_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-# define ATTR_NONULL_FIRST
-# define ATTR_UNUSED_RESULT
-#endif
-
-
-void BLI_smallhash_init(SmallHash *hash) ATTR_NONULL_FIRST;
-void BLI_smallhash_release(SmallHash *hash) ATTR_NONULL_FIRST;
-void BLI_smallhash_insert(SmallHash *hash, uintptr_t key, void *item) ATTR_NONULL_FIRST;
-void BLI_smallhash_remove(SmallHash *hash, uintptr_t key) ATTR_NONULL_FIRST;
-void *BLI_smallhash_lookup(SmallHash *hash, uintptr_t key) ATTR_NONULL_FIRST ATTR_UNUSED_RESULT;
-int BLI_smallhash_haskey(SmallHash *hash, uintptr_t key) ATTR_NONULL_FIRST;
-int BLI_smallhash_count(SmallHash *hash) ATTR_NONULL_FIRST;
-void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONULL_FIRST ATTR_UNUSED_RESULT;
-void *BLI_smallhash_iternew(SmallHash *hash, SmallHashIter *iter, uintptr_t *key) ATTR_NONULL_FIRST ATTR_UNUSED_RESULT;
+void BLI_smallhash_init(SmallHash *hash) ATTR_NONNULL(1);
+void BLI_smallhash_release(SmallHash *hash) ATTR_NONNULL(1);
+void BLI_smallhash_insert(SmallHash *hash, uintptr_t key, void *item) ATTR_NONNULL(1);
+void BLI_smallhash_remove(SmallHash *hash, uintptr_t key) ATTR_NONNULL(1);
+void *BLI_smallhash_lookup(SmallHash *hash, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+int BLI_smallhash_haskey(SmallHash *hash, uintptr_t key) ATTR_NONNULL(1);
+int BLI_smallhash_count(SmallHash *hash) ATTR_NONNULL(1);
+void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+void *BLI_smallhash_iternew(SmallHash *hash, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/* void BLI_smallhash_print(SmallHash *hash); */ /* UNUSED */
-#undef ATTR_NONULL_FIRST
-#undef ATTR_UNUSED_RESULT
-
#endif /* __BLI_SMALLHASH_H__ */
diff --git a/source/blender/compositor/operations/COM_MixColorOperation.h b/source/blender/blenlib/BLI_sort.h
index 1409d726f03..4df17d98a4b 100644
--- a/source/blender/compositor/operations/COM_MixColorOperation.h
+++ b/source/blender/blenlib/BLI_sort.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * ***** 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
@@ -15,31 +15,31 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Benoit Bolsee,
+ * Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
-#ifndef _COM_MixColorOperation_h
-#define _COM_MixColorOperation_h
-#include "COM_MixBaseOperation.h"
+#ifndef __BLI_SORT_H__
+#define __BLI_SORT_H__
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
+/** \file BLI_sort.h
+ * \ingroup bli
*/
-class MixColorOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixColorOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-};
+/* Quick sort reentrant */
+typedef int (*BLI_sort_cmp_t)(void *ctx, const void *a, const void *b);
+
+void BLI_qsort_r(void *a, size_t n, size_t es, void *thunk, BLI_sort_cmp_t cmp)
+#ifdef __GNUC__
+__attribute__((nonnull(1, 5)))
#endif
+;
+
+#endif /* __BLI_SORT_H__ */
diff --git a/source/blender/blenlib/BLI_sort_utils.h b/source/blender/blenlib/BLI_sort_utils.h
new file mode 100644
index 00000000000..e08f4e5ac83
--- /dev/null
+++ b/source/blender/blenlib/BLI_sort_utils.h
@@ -0,0 +1,61 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_SORT_UTILS_H__
+#define __BLI_SORT_UTILS_H__
+
+/** \file BLI_sort_utils.h
+ * \ingroup bli
+ */
+
+/**
+ * \note keep \a sort_value first,
+ * so cmp functions can be reused.
+ */
+struct SortPointerByFloat {
+ float sort_value;
+ void *data;
+};
+
+struct SortIntByFloat {
+ float sort_value;
+ int data;
+};
+
+struct SortPointerByInt {
+ int sort_value;
+ void *data;
+};
+
+struct SortIntByInt {
+ int sort_value;
+ int data;
+};
+
+int BLI_sortutil_cmp_float(const void *a_, const void *b_);
+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_);
+
+#endif /* __BLI_SORT_UTILS_H__ */
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h b/source/blender/blenlib/BLI_strict_flags.h
index 9d3ab156555..5c5a6f45f0c 100644
--- a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h
+++ b/source/blender/blenlib/BLI_strict_flags.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012, Blender Foundation.
+ * ***** 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
@@ -15,34 +15,27 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Dalai Felinto
+ * ***** END GPL LICENSE BLOCK *****
*/
-#ifndef _COM_ConvertPremulToStraightOperation_h
-#define _COM_ConvertPremulToStraightOperation_h
-#include "COM_NodeOperation.h"
+#ifndef __BLI_STRICT_FLAGS_H__
+#define __BLI_STRICT_FLAGS_H__
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
+/** \file BLI_strict_flags.h
+ * \ingroup bli
+ * \brief Strict compiler flags for areas of code we want
+ * to ensure don't do conversions without us knowing about it.
*/
-class ConvertPremulToStraightOperation : public NodeOperation {
-private:
- SocketReader *m_inputColor;
-public:
- /**
- * Default constructor
- */
- ConvertPremulToStraightOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
- void initExecution();
- void deinitExecution();
-};
+#ifdef __GNUC__
+# pragma GCC diagnostic error "-Wsign-conversion"
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
+# pragma GCC diagnostic error "-Wsign-compare"
+# pragma GCC diagnostic error "-Wconversion"
+# endif
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 /* gcc4.8+ only (behavior changed to ignore globals)*/
+# pragma GCC diagnostic error "-Wshadow"
+# endif
#endif
+
+#endif /* __BLI_STRICT_FLAGS_H__ */
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 6c66d2f4e18..b995f2565e1 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -38,152 +38,43 @@
extern "C" {
#endif
-char *BLI_strdupn(const char *str, const size_t len)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+#include "BLI_compiler_attrs.h"
-char *BLI_strdup(const char *str)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+char *BLI_strdupn(const char *str, const size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+char *BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
-char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
-size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL();
-size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
-size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 3, 4)))
-__attribute__((nonnull))
-#endif
-;
+char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
-size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 3, 0)))
-#endif
-;
-
-char *BLI_sprintfN(const char *__restrict format, ...)
-#ifdef __GNUC__
-__attribute__((malloc))
-__attribute__ ((format(printf, 1, 2)))
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL() ATTR_PRINTF_FORMAT(3, 4);
-size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0);
-int BLI_strcaseeq(const char *a, const char *b)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
+char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2);
-char *BLI_strcasestr(const char *s, const char *find)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-int BLI_strcasecmp(const char *s1, const char *s2)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-int BLI_strncasecmp(const char *s1, const char *s2, size_t len)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-int BLI_natstrcmp(const char *s1, const char *s2)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-size_t BLI_strnlen(const char *str, const size_t maxlen)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-__attribute__((nonnull))
-#endif
-;
-void BLI_timestr(double _time, char *str, size_t maxlen)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL();
-void BLI_ascii_strtolower(char *str, const size_t len)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-void BLI_ascii_strtoupper(char *str, const size_t len)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
-int BLI_str_rstrip_float_zero(char *str, const char pad)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_natstrcmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+size_t BLI_strnlen(const char *str, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BLI_timestr(double _time, char *str, size_t maxlen) ATTR_NONNULL();
+
+void BLI_ascii_strtolower(char *str, const size_t len) ATTR_NONNULL();
+void BLI_ascii_strtoupper(char *str, const size_t len) ATTR_NONNULL();
+int BLI_str_rstrip_float_zero(char *str, const char pad) ATTR_NONNULL();
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index db32190494a..4aef2318683 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -31,57 +31,45 @@
extern "C" {
#endif
-#ifdef __GNUC__
-# define ATTR_NONULL __attribute__((nonnull))
-# define ATTR_NONULL_FIRST __attribute__((nonnull(1)))
-# define ATTR_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-# define ATTR_NONULL
-# define ATTR_NONULL_FIRST
-# define ATTR_UNUSED_RESULT
-#endif
+#include "BLI_compiler_attrs.h"
-char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONULL;
-char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONULL;
-int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONULL;
-int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONULL;
+char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
+char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
+int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONNULL();
+int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONNULL();
-int BLI_str_utf8_size(const char *p) ATTR_NONULL; /* warning, can return -1 on bad chars */
-int BLI_str_utf8_size_safe(const char *p) ATTR_NONULL;
+int BLI_str_utf8_size(const char *p) ATTR_NONNULL(); /* warning, can return -1 on bad chars */
+int BLI_str_utf8_size_safe(const char *p) ATTR_NONNULL();
/* copied from glib */
-unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_NONULL;
-unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) ATTR_NONULL;
-unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index) ATTR_NONULL;
-unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) ATTR_NONULL;
+unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_NONNULL();
+unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) ATTR_NONNULL();
+unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index) ATTR_NONNULL();
+unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) ATTR_NONNULL();
size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf);
-char *BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONULL;
-char *BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONULL_FIRST;
-char *BLI_str_prev_char_utf8(const char *p) ATTR_NONULL;
+char *BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONNULL();
+char *BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONNULL(1);
+char *BLI_str_prev_char_utf8(const char *p) ATTR_NONNULL();
/* wchar_t functions, copied from blenders own font.c originally */
-size_t BLI_wstrlen_utf8(const wchar_t *src) ATTR_NONULL;
-size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONULL;
-size_t BLI_strlen_utf8(const char *strc) ATTR_NONULL;
-size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_bytes) ATTR_NONULL;
-size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen) ATTR_NONULL;
-size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy) ATTR_NONULL;
-size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy) ATTR_NONULL;
+size_t BLI_wstrlen_utf8(const wchar_t *src) ATTR_NONNULL();
+size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONNULL();
+size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL();
+size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_bytes) ATTR_NONNULL();
+size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen) ATTR_NONNULL();
+size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy) ATTR_NONNULL();
+size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy) ATTR_NONNULL();
/* count columns that character/string occupies, based on wcwidth.c */
int BLI_wcwidth(wchar_t ucs);
-int BLI_wcswidth(const wchar_t *pwcs, size_t n) ATTR_NONULL;
-int BLI_str_utf8_char_width(const char *p) ATTR_NONULL; /* warning, can return -1 on bad chars */
-int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONULL;
+int BLI_wcswidth(const wchar_t *pwcs, size_t n) ATTR_NONNULL();
+int BLI_str_utf8_char_width(const char *p) ATTR_NONNULL(); /* warning, can return -1 on bad chars */
+int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONNULL();
#define BLI_UTF8_MAX 6 /* mem */
#define BLI_UTF8_WIDTH_MAX 2 /* columns */
#define BLI_UTF8_ERR ((unsigned int)-1)
-#undef ATTR_NONULL
-#undef ATTR_NONULL_FIRST
-#undef ATTR_UNUSED_RESULT
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index 154986936a2..38ad0827246 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -50,6 +50,7 @@ struct ListBase;
/*this is run once at startup*/
void BLI_threadapi_init(void);
+void BLI_threadapi_exit(void);
void BLI_init_threads(struct ListBase *threadbase, void *(*do_thread)(void *), int tot);
int BLI_available_threads(struct ListBase *threadbase);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 63235ad9c82..c3a3c035ed3 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -113,7 +113,7 @@
/* can be used in simple macros */
#define CHECK_TYPE_INLINE(val, type) \
- ((void)(((type *)0) != (val)))
+ ((void)(((type)0) != (val)))
#define SWAP(type, a, b) { \
type sw_ap; \
@@ -337,12 +337,6 @@
# define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif
-#ifdef __GNUC__
-# define WARN_UNUSED __attribute__((warn_unused_result))
-#else
-# define WARN_UNUSED
-#endif
-
/*little macro so inline keyword works*/
#if defined(_MSC_VER)
# define BLI_INLINE static __forceinline
diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h
index 20a4c3c274e..e75ec7eef2c 100644
--- a/source/blender/blenlib/BLI_winstuff.h
+++ b/source/blender/blenlib/BLI_winstuff.h
@@ -100,7 +100,6 @@ extern "C" {
// not accepted by access() on windows
//# define X_OK 1
# define F_OK 0
-# define PATH_MAX 4096
#endif
#ifndef FREE_WINDOWS
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index b6b69116e67..65ba545ef13 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -25,7 +25,7 @@
# XXX allowing blenkernel and RNA includes in blenlib is a hack,
# but needed in a few places atm (bpath.c for instance)
-set(INC
+set(INC
.
# ../blenkernel # dont add this back!
../makesdna
@@ -54,6 +54,7 @@ set(SRC
intern/boxpack2d.c
intern/buffer.c
intern/callbacks.c
+ intern/convexhull2d.c
intern/cpu.c
intern/dynlib.c
intern/edgehash.c
@@ -86,6 +87,8 @@ set(SRC
intern/rct.c
intern/scanfill.c
intern/smallhash.c
+ intern/sort.c
+ intern/sort_utils.c
intern/stack.c
intern/storage.c
intern/string.c
@@ -98,14 +101,16 @@ set(SRC
intern/voxel.c
intern/winstuff.c
- BLI_args.h
BLI_alloca.h
+ BLI_args.h
BLI_array.h
BLI_bitmap.h
BLI_blenlib.h
- BLI_buffer.h
BLI_boxpack2d.h
+ BLI_buffer.h
BLI_callbacks.h
+ BLI_compiler_attrs.h
+ BLI_convexhull2d.h
BLI_cpu.h
BLI_dlrbTree.h
BLI_dynlib.h
@@ -125,6 +130,7 @@ set(SRC
BLI_kdtree.h
BLI_lasso.h
BLI_linklist.h
+ BLI_linklist_stack.h
BLI_listbase.h
BLI_math.h
BLI_math_base.h
@@ -146,7 +152,10 @@ set(SRC
BLI_rect.h
BLI_scanfill.h
BLI_smallhash.h
+ BLI_sort.h
+ BLI_sort_utils.h
BLI_stack.h
+ BLI_strict_flags.h
BLI_string.h
BLI_string_cursor_utf8.h
BLI_string_utf8.h
@@ -159,6 +168,7 @@ set(SRC
BLI_voxel.h
BLI_winstuff.h
PIL_time.h
+ PIL_time_utildefines.h
)
if(WITH_BINRELOC)
@@ -168,6 +178,10 @@ if(WITH_BINRELOC)
add_definitions(-DWITH_BINRELOC)
endif()
+if(WITH_MEM_VALGRIND)
+ add_definitions(-DWITH_MEM_VALGRIND)
+endif()
+
if(WIN32)
list(APPEND INC
../../../intern/utfconv
diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h
index c3e7e8486d9..158559fa3d9 100644
--- a/source/blender/blenlib/PIL_time.h
+++ b/source/blender/blenlib/PIL_time.h
@@ -51,44 +51,8 @@ double PIL_check_seconds_timer(void);
*/
void PIL_sleep_ms(int ms);
-/** Utility defines for timing.
- * requires BLI_utildefines.h for 'AT'
- * TIMEIT_VALUE returns the time since TIMEIT_START was called.
- */
-#define TIMEIT_START(var) \
- { \
- double _timeit_##var = PIL_check_seconds_timer(); \
- printf("time start (" #var "): " AT "\n"); \
- fflush(stdout); \
- { (void)0
-
-#define TIMEIT_VALUE(var) (float)(PIL_check_seconds_timer() - _timeit_##var)
-
-#define TIMEIT_VALUE_PRINT(var) \
- { \
- printf("time update(" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var));\
- fflush(stdout); \
- } (void)0
-
-#define TIMEIT_END(var) \
- } \
- printf("time end (" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var)); \
- fflush(stdout); \
-} (void)0
-
-/**
- * Given some function/expression:
- * TIMEIT_BENCH(some_function(), some_unique_description);
- */
-#define TIMEIT_BENCH(expr, id) \
- { \
- TIMEIT_START(id); \
- (expr); \
- TIMEIT_END(id); \
- } (void)0
-
#ifdef __cplusplus
}
#endif
-#endif /* !__PIL_TIME_H__ */
+#endif /* __PIL_TIME_H__ */
diff --git a/source/blender/blenlib/PIL_time_utildefines.h b/source/blender/blenlib/PIL_time_utildefines.h
new file mode 100644
index 00000000000..135817f6a17
--- /dev/null
+++ b/source/blender/blenlib/PIL_time_utildefines.h
@@ -0,0 +1,96 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/PIL_time_utildefines.h
+ * \ingroup bli
+ * \brief Utility defines for timing/benchmarks.
+ */
+
+#ifndef __PIL_TIME_UTILDEFINES_H__
+#define __PIL_TIME_UTILDEFINES_H__
+
+#include "PIL_time.h" /* for PIL_check_seconds_timer */
+#include "BLI_utildefines.h" /* for AT */
+
+#define TIMEIT_START(var) \
+ { \
+ double _timeit_##var = PIL_check_seconds_timer(); \
+ printf("time start (" #var "): " AT "\n"); \
+ fflush(stdout); \
+ { (void)0
+
+/**
+ * \return the time since TIMEIT_START was called.
+ */
+#define TIMEIT_VALUE(var) (float)(PIL_check_seconds_timer() - _timeit_##var)
+
+#define TIMEIT_VALUE_PRINT(var) \
+ { \
+ printf("time update(" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var));\
+ fflush(stdout); \
+ } (void)0
+
+#define TIMEIT_END(var) \
+ } \
+ printf("time end (" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var)); \
+ fflush(stdout); \
+} (void)0
+
+/**
+ * Given some function/expression:
+ * TIMEIT_BENCH(some_function(), some_unique_description);
+ */
+#define TIMEIT_BENCH(expr, id) \
+ { \
+ TIMEIT_START(id); \
+ (expr); \
+ TIMEIT_END(id); \
+ } (void)0
+
+#define TIMEIT_BLOCK_INIT(id) \
+ double _timeit_var_##id = 0; \
+ (void) 0
+
+#define TIMEIT_BLOCK_START(id) \
+ { \
+ double _timeit_block_start_##id = PIL_check_seconds_timer(); \
+ { (void)0
+
+#define TIMEIT_BLOCK_END(id) \
+ } \
+ _timeit_var_##id += (PIL_check_seconds_timer() - \
+ _timeit_block_start_##id); \
+ } (void)0
+
+#define TIMEIT_BLOCK_STATS(id) \
+ { \
+ printf("%s time (in seconds): %f\n", #id, _timeit_var_##id); \
+ fflush(stdout); \
+ } (void)0
+
+#endif /* __PIL_TIME_UTILDEFINES_H__ */
diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c
index 510bf072513..21d7a5a6d10 100644
--- a/source/blender/blenlib/intern/BLI_array.c
+++ b/source/blender/blenlib/intern/BLI_array.c
@@ -13,7 +13,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 14dfbcffebe..fcca6cd59ba 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -23,12 +23,13 @@
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
- * A general (pointer -> pointer) hash table ADT
*/
/** \file blender/blenlib/intern/BLI_ghash.c
* \ingroup bli
*
+ * A general (pointer -> pointer) hash table ADT
+ *
* \note edgehash.c is based on this, make sure they stay in sync.
*/
@@ -42,16 +43,8 @@
#include "BLI_utildefines.h"
#include "BLI_mempool.h"
#include "BLI_ghash.h"
+#include "BLI_strict_flags.h"
-/***/
-
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
-# pragma GCC diagnostic error "-Wsign-compare"
-# pragma GCC diagnostic error "-Wconversion"
-# endif
-#endif
const unsigned int hashsizes[] = {
5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209,
@@ -60,206 +53,507 @@ const unsigned int hashsizes[] = {
268435459
};
+/* internal flag to ensure sets values aren't used */
+#ifndef NDEBUG
+# define GHASH_FLAG_IS_SET (1 << 8)
+# define IS_GHASH_ASSERT(gh) BLI_assert((gh->flag & GHASH_FLAG_IS_SET) == 0)
+// # define IS_GSET_ASSERT(gs) BLI_assert((gs->flag & GHASH_FLAG_IS_SET) != 0)
+#else
+# define IS_GHASH_ASSERT(gh)
+// # define IS_GSET_ASSERT(eh)
+#endif
+
/***/
-GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info)
+typedef struct Entry {
+ struct Entry *next;
+
+ void *key, *val;
+} Entry;
+
+struct GHash {
+ GHashHashFP hashfp;
+ GHashCmpFP cmpfp;
+
+ Entry **buckets;
+ struct BLI_mempool *entrypool;
+ unsigned int nbuckets;
+ unsigned int nentries;
+ unsigned int cursize, flag;
+};
+
+
+/* -------------------------------------------------------------------- */
+/* GHash API */
+
+/** \name Internal Utility API
+ * \{ */
+
+/**
+ * Get the hash for a key.
+ */
+BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key)
+{
+ return gh->hashfp(key) % gh->nbuckets;
+}
+
+/**
+ * Check if the number of items in the GHash is large enough to require more buckets.
+ */
+BLI_INLINE bool ghash_test_expand_buckets(const unsigned int nentries, const unsigned int nbuckets)
+{
+ return (nentries > nbuckets * 3);
+}
+
+/**
+ * Expand buckets to the next size up.
+ */
+BLI_INLINE void ghash_resize_buckets(GHash *gh, const unsigned int nbuckets)
+{
+ Entry **buckets_old = gh->buckets;
+ Entry **buckets_new;
+ const unsigned int nbuckets_old = gh->nbuckets;
+ unsigned int i;
+ Entry *e;
+
+ BLI_assert(gh->nbuckets != nbuckets);
+
+ gh->nbuckets = nbuckets;
+ buckets_new = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
+
+ for (i = 0; i < nbuckets_old; i++) {
+ Entry *e_next;
+ for (e = buckets_old[i]; e; e = e_next) {
+ const unsigned hash = ghash_keyhash(gh, e->key);
+ e_next = e->next;
+ e->next = buckets_new[hash];
+ buckets_new[hash] = e;
+ }
+ }
+
+ gh->buckets = buckets_new;
+ MEM_freeN(buckets_old);
+}
+
+/**
+ * Increase initial bucket size to match a reserved ammount.
+ */
+BLI_INLINE void ghash_buckets_reserve(GHash *gh, const unsigned int nentries_reserve)
+{
+ while (ghash_test_expand_buckets(nentries_reserve, gh->nbuckets)) {
+ gh->nbuckets = hashsizes[++gh->cursize];
+ }
+}
+
+/**
+ * Internal lookup function.
+ * Takes a hash argument to avoid calling #ghash_keyhash multiple times.
+ */
+BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key,
+ const unsigned int hash)
+{
+ Entry *e;
+
+ for (e = gh->buckets[hash]; e; e = e->next) {
+ if (UNLIKELY(gh->cmpfp(key, e->key) == 0)) {
+ return e;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Internal lookup function. Only wraps #ghash_lookup_entry_ex
+ */
+BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ return ghash_lookup_entry_ex(gh, key, hash);
+}
+
+static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
+ const unsigned int nentries_reserve,
+ const unsigned int entry_size)
{
GHash *gh = MEM_mallocN(sizeof(*gh), info);
+
gh->hashfp = hashfp;
gh->cmpfp = cmpfp;
- gh->entrypool = BLI_mempool_create(sizeof(Entry), 64, 64, 0);
- gh->cursize = 0;
+ gh->nbuckets = hashsizes[0]; /* gh->cursize */
gh->nentries = 0;
- gh->nbuckets = hashsizes[gh->cursize];
+ gh->cursize = 0;
+ gh->flag = 0;
+
+ /* if we have reserved the number of elements that this hash will contain */
+ if (nentries_reserve) {
+ ghash_buckets_reserve(gh, nentries_reserve);
+ }
gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
+ gh->entrypool = BLI_mempool_create(entry_size, 64, 64, 0);
return gh;
}
-int BLI_ghash_size(GHash *gh)
-{
- return (int)gh->nentries;
-}
-
-void BLI_ghash_insert(GHash *gh, void *key, void *val)
+/**
+ * Internal insert function.
+ * Takes a hash argument to avoid calling #ghash_keyhash multiple times.
+ */
+BLI_INLINE void ghash_insert_ex(GHash *gh, void *key, void *val,
+ unsigned int hash)
{
- unsigned int hash = gh->hashfp(key) % gh->nbuckets;
Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool);
+ BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
+ IS_GHASH_ASSERT(gh);
e->next = gh->buckets[hash];
e->key = key;
e->val = val;
gh->buckets[hash] = e;
- if (UNLIKELY(++gh->nentries > gh->nbuckets / 2)) {
- Entry **old = gh->buckets;
- const unsigned nold = gh->nbuckets;
- unsigned int i;
-
- gh->nbuckets = hashsizes[++gh->cursize];
- gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
-
- for (i = 0; i < nold; i++) {
- Entry *e_next;
- for (e = old[i]; e; e = e_next) {
- e_next = e->next;
- hash = gh->hashfp(e->key) % gh->nbuckets;
- e->next = gh->buckets[hash];
- gh->buckets[hash] = e;
- }
- }
-
- MEM_freeN(old);
+ if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) {
+ ghash_resize_buckets(gh, hashsizes[++gh->cursize]);
}
}
-void *BLI_ghash_lookup(GHash *gh, const void *key)
+/**
+ * Insert function that doesn't set the value (use for GSet)
+ */
+BLI_INLINE void ghash_insert_ex_keyonly(GHash *gh, void *key,
+ unsigned int hash)
{
- const unsigned int hash = gh->hashfp(key) % gh->nbuckets;
- Entry *e;
+ Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool);
+ BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
+ e->next = gh->buckets[hash];
+ e->key = key;
+ /* intentionally leave value unset */
+ gh->buckets[hash] = e;
- for (e = gh->buckets[hash]; e; e = e->next) {
- if (gh->cmpfp(key, e->key) == 0) {
- return e->val;
- }
+ if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) {
+ ghash_resize_buckets(gh, hashsizes[++gh->cursize]);
}
- return NULL;
}
-bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ ghash_insert_ex(gh, key, val, hash);
+}
+
+/**
+ * Remove the entry and return it, caller must free from gh->entrypool.
+ */
+static Entry *ghash_remove_ex(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ unsigned int hash)
{
- unsigned int hash = gh->hashfp(key) % gh->nbuckets;
Entry *e;
- Entry *p = NULL;
+ Entry *e_prev = NULL;
for (e = gh->buckets[hash]; e; e = e->next) {
- if (gh->cmpfp(key, e->key) == 0) {
- Entry *n = e->next;
+ if (UNLIKELY(gh->cmpfp(key, e->key) == 0)) {
+ Entry *e_next = e->next;
if (keyfreefp) keyfreefp(e->key);
if (valfreefp) valfreefp(e->val);
- BLI_mempool_free(gh->entrypool, e);
- /* correct but 'e' isn't used before return */
- /* e = n; *//*UNUSED*/
- if (p) p->next = n;
- else gh->buckets[hash] = n;
+ if (e_prev) e_prev->next = e_next;
+ else gh->buckets[hash] = e_next;
gh->nentries--;
- return true;
+ return e;
}
- p = e;
+ e_prev = e;
}
- return false;
+ return NULL;
}
-void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+/**
+ * Run free callbacks for freeing entries.
+ */
+static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
unsigned int i;
- if (keyfreefp || valfreefp) {
- for (i = 0; i < gh->nbuckets; i++) {
- Entry *e;
+ BLI_assert(keyfreefp || valfreefp);
- for (e = gh->buckets[i]; e; ) {
- Entry *n = e->next;
+ for (i = 0; i < gh->nbuckets; i++) {
+ Entry *e;
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(e->val);
+ for (e = gh->buckets[i]; e; ) {
+ Entry *e_next = e->next;
- e = n;
- }
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+
+ e = e_next;
}
}
+}
+/** \} */
- gh->cursize = 0;
- gh->nentries = 0;
- gh->nbuckets = hashsizes[gh->cursize];
- MEM_freeN(gh->buckets);
- gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
-}
+/** \name Public API
+ * \{ */
-/* same as above but return the value,
- * no free value argument since it will be returned */
-void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
+/**
+ * Creates a new, empty GHash.
+ *
+ * \param hashfp Hash callback.
+ * \param cmpfp Comparison callback.
+ * \param info Identifier string for the GHash.
+ * \param nentries_reserve Optionally reserve the number of members that the hash will hold.
+ * Use this to avoid resizing buckets if the size is known or can be closely approximated.
+ * \return An empty GHash.
+ */
+GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
+ const unsigned int nentries_reserve)
{
- unsigned int hash = gh->hashfp(key) % gh->nbuckets;
- Entry *e;
- Entry *p = NULL;
+ return ghash_new(hashfp, cmpfp, info,
+ nentries_reserve,
+ (unsigned int)sizeof(Entry));
+}
- for (e = gh->buckets[hash]; e; e = e->next) {
- if (gh->cmpfp(key, e->key) == 0) {
- Entry *n = e->next;
- void *value = e->val;
+/**
+ * Wraps #BLI_ghash_new_ex with zero entries reserved.
+ */
+GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info)
+{
+ return BLI_ghash_new_ex(hashfp, cmpfp, info, 0);
+}
- if (keyfreefp) keyfreefp(e->key);
- BLI_mempool_free(gh->entrypool, e);
+/**
+ * \return size of the GHash.
+ */
+int BLI_ghash_size(GHash *gh)
+{
+ return (int)gh->nentries;
+}
- /* correct but 'e' isn't used before return */
- /* e = n; *//*UNUSED*/
- if (p) p->next = n;
- else gh->buckets[hash] = n;
+/**
+ * Insert a key/value pair into the \a gh.
+ *
+ * \note Duplicates are not checked,
+ * the caller is expected to ensure elements are unique unless
+ * GHASH_FLAG_ALLOW_DUPES flag is set.
+ */
+void BLI_ghash_insert(GHash *gh, void *key, void *val)
+{
+ ghash_insert(gh, key, val);
+}
- gh->nentries--;
- return value;
- }
- p = e;
+/**
+ * Inserts a new value to a key that may already be in ghash.
+ *
+ * Avoids #BLI_ghash_remove, #BLI_ghash_insert calls (double lookups)
+ *
+ * \returns true if a new key has been added.
+ */
+bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ Entry *e = ghash_lookup_entry_ex(gh, key, hash);
+ if (e) {
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+ e->key = key;
+ e->val = val;
+ return false;
+ }
+ else {
+ ghash_insert_ex(gh, key, val, hash);
+ return true;
}
-
- return NULL;
}
-bool BLI_ghash_haskey(GHash *gh, const void *key)
+/**
+ * Lookup the value of \a key in \a gh.
+ *
+ * \param key The key to lookup.
+ * \returns the value for \a key or NULL.
+ *
+ * \note When NULL is a valid value, use #BLI_ghash_lookup_p to differentiate a missing key
+ * from a key with a NULL value. (Avoids calling #BLI_ghash_haskey before #BLI_ghash_lookup)
+ */
+void *BLI_ghash_lookup(GHash *gh, const void *key)
{
- unsigned int hash = gh->hashfp(key) % gh->nbuckets;
- Entry *e;
+ Entry *e = ghash_lookup_entry(gh, key);
+ IS_GHASH_ASSERT(gh);
+ return e ? e->val : NULL;
+}
- for (e = gh->buckets[hash]; e; e = e->next)
- if (gh->cmpfp(key, e->key) == 0)
- return true;
+/**
+ * Lookup a pointer to the value of \a key in \a gh.
+ *
+ * \param key The key to lookup.
+ * \returns the pointer to value for \a key or NULL.
+ *
+ * \note This has 2 main benifits over #BLI_ghash_lookup.
+ * - A NULL return always means that \a key isn't in \a gh.
+ * - The value can be modified in-place without further function calls (faster).
+ */
+void **BLI_ghash_lookup_p(GHash *gh, const void *key)
+{
+ Entry *e = ghash_lookup_entry(gh, key);
+ IS_GHASH_ASSERT(gh);
+ return e ? &e->val : NULL;
+}
- return false;
+/**
+ * Remove \a key from \a gh, or return false if the key wasn't found.
+ *
+ * \param key The key to remove.
+ * \param keyfreefp Optional callback to free the key.
+ * \param valfreefp Optional callback to free the value.
+ * \return true if \a key was removed from \a gh.
+ */
+bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, hash);
+ if (e) {
+ BLI_mempool_free(gh->entrypool, e);
+ return true;
+ }
+ else {
+ return false;
+ }
}
-void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+/* same as above but return the value,
+ * no free value argument since it will be returned */
+/**
+ * Remove \a key from \a gh, returning the value or NULL if the key wasn't found.
+ *
+ * \param key The key to remove.
+ * \param keyfreefp Optional callback to free the key.
+ * \return the value of \a key int \a gh or NULL.
+ */
+void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
{
- unsigned int i;
+ const unsigned int hash = ghash_keyhash(gh, key);
+ Entry *e = ghash_remove_ex(gh, key, keyfreefp, NULL, hash);
+ IS_GHASH_ASSERT(gh);
+ if (e) {
+ void *val = e->val;
+ BLI_mempool_free(gh->entrypool, e);
+ return val;
+ }
+ else {
+ return NULL;
+ }
+}
- if (keyfreefp || valfreefp) {
- for (i = 0; i < gh->nbuckets; i++) {
- Entry *e;
+/**
+ * \return true if the \a key is in \a gh.
+ */
+bool BLI_ghash_haskey(GHash *gh, const void *key)
+{
+ return (ghash_lookup_entry(gh, key) != NULL);
+}
- for (e = gh->buckets[i]; e; ) {
- Entry *n = e->next;
+/**
+ * Reset \a gh clearing all entries.
+ *
+ * \param keyfreefp Optional callback to free the key.
+ * \param valfreefp Optional callback to free the value.
+ * \param nentries_reserve Optionally reserve the number of members that the hash will hold.
+ */
+void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ const unsigned int nentries_reserve)
+{
+ if (keyfreefp || valfreefp)
+ ghash_free_cb(gh, keyfreefp, valfreefp);
- if (keyfreefp) keyfreefp(e->key);
- if (valfreefp) valfreefp(e->val);
+ gh->nbuckets = hashsizes[0]; /* gh->cursize */
+ gh->nentries = 0;
+ gh->cursize = 0;
- e = n;
- }
- }
+ if (nentries_reserve) {
+ ghash_buckets_reserve(gh, nentries_reserve);
}
MEM_freeN(gh->buckets);
+ gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
+
+ BLI_mempool_clear_ex(gh->entrypool, nentries_reserve ? (int)nentries_reserve : -1);
+}
+
+/**
+ * Wraps #BLI_ghash_clear_ex with zero entries reserved.
+ */
+void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ BLI_ghash_clear_ex(gh, keyfreefp, valfreefp, 0);
+}
+
+/**
+ * Frees the GHash and its members.
+ *
+ * \param gh The GHash to free.
+ * \param keyfreefp Optional callback to free the key.
+ * \param valfreefp Optional callback to free the value.
+ */
+void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ BLI_assert((int)gh->nentries == BLI_mempool_count(gh->entrypool));
+ if (keyfreefp || valfreefp)
+ ghash_free_cb(gh, keyfreefp, valfreefp);
+
+ MEM_freeN(gh->buckets);
BLI_mempool_destroy(gh->entrypool);
- gh->buckets = NULL;
- gh->nentries = 0;
- gh->nbuckets = 0;
MEM_freeN(gh);
}
-/***/
+/**
+ * Sets a GHash flag.
+ */
+void BLI_ghash_flag_set(GHash *gh, unsigned int flag)
+{
+ gh->flag |= flag;
+}
+/**
+ * Clear a GHash flag.
+ */
+void BLI_ghash_flag_clear(GHash *gh, unsigned int flag)
+{
+ gh->flag &= ~flag;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* GHash Iterator API */
+
+/** \name Iterator API
+ * \{ */
+
+/**
+ * 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.
+ *
+ * \param gh The GHash to iterate over.
+ * \return Pointer to a new DynStr.
+ */
GHashIterator *BLI_ghashIterator_new(GHash *gh)
{
GHashIterator *ghi = MEM_mallocN(sizeof(*ghi), "ghash iterator");
BLI_ghashIterator_init(ghi, gh);
return ghi;
}
+
+/**
+ * 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.
+ *
+ * \param ghi The GHashIterator to initialize.
+ * \param gh The GHash to iterate over.
+ */
void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
{
ghi->gh = gh;
@@ -272,20 +566,58 @@ void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
ghi->curEntry = ghi->gh->buckets[ghi->curBucket];
}
}
+
+/**
+ * Free a GHashIterator.
+ *
+ * \param ghi The iterator to free.
+ */
void BLI_ghashIterator_free(GHashIterator *ghi)
{
MEM_freeN(ghi);
}
+/**
+ * Retrieve the key from an iterator.
+ *
+ * \param ghi The iterator.
+ * \return The key at the current index, or NULL if the
+ * iterator is done.
+ */
void *BLI_ghashIterator_getKey(GHashIterator *ghi)
{
return ghi->curEntry ? ghi->curEntry->key : NULL;
}
+
+/**
+ * Retrieve the value from an iterator.
+ *
+ * \param ghi The iterator.
+ * \return The value at the current index, or NULL if the
+ * iterator is done.
+ */
void *BLI_ghashIterator_getValue(GHashIterator *ghi)
{
return ghi->curEntry ? ghi->curEntry->val : NULL;
}
+/**
+ * Retrieve the value from an iterator.
+ *
+ * \param ghi The iterator.
+ * \return The value at the current index, or NULL if the
+ * iterator is done.
+ */
+void **BLI_ghashIterator_getValue_p(GHashIterator *ghi)
+{
+ return ghi->curEntry ? &ghi->curEntry->val : NULL;
+}
+
+/**
+ * Steps the iterator to the next index.
+ *
+ * \param ghi The iterator.
+ */
void BLI_ghashIterator_step(GHashIterator *ghi)
{
if (ghi->curEntry) {
@@ -298,17 +630,44 @@ void BLI_ghashIterator_step(GHashIterator *ghi)
}
}
}
+
+/**
+ * Determine if an iterator is done (has reached the end of
+ * the hash table).
+ *
+ * \param ghi The iterator.
+ * \return True if done, False otherwise.
+ */
bool BLI_ghashIterator_done(GHashIterator *ghi)
{
return ghi->curEntry == NULL;
}
+/** \} */
+
+
+/** \name Generic Key Hash & Comparison Functions
+ * \{ */
+
/***/
+#if 0
+/* works but slower */
unsigned int BLI_ghashutil_ptrhash(const void *key)
{
return (unsigned int)(intptr_t)key;
}
+#else
+/* based python3.3's pointer hashing function */
+unsigned int 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 (unsigned int)y;
+}
+#endif
int BLI_ghashutil_ptrcmp(const void *a, const void *b)
{
if (a == b)
@@ -364,23 +723,6 @@ int BLI_ghashutil_strcmp(const void *a, const void *b)
return strcmp(a, b);
}
-GHash *BLI_ghash_ptr_new(const char *info)
-{
- return BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info);
-}
-GHash *BLI_ghash_str_new(const char *info)
-{
- return BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, info);
-}
-GHash *BLI_ghash_int_new(const char *info)
-{
- return BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, info);
-}
-GHash *BLI_ghash_pair_new(const char *info)
-{
- return BLI_ghash_new(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info);
-}
-
GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second)
{
GHashPair *pair = MEM_mallocN(sizeof(GHashPair), "GHashPair");
@@ -411,3 +753,176 @@ void BLI_ghashutil_pairfree(void *ptr)
{
MEM_freeN(ptr);
}
+
+/** \} */
+
+
+/** \name Convenience GHash Creation Functions
+ * \{ */
+
+GHash *BLI_ghash_ptr_new_ex(const char *info,
+ const unsigned int 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 unsigned int nentries_reserve)
+{
+ return BLI_ghash_new_ex(BLI_ghashutil_strhash, 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 unsigned int nentries_reserve)
+{
+ return BLI_ghash_new_ex(BLI_ghashutil_inthash, 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 unsigned int 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);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* GSet API */
+
+/* Use ghash API to give 'set' functionality */
+
+/* TODO: typical set functions
+ * isdisjoint/issubset/issuperset/union/intersection/difference etc */
+
+/** \name GSet Functions
+ * \{ */
+GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info,
+ const unsigned int nentries_reserve)
+{
+ GSet *gs = (GSet *)ghash_new(hashfp, cmpfp, info,
+ nentries_reserve,
+ sizeof(Entry) - sizeof(void *));
+#ifndef NDEBUG
+ ((GHash *)gs)->flag |= GHASH_FLAG_IS_SET;
+#endif
+ return gs;
+}
+
+GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info)
+{
+ return BLI_gset_new_ex(hashfp, cmpfp, info, 0);
+}
+
+int BLI_gset_size(GSet *gs)
+{
+ return (int)((GHash *)gs)->nentries;
+}
+
+/**
+ * Adds the key to the set (no checks for unique keys!).
+ * Matching #BLI_ghash_insert
+ */
+void BLI_gset_insert(GSet *gs, void *key)
+{
+ const unsigned int hash = ghash_keyhash((GHash *)gs, key);
+ ghash_insert_ex_keyonly((GHash *)gs, key, hash);
+}
+
+/**
+ * Adds the key to the set (duplicates are managed).
+ * Matching #BLI_ghash_reinsert
+ *
+ * \returns true if a new key has been added.
+ */
+bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp)
+{
+ const unsigned int hash = ghash_keyhash((GHash *)gs, key);
+ Entry *e = ghash_lookup_entry_ex((GHash *)gs, key, hash);
+ if (e) {
+ if (keyfreefp) keyfreefp(e->key);
+ e->key = key;
+ return false;
+ }
+ else {
+ ghash_insert_ex_keyonly((GHash *)gs, key, hash);
+ return true;
+ }
+}
+
+bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp)
+{
+ return BLI_ghash_remove((GHash *)gs, key, keyfreefp, NULL);
+}
+
+
+bool BLI_gset_haskey(GSet *gs, const void *key)
+{
+ return (ghash_lookup_entry((GHash *)gs, key) != NULL);
+}
+
+void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp,
+ const unsigned int nentries_reserve)
+{
+ BLI_ghash_clear_ex((GHash *)gs, keyfreefp, NULL,
+ nentries_reserve);
+}
+
+void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp)
+{
+ BLI_ghash_clear((GHash *)gs, keyfreefp, NULL);
+}
+
+void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
+{
+ BLI_ghash_free((GHash *)gs, keyfreefp, NULL);
+}
+/** \} */
+
+
+/** \name Convenience GSet Creation Functions
+ * \{ */
+
+GSet *BLI_gset_ptr_new_ex(const char *info,
+ const unsigned int 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_pair_new_ex(const char *info,
+ const unsigned int 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 0aaa3e13b3f..45bdeeedcf9 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -34,14 +34,7 @@
#include "BLI_utildefines.h"
#include "BLI_memarena.h"
#include "BLI_heap.h"
-
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
-# pragma GCC diagnostic error "-Wsign-compare"
-# pragma GCC diagnostic error "-Wconversion"
-# endif
-#endif
+#include "BLI_strict_flags.h"
/***/
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index a4c72aa26b0..80483fbfa38 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -36,6 +36,7 @@
#include "BLI_utildefines.h"
#include "BLI_kdopbvh.h"
#include "BLI_math.h"
+#include "BLI_strict_flags.h"
#ifdef _OPENMP
#include <omp.h>
@@ -65,8 +66,8 @@ struct BVHTree {
int totleaf; /* leafs */
int totbranch;
axis_t start_axis, stop_axis; /* KDOP_AXES array indices according to axis */
- axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */
- char tree_type; /* type of tree (4 => quadtree) */
+ axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */
+ char tree_type; /* type of tree (4 => quadtree) */
};
/* optimization, ensure we stay small */
@@ -77,7 +78,8 @@ BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) ||
typedef struct BVHOverlapData {
BVHTree *tree1, *tree2;
BVHTreeOverlap *overlap;
- int i, max_overlap; /* i is number of overlaps */
+ unsigned int i;
+ unsigned int max_overlap; /* i is number of overlaps */
axis_t start_axis, stop_axis;
} BVHOverlapData;
@@ -437,7 +439,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end)
/* only supports x,y,z axis in the moment
* but we should use a plain and simple function here for speed sake */
-static char get_largest_axis(float *bv)
+static char get_largest_axis(const float *bv)
{
float middle_point[3];
@@ -497,9 +499,13 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
axis_t axis_iter;
for (i = 0; i < depth; i++) printf(" ");
- printf(" - %d (%ld): ", node->index, node - tree->nodearray);
- for (axis_iter = 2 * tree->start_axis; axis_iter < 2 * tree->stop_axis; axis_iter++)
+ printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray));
+ for (axis_iter = (axis_t)(2 * tree->start_axis);
+ axis_iter < (axis_t)(2 * tree->stop_axis);
+ axis_iter++)
+ {
printf("%.3f ", node->bv[axis_iter]);
+ }
printf("\n");
for (i = 0; i < tree->tree_type; i++)
@@ -513,7 +519,7 @@ static void bvhtree_info(BVHTree *tree)
printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon);
printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf);
printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis);
- printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv));
+ printf("BV memory = %dbytes\n", (int)MEM_allocN_len(tree->nodebv));
printf("Total memory = %ldbytes\n", sizeof(BVHTree) +
MEM_allocN_len(tree->nodes) +
@@ -792,7 +798,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array,
break;
}
- parent->totnode = k + 1;
+ parent->totnode = (char)(k + 1);
}
}
}
@@ -811,10 +817,9 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
if (tree_type < 2)
return NULL;
- if (tree_type > MAX_TREETYPE)
- return NULL;
+ BLI_assert(tree_type <= MAX_TREETYPE);
- tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree");
+ tree = MEM_callocN(sizeof(BVHTree), "BVHTree");
/* tree epsilon must be >= FLT_EPSILON
* so that tangent rays can still hit a bounding volume..
@@ -855,27 +860,27 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
/* Allocate arrays */
numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type;
- tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *) * numnodes, "BVHNodes");
+ tree->nodes = MEM_callocN(sizeof(BVHNode *) * (size_t)numnodes, "BVHNodes");
if (!tree->nodes) {
MEM_freeN(tree);
return NULL;
}
-
- tree->nodebv = (float *)MEM_callocN(sizeof(float) * axis * numnodes, "BVHNodeBV");
+
+ tree->nodebv = MEM_callocN(sizeof(float) * (size_t)(axis * numnodes), "BVHNodeBV");
if (!tree->nodebv) {
MEM_freeN(tree->nodes);
MEM_freeN(tree);
}
- tree->nodechild = (BVHNode **)MEM_callocN(sizeof(BVHNode *) * tree_type * numnodes, "BVHNodeBV");
+ tree->nodechild = MEM_callocN(sizeof(BVHNode *) * (size_t)(tree_type * numnodes), "BVHNodeBV");
if (!tree->nodechild) {
MEM_freeN(tree->nodebv);
MEM_freeN(tree->nodes);
MEM_freeN(tree);
}
- tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode) * numnodes, "BVHNodeArray");
+ tree->nodearray = MEM_callocN(sizeof(BVHNode) * (size_t)numnodes, "BVHNodeArray");
if (!tree->nodearray) {
MEM_freeN(tree->nodechild);
@@ -915,7 +920,7 @@ void BLI_bvhtree_balance(BVHTree *tree)
BVHNode **leafs_array = tree->nodes;
/* This function should only be called once (some big bug goes here if its being called more than once per tree) */
- assert(tree->totbranch == 0);
+ BLI_assert(tree->totbranch == 0);
/* Build the implicit tree */
non_recursive_bvh_div_nodes(tree, branches_array, leafs_array, tree->totleaf);
@@ -930,19 +935,14 @@ void BLI_bvhtree_balance(BVHTree *tree)
/* bvhtree_info(tree); */
}
-int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
+void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
{
axis_t axis_iter;
BVHNode *node = NULL;
/* insert should only possible as long as tree->totbranch is 0 */
- if (tree->totbranch > 0)
- return 0;
-
- if (tree->totleaf + 1 >= MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes)))
- return 0;
-
- /* TODO check if have enough nodes in array */
+ BLI_assert(tree->totbranch <= 0);
+ BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes)));
node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
tree->totleaf++;
@@ -955,8 +955,6 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoint
node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */
node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */
}
-
- return 1;
}
@@ -1012,10 +1010,10 @@ float BLI_bvhtree_getepsilon(const BVHTree *tree)
* overlap - is it possible for 2 bv's to collide ? */
static int tree_overlap(BVHNode *node1, BVHNode *node2, axis_t start_axis, axis_t stop_axis)
{
- float *bv1 = node1->bv;
- float *bv2 = node2->bv;
+ const float *bv1 = node1->bv;
+ const float *bv2 = node2->bv;
- float *bv1_end = bv1 + (stop_axis << 1);
+ const float *bv1_end = bv1 + (stop_axis << 1);
bv1 += start_axis << 1;
bv2 += start_axis << 1;
@@ -1045,7 +1043,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2)
if (data->i >= data->max_overlap) {
/* try to make alloc'ed memory bigger */
- data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap) * data->max_overlap * 2);
+ data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap) * (size_t)data->max_overlap * 2);
if (!data->overlap) {
printf("Out of Memory in traverse\n");
@@ -1099,13 +1097,13 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int
data = MEM_callocN(sizeof(BVHOverlapData *) * tree1->tree_type, "BVHOverlapData_star");
for (j = 0; j < tree1->tree_type; j++) {
- data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData");
+ data[j] = MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData");
/* init BVHOverlapData */
- data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap) * max_ii(tree1->totleaf, tree2->totleaf));
+ data[j]->overlap = malloc(sizeof(BVHTreeOverlap) * (size_t)max_ii(tree1->totleaf, tree2->totleaf));
data[j]->tree1 = tree1;
data[j]->tree2 = tree2;
- data[j]->max_overlap = max_ii(tree1->totleaf, tree2->totleaf);
+ data[j]->max_overlap = (unsigned int)max_ii(tree1->totleaf, tree2->totleaf);
data[j]->i = 0;
data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis);
data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
@@ -1119,7 +1117,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int
for (j = 0; j < tree1->tree_type; j++)
total += data[j]->i;
- to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap");
+ to = overlap = MEM_callocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap");
for (j = 0; j < tree1->tree_type; j++) {
memcpy(to, data[j]->overlap, data[j]->i * sizeof(BVHTreeOverlap));
diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c
index dd54fe681b0..57227dc5d5f 100644
--- a/source/blender/blenlib/intern/BLI_kdtree.c
+++ b/source/blender/blenlib/intern/BLI_kdtree.c
@@ -30,28 +30,37 @@
#include "BLI_math.h"
#include "BLI_kdtree.h"
#include "BLI_utildefines.h"
+#include "BLI_strict_flags.h"
typedef struct KDTreeNode {
struct KDTreeNode *left, *right;
float co[3], nor[3];
int index;
- short d;
+ unsigned int d; /* range is only (0-2) */
} KDTreeNode;
struct KDTree {
KDTreeNode *nodes;
- int totnode;
+ unsigned int totnode;
KDTreeNode *root;
};
-KDTree *BLI_kdtree_new(int maxsize)
+#define KD_STACK_INIT 100 /* initial size for array (on the stack) */
+#define KD_NEAR_ALLOC_INC 100 /* alloc increment for collecting nearest */
+#define KD_FOUND_ALLOC_INC 50 /* alloc increment for collecting nearest */
+
+/**
+ * Creates or free a kdtree
+ */
+KDTree *BLI_kdtree_new(unsigned int maxsize)
{
KDTree *tree;
- tree = MEM_callocN(sizeof(KDTree), "KDTree");
- tree->nodes = MEM_callocN(sizeof(KDTreeNode) * maxsize, "KDTreeNode");
+ tree = MEM_mallocN(sizeof(KDTree), "KDTree");
+ tree->nodes = MEM_mallocN(sizeof(KDTreeNode) * maxsize, "KDTreeNode");
tree->totnode = 0;
+ tree->root = NULL;
return tree;
}
@@ -64,20 +73,32 @@ void BLI_kdtree_free(KDTree *tree)
}
}
+/**
+ * Construction: first insert points, then call balance. Normal is optional.
+ */
void BLI_kdtree_insert(KDTree *tree, int index, const float co[3], const float nor[3])
{
KDTreeNode *node = &tree->nodes[tree->totnode++];
- node->index = index;
+ /* note, array isn't calloc'd,
+ * need to initialize all struct members */
+
+ node->left = node->right = NULL;
copy_v3_v3(node->co, co);
- if (nor) copy_v3_v3(node->nor, nor);
+ if (nor)
+ copy_v3_v3(node->nor, nor);
+ else
+ zero_v3(node->nor);
+
+ node->index = index;
+ node->d = 0;
}
-static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis)
+static KDTreeNode *kdtree_balance(KDTreeNode *nodes, unsigned int totnode, unsigned int axis)
{
KDTreeNode *node;
float co;
- int left, right, median, i, j;
+ unsigned int left, right, median, i, j;
if (totnode <= 0)
return NULL;
@@ -98,7 +119,9 @@ static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis)
while (nodes[++i].co[axis] < co) ;
while (nodes[--j].co[axis] > co && j > left) ;
- if (i >= j) break;
+ if (i >= j)
+ break;
+
SWAP(KDTreeNode, nodes[i], nodes[j]);
}
@@ -143,18 +166,33 @@ static float squared_distance(const float v2[3], const float v1[3], const float
return dist;
}
-int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], KDTreeNearest *nearest)
+static KDTreeNode **realloc_nodes(KDTreeNode **stack, unsigned int *totstack, const bool is_alloc)
+{
+ KDTreeNode **stack_new = MEM_mallocN((*totstack + KD_NEAR_ALLOC_INC) * sizeof(KDTreeNode *), "KDTree.treestack");
+ memcpy(stack_new, stack, *totstack * sizeof(KDTreeNode *));
+ // memset(stack_new + *totstack, 0, sizeof(KDTreeNode *) * KD_NEAR_ALLOC_INC);
+ if (is_alloc)
+ MEM_freeN(stack);
+ *totstack += KD_NEAR_ALLOC_INC;
+ return stack_new;
+}
+
+/**
+ * Find nearest returns index, and -1 if no node is found.
+ */
+int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3],
+ KDTreeNearest *r_nearest)
{
KDTreeNode *root, *node, *min_node;
- KDTreeNode **stack, *defaultstack[100];
+ KDTreeNode **stack, *defaultstack[KD_STACK_INIT];
float min_dist, cur_dist;
- int totstack, cur = 0;
+ unsigned int totstack, cur = 0;
if (!tree->root)
return -1;
stack = defaultstack;
- totstack = 100;
+ totstack = KD_STACK_INIT;
root = tree->root;
min_node = root;
@@ -208,20 +246,15 @@ int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3],
if (node->left)
stack[cur++] = node->left;
}
- if (cur + 3 > totstack) {
- KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack");
- memcpy(temp, stack, totstack * sizeof(KDTreeNode *));
- if (stack != defaultstack)
- MEM_freeN(stack);
- stack = temp;
- totstack += 100;
+ if (UNLIKELY(cur + 3 > totstack)) {
+ stack = realloc_nodes(stack, &totstack, defaultstack != stack);
}
}
- if (nearest) {
- nearest->index = min_node->index;
- nearest->dist = sqrt(min_dist);
- copy_v3_v3(nearest->co, min_node->co);
+ if (r_nearest) {
+ r_nearest->index = min_node->index;
+ r_nearest->dist = sqrtf(min_dist);
+ copy_v3_v3(r_nearest->co, min_node->co);
}
if (stack != defaultstack)
@@ -230,9 +263,10 @@ int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3],
return min_node->index;
}
-static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float dist, float *co)
+static void add_nearest(KDTreeNearest *ptn, unsigned int *found, unsigned int n, int index,
+ float dist, const float *co)
{
- int i;
+ unsigned int i;
if (*found < n) (*found)++;
@@ -248,24 +282,32 @@ static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float
copy_v3_v3(ptn[i].co, co);
}
-/* finds the nearest n entries in tree to specified coordinates */
-int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const float nor[3], KDTreeNearest *nearest)
+/**
+ * Find n nearest returns number of points found, with results in nearest.
+ * Normal is optional, but if given will limit results to points in normal direction from co.
+ *
+ * \param r_nearest An array of nearest, sized at least \a n.
+ */
+int BLI_kdtree_find_nearest_n(KDTree *tree, const float co[3], const float nor[3],
+ KDTreeNearest r_nearest[],
+ unsigned int n)
{
KDTreeNode *root, *node = NULL;
- KDTreeNode **stack, *defaultstack[100];
+ KDTreeNode **stack, *defaultstack[KD_STACK_INIT];
float cur_dist;
- int i, totstack, cur = 0, found = 0;
+ unsigned int totstack, cur = 0;
+ unsigned int i, found = 0;
- if (!tree->root)
+ if (!tree->root || n == 0)
return 0;
stack = defaultstack;
- totstack = 100;
+ totstack = KD_STACK_INIT;
root = tree->root;
cur_dist = squared_distance(root->co, co, root->nor, nor);
- add_nearest(nearest, &found, n, root->index, cur_dist, root->co);
+ add_nearest(r_nearest, &found, n, root->index, cur_dist, root->co);
if (co[root->d] < root->co[root->d]) {
if (root->right)
@@ -288,11 +330,11 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const floa
if (cur_dist < 0.0f) {
cur_dist = -cur_dist * cur_dist;
- if (found < n || -cur_dist < nearest[found - 1].dist) {
+ if (found < n || -cur_dist < r_nearest[found - 1].dist) {
cur_dist = squared_distance(node->co, co, node->nor, nor);
- if (found < n || cur_dist < nearest[found - 1].dist)
- add_nearest(nearest, &found, n, node->index, cur_dist, node->co);
+ if (found < n || cur_dist < r_nearest[found - 1].dist)
+ add_nearest(r_nearest, &found, n, node->index, cur_dist, node->co);
if (node->left)
stack[cur++] = node->left;
@@ -303,10 +345,10 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const floa
else {
cur_dist = cur_dist * cur_dist;
- if (found < n || cur_dist < nearest[found - 1].dist) {
+ if (found < n || cur_dist < r_nearest[found - 1].dist) {
cur_dist = squared_distance(node->co, co, node->nor, nor);
- if (found < n || cur_dist < nearest[found - 1].dist)
- add_nearest(nearest, &found, n, node->index, cur_dist, node->co);
+ if (found < n || cur_dist < r_nearest[found - 1].dist)
+ add_nearest(r_nearest, &found, n, node->index, cur_dist, node->co);
if (node->right)
stack[cur++] = node->right;
@@ -314,23 +356,18 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const floa
if (node->left)
stack[cur++] = node->left;
}
- if (cur + 3 > totstack) {
- KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack");
- memcpy(temp, stack, totstack * sizeof(KDTreeNode *));
- if (stack != defaultstack)
- MEM_freeN(stack);
- stack = temp;
- totstack += 100;
+ if (UNLIKELY(cur + 3 > totstack)) {
+ stack = realloc_nodes(stack, &totstack, defaultstack != stack);
}
}
for (i = 0; i < found; i++)
- nearest[i].dist = sqrt(nearest[i].dist);
+ r_nearest[i].dist = sqrtf(r_nearest[i].dist);
if (stack != defaultstack)
MEM_freeN(stack);
- return found;
+ return (int)found;
}
static int range_compare(const void *a, const void *b)
@@ -345,38 +382,45 @@ static int range_compare(const void *a, const void *b)
else
return 0;
}
-static void add_in_range(KDTreeNearest **ptn, int found, int *totfoundstack, int index, float dist, float *co)
+static void add_in_range(KDTreeNearest **ptn, unsigned int found, unsigned int *totfoundstack, int index, float dist, float *co)
{
KDTreeNearest *to;
if (found >= *totfoundstack) {
- KDTreeNearest *temp = MEM_callocN((*totfoundstack + 50) * sizeof(KDTreeNode), "psys_treefoundstack");
+ KDTreeNearest *temp = MEM_mallocN((*totfoundstack + KD_FOUND_ALLOC_INC) * sizeof(KDTreeNode), "KDTree.treefoundstack");
memcpy(temp, *ptn, *totfoundstack * sizeof(KDTreeNearest));
if (*ptn)
MEM_freeN(*ptn);
*ptn = temp;
- *totfoundstack += 50;
+ *totfoundstack += KD_FOUND_ALLOC_INC;
}
to = (*ptn) + found;
to->index = index;
- to->dist = sqrt(dist);
+ to->dist = sqrtf(dist);
copy_v3_v3(to->co, co);
}
-int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const float nor[3], KDTreeNearest **nearest)
+
+/**
+ * Range search returns number of points found, with results in nearest
+ * Normal is optional, but if given will limit results to points in normal direction from co.
+ * Remember to free nearest after use!
+ */
+int BLI_kdtree_range_search(KDTree *tree, const float co[3], const float nor[3],
+ KDTreeNearest **r_nearest, float range)
{
KDTreeNode *root, *node = NULL;
- KDTreeNode **stack, *defaultstack[100];
+ KDTreeNode **stack, *defaultstack[KD_STACK_INIT];
KDTreeNearest *foundstack = NULL;
float range2 = range * range, dist2;
- int totstack, cur = 0, found = 0, totfoundstack = 0;
+ unsigned int totstack, cur = 0, found = 0, totfoundstack = 0;
if (!tree || !tree->root)
return 0;
stack = defaultstack;
- totstack = 100;
+ totstack = KD_STACK_INIT;
root = tree->root;
@@ -421,13 +465,8 @@ int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const
stack[cur++] = node->right;
}
- if (cur + 3 > totstack) {
- KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack");
- memcpy(temp, stack, totstack * sizeof(KDTreeNode *));
- if (stack != defaultstack)
- MEM_freeN(stack);
- stack = temp;
- totstack += 100;
+ if (UNLIKELY(cur + 3 > totstack)) {
+ stack = realloc_nodes(stack, &totstack, defaultstack != stack);
}
}
@@ -437,7 +476,7 @@ int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const
if (found)
qsort(foundstack, found, sizeof(KDTreeNearest), range_compare);
- *nearest = foundstack;
+ *r_nearest = foundstack;
- return found;
+ return (int)found;
}
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index b08fbe17a43..66fcfd21fbb 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
+#include "BLI_mempool.h"
int BLI_linklist_length(LinkNode *list)
{
@@ -88,18 +89,39 @@ void BLI_linklist_reverse(LinkNode **listp)
*listp = rhead;
}
-void BLI_linklist_prepend(LinkNode **listp, void *ptr)
+/**
+ * A version of prepend that takes the allocated link.
+ */
+void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
{
- LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
nlink->link = ptr;
-
nlink->next = *listp;
*listp = nlink;
}
-void BLI_linklist_append(LinkNode **listp, void *ptr)
+void BLI_linklist_prepend(LinkNode **listp, void *ptr)
{
LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
+ BLI_linklist_prepend_nlink(listp, ptr, nlink);
+}
+
+void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma)
+{
+ LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink));
+ BLI_linklist_prepend_nlink(listp, ptr, nlink);
+}
+
+void BLI_linklist_prepend_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool)
+{
+ LinkNode *nlink = BLI_mempool_alloc(mempool);
+ BLI_linklist_prepend_nlink(listp, ptr, nlink);
+}
+
+/**
+ * A version of append that takes the allocated link.
+ */
+void BLI_linklist_append_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
+{
LinkNode *node = *listp;
nlink->link = ptr;
@@ -116,13 +138,46 @@ void BLI_linklist_append(LinkNode **listp, void *ptr)
}
}
-void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma)
+void BLI_linklist_append(LinkNode **listp, void *ptr)
+{
+ LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
+ BLI_linklist_append_nlink(listp, ptr, nlink);
+}
+
+void BLI_linklist_append_arena(LinkNode **listp, void *ptr, MemArena *ma)
{
LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink));
- nlink->link = ptr;
-
- nlink->next = *listp;
- *listp = nlink;
+ BLI_linklist_append_nlink(listp, ptr, nlink);
+}
+
+void BLI_linklist_append_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool)
+{
+ LinkNode *nlink = BLI_mempool_alloc(mempool);
+ BLI_linklist_append_nlink(listp, ptr, nlink);
+}
+
+void *BLI_linklist_pop(struct LinkNode **listp)
+{
+ /* intentionally no NULL check */
+ void *link = (*listp)->link;
+ void *next = (*listp)->next;
+
+ MEM_freeN((*listp));
+
+ *listp = next;
+ return link;
+}
+
+void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool)
+{
+ /* intentionally no NULL check */
+ void *link = (*listp)->link;
+ void *next = (*listp)->next;
+
+ BLI_mempool_free(mempool, (*listp));
+
+ *listp = next;
+ return link;
}
void BLI_linklist_insert_after(LinkNode **listp, void *ptr)
@@ -155,6 +210,19 @@ void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc)
}
}
+void BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool)
+{
+ while (list) {
+ LinkNode *next = list->next;
+
+ if (freefunc)
+ freefunc(list->link);
+ BLI_mempool_free(mempool, list);
+
+ list = next;
+ }
+}
+
void BLI_linklist_freeN(LinkNode *list)
{
while (list) {
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index ef10cb805ad..4a6712201a9 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -30,17 +30,16 @@
* \ingroup bli
*/
+#include <string.h>
+
#include "MEM_guardedalloc.h"
#include "BLI_memarena.h"
#include "BLI_linklist.h"
+#include "BLI_strict_flags.h"
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
-# pragma GCC diagnostic error "-Wsign-compare"
-# pragma GCC diagnostic error "-Wconversion"
-# endif
+#ifdef WITH_MEM_VALGRIND
+# include "valgrind/memcheck.h"
#endif
struct MemArena {
@@ -61,6 +60,10 @@ MemArena *BLI_memarena_new(const int bufsize, const char *name)
ma->align = 8;
ma->name = name;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_CREATE_MEMPOOL(ma, 0, false);
+#endif
+
return ma;
}
@@ -83,12 +86,27 @@ void BLI_memarena_use_align(struct MemArena *ma, const int align)
void BLI_memarena_free(MemArena *ma)
{
BLI_linklist_freeN(ma->bufs);
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(ma);
+#endif
+
MEM_freeN(ma);
}
/* amt must be power of two */
#define PADUP(num, amt) (((num) + ((amt) - 1)) & ~((amt) - 1))
+/* align alloc'ed memory (needed if align > 8) */
+static void memarena_curbuf_align(MemArena *ma)
+{
+ unsigned char *tmp;
+
+ tmp = (unsigned char *)PADUP( (intptr_t) ma->curbuf, ma->align);
+ ma->cursize -= (int)(tmp - ma->curbuf);
+ ma->curbuf = tmp;
+}
+
void *BLI_memarena_alloc(MemArena *ma, int size)
{
void *ptr;
@@ -98,8 +116,6 @@ void *BLI_memarena_alloc(MemArena *ma, int size)
size = PADUP(size, ma->align);
if (size > ma->cursize) {
- unsigned char *tmp;
-
if (size > ma->bufsize - (ma->align - 1)) {
ma->cursize = PADUP(size + 1, ma->align);
}
@@ -112,16 +128,51 @@ void *BLI_memarena_alloc(MemArena *ma, int size)
ma->curbuf = MEM_mallocN((size_t)ma->cursize, ma->name);
BLI_linklist_prepend(&ma->bufs, ma->curbuf);
-
- /* align alloc'ed memory (needed if align > 8) */
- tmp = (unsigned char *)PADUP( (intptr_t) ma->curbuf, ma->align);
- ma->cursize -= (int)(tmp - ma->curbuf);
- ma->curbuf = tmp;
+ memarena_curbuf_align(ma);
}
ptr = ma->curbuf;
ma->curbuf += size;
ma->cursize -= size;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_ALLOC(ma, ptr, size);
+#endif
+
return ptr;
}
+
+/**
+ * Clear for reuse, avoids re-allocation when an arena may
+ * otherwise be free'd and recreated.
+ */
+void BLI_memarena_clear(MemArena *ma)
+{
+ if (ma->bufs) {
+ unsigned char *curbuf_prev;
+ int curbuf_used;
+
+ if (ma->bufs->next) {
+ BLI_linklist_freeN(ma->bufs->next);
+ ma->bufs->next = NULL;
+ }
+
+ curbuf_prev = ma->curbuf;
+ ma->curbuf = ma->bufs->link;
+ memarena_curbuf_align(ma);
+
+ /* restore to original size */
+ curbuf_used = (int)(curbuf_prev - ma->curbuf);
+ ma->cursize += curbuf_used;
+
+ if (ma->use_calloc) {
+ memset(ma->curbuf, 0, (size_t)curbuf_used);
+ }
+ }
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(ma);
+ VALGRIND_CREATE_MEMPOOL(ma, 0, false);
+#endif
+
+}
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index bb326a23d59..261e53f0f55 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -31,6 +31,9 @@
* Simple, fast memory allocator for allocating many elements of the same size.
*/
+#include <string.h>
+#include <stdlib.h>
+
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
@@ -40,15 +43,10 @@
#include "MEM_guardedalloc.h"
-#include <string.h>
-#include <stdlib.h>
+#include "BLI_strict_flags.h" /* keep last */
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
-# pragma GCC diagnostic error "-Wsign-compare"
-# pragma GCC diagnostic error "-Wconversion"
-# endif
+#ifdef WITH_MEM_VALGRIND
+# include "valgrind/memcheck.h"
#endif
/* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */
@@ -65,37 +63,185 @@
/* currently totalloc isnt used */
// #define USE_TOTALLOC
+/* when undefined, merge the allocs for BLI_mempool_chunk and its data */
+// #define USE_DATA_PTR
+
+#ifndef NDEBUG
+static bool mempool_debug_memset = false;
+#endif
+
+/**
+ * A free element from #BLI_mempool_chunk. Data is cast to this type and stored in
+ * #BLI_mempool.free as a single linked list, each item #BLI_mempool.esize large.
+ *
+ * Each element represents a block which BLI_mempool_alloc may return.
+ */
typedef struct BLI_freenode {
struct BLI_freenode *next;
int freeword; /* used to identify this as a freed node */
} BLI_freenode;
+/**
+ * A chunk of memory in the mempool stored in
+ * #BLI_mempool.chunks as a double linked list.
+ */
typedef struct BLI_mempool_chunk {
struct BLI_mempool_chunk *next, *prev;
- void *data;
+#ifdef USE_DATA_PTR
+ void *_data;
+#endif
} BLI_mempool_chunk;
+/**
+ * The mempool, stores and tracks memory \a chunks and elements within those chunks \a free.
+ */
struct BLI_mempool {
struct ListBase chunks;
- int esize; /* element size in bytes */
- int csize; /* chunk size in bytes */
- int pchunk; /* number of elements per chunk */
- int flag;
+ unsigned int esize; /* element size in bytes */
+ unsigned int csize; /* chunk size in bytes */
+ unsigned int pchunk; /* number of elements per chunk */
+ unsigned int flag;
/* keeps aligned to 16 bits */
- BLI_freenode *free; /* free element list. Interleaved into chunk datas. */
- int totalloc, totused; /* total number of elements allocated in total,
- * and currently in use */
+ BLI_freenode *free; /* free element list. Interleaved into chunk datas. */
+ unsigned int maxchunks; /* use to know how many chunks to keep for BLI_mempool_clear */
+ unsigned int totused; /* number of elements currently in use */
+#ifdef USE_TOTALLOC
+ unsigned int totalloc; /* number of elements allocated in total */
+#endif
};
#define MEMPOOL_ELEM_SIZE_MIN (sizeof(void *) * 2)
-BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag)
+#ifdef USE_DATA_PTR
+# define CHUNK_DATA(chunk) (chunk)->_data
+#else
+# define CHUNK_DATA(chunk) (CHECK_TYPE_INLINE(chunk, BLI_mempool_chunk *), (void *)((chunk) + 1))
+#endif
+
+/**
+ * \return the number of chunks to allocate based on how many elements are needed.
+ */
+BLI_INLINE unsigned int mempool_maxchunks(const unsigned int totelem, const unsigned int pchunk)
{
- BLI_mempool *pool = NULL;
- BLI_freenode *lasttail = NULL, *curnode = NULL;
- int i, j, maxchunks;
+ return totelem / pchunk + 1;
+}
+
+static BLI_mempool_chunk *mempool_chunk_alloc(BLI_mempool *pool)
+{
+ BLI_mempool_chunk *mpchunk;
+#ifdef USE_DATA_PTR
+ if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
+ mpchunk = malloc(sizeof(BLI_mempool_chunk));
+ CHUNK_DATA(mpchunk) = malloc((size_t)pool->csize);
+ }
+ else {
+ mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
+ CHUNK_DATA(mpchunk) = MEM_mallocN((size_t)pool->csize, "BLI Mempool Chunk Data");
+ }
+#else
+ if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
+ mpchunk = malloc(sizeof(BLI_mempool_chunk) + (size_t)pool->csize);
+ }
+ else {
+ mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk) + (size_t)pool->csize, "BLI_Mempool Chunk");
+ }
+#endif
+
+ return mpchunk;
+}
+
+/**
+ * Initialize a chunk and add into \a pool->chunks
+ *
+ * \param pool The pool to add the chunk into.
+ * \param mpchunk The new uninitialized chunk (can be malloc'd)
+ * \param lasttail The last element of the previous chunk
+ * (used when building free chunks initially)
+ * \return The last chunk,
+ */
+static BLI_freenode *mempool_chunk_add(BLI_mempool *pool, BLI_mempool_chunk *mpchunk,
+ BLI_freenode *lasttail)
+{
+ BLI_freenode *curnode = NULL;
+ const unsigned int pchunk_last = pool->pchunk - 1;
char *addr;
+ unsigned int j;
+
+ mpchunk->next = mpchunk->prev = NULL;
+ BLI_addtail(&(pool->chunks), mpchunk);
+
+ if (pool->free == NULL) {
+ pool->free = CHUNK_DATA(mpchunk); /* start of the list */
+ if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
+ pool->free->freeword = FREEWORD;
+ }
+ }
+
+ /* loop through the allocated data, building the pointer structures */
+ for (addr = CHUNK_DATA(mpchunk), j = 0; j != pchunk_last; j++) {
+ curnode = ((BLI_freenode *)addr);
+ addr += pool->esize;
+ curnode->next = (BLI_freenode *)addr;
+ if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
+ if (j != pchunk_last)
+ curnode->next->freeword = FREEWORD;
+ curnode->freeword = FREEWORD;
+ }
+ }
+
+ /* terminate the list,
+ * will be overwritten if 'curnode' gets passed in again as 'lasttail' */
+ curnode->next = NULL;
+
+#ifdef USE_TOTALLOC
+ pool->totalloc += pool->pchunk;
+#endif
+
+ /* final pointer in the previously allocated chunk is wrong */
+ if (lasttail) {
+ lasttail->next = CHUNK_DATA(mpchunk);
+ if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
+ lasttail->freeword = FREEWORD;
+ }
+ }
+
+ return curnode;
+}
+
+static void mempool_chunk_free(BLI_mempool_chunk *mpchunk, const unsigned int flag)
+{
+ if (flag & BLI_MEMPOOL_SYSMALLOC) {
+#ifdef USE_DATA_PTR
+ free(CHUNK_DATA(mpchunk));
+#endif
+ free(mpchunk);
+ }
+ else {
+#ifdef USE_DATA_PTR
+ MEM_freeN(CHUNK_DATA(mpchunk));
+#endif
+ MEM_freeN(mpchunk);
+ }
+}
+
+static void mempool_chunk_free_all(ListBase *chunks, const unsigned int flag)
+{
+ BLI_mempool_chunk *mpchunk, *mpchunk_next;
+
+ for (mpchunk = chunks->first; mpchunk; mpchunk = mpchunk_next) {
+ mpchunk_next = mpchunk->next;
+ mempool_chunk_free(mpchunk, flag);
+ }
+ chunks->first = chunks->last = NULL;
+}
+
+BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem,
+ unsigned int pchunk, unsigned int flag)
+{
+ BLI_mempool *pool = NULL;
+ BLI_freenode *lasttail = NULL;
+ unsigned int i, maxchunks;
/* allocate the pool structure */
if (flag & BLI_MEMPOOL_SYSMALLOC) {
@@ -117,68 +263,29 @@ BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag)
pool->esize = esize;
}
+ maxchunks = mempool_maxchunks(totelem, pchunk);
+
pool->flag = flag;
pool->pchunk = pchunk;
pool->csize = esize * pchunk;
pool->chunks.first = pool->chunks.last = NULL;
+ pool->free = NULL; /* mempool_chunk_add assigns */
+ pool->maxchunks = maxchunks;
+#ifdef USE_TOTALLOC
pool->totalloc = 0;
+#endif
pool->totused = 0;
- maxchunks = totelem / pchunk + 1;
- if (maxchunks == 0) {
- maxchunks = 1;
- }
-
/* allocate the actual chunks */
for (i = 0; i < maxchunks; i++) {
- BLI_mempool_chunk *mpchunk;
-
- if (flag & BLI_MEMPOOL_SYSMALLOC) {
- mpchunk = malloc(sizeof(BLI_mempool_chunk));
- mpchunk->data = malloc((size_t)pool->csize);
- }
- else {
- mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
- mpchunk->data = MEM_mallocN((size_t)pool->csize, "BLI Mempool Chunk Data");
- }
-
- mpchunk->next = mpchunk->prev = NULL;
- BLI_addtail(&(pool->chunks), mpchunk);
-
- if (i == 0) {
- pool->free = mpchunk->data; /* start of the list */
- if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
- pool->free->freeword = FREEWORD;
- }
- }
-
- /* loop through the allocated data, building the pointer structures */
- for (addr = mpchunk->data, j = 0; j < pool->pchunk; j++) {
- curnode = ((BLI_freenode *)addr);
- addr += pool->esize;
- curnode->next = (BLI_freenode *)addr;
- if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
- if (j != pool->pchunk - 1)
- curnode->next->freeword = FREEWORD;
- curnode->freeword = FREEWORD;
- }
- }
- /* final pointer in the previously allocated chunk is wrong */
- if (lasttail) {
- lasttail->next = mpchunk->data;
- if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
- lasttail->freeword = FREEWORD;
- }
- }
+ BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool);
+ lasttail = mempool_chunk_add(pool, mpchunk, lasttail);
+ }
- /* set the end of this chunks memory to the new tail for next iteration */
- lasttail = curnode;
-#ifdef USE_TOTALLOC
- pool->totalloc += pool->pchunk;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_CREATE_MEMPOOL(pool, 0, false);
#endif
- }
- /* terminate the list */
- curnode->next = NULL;
+
return pool;
}
@@ -189,46 +296,9 @@ void *BLI_mempool_alloc(BLI_mempool *pool)
pool->totused++;
if (!(pool->free)) {
- BLI_freenode *curnode = NULL;
- char *addr;
- int j;
-
/* need to allocate a new chunk */
- BLI_mempool_chunk *mpchunk;
-
- if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
- mpchunk = malloc(sizeof(BLI_mempool_chunk));
- mpchunk->data = malloc((size_t)pool->csize);
- }
- else {
- mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
- mpchunk->data = MEM_mallocN((size_t)pool->csize, "BLI_Mempool Chunk Data");
- }
-
- mpchunk->next = mpchunk->prev = NULL;
- BLI_addtail(&(pool->chunks), mpchunk);
-
- pool->free = mpchunk->data; /* start of the list */
-
- if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
- pool->free->freeword = FREEWORD;
- }
-
- for (addr = mpchunk->data, j = 0; j < pool->pchunk; j++) {
- curnode = ((BLI_freenode *)addr);
- addr += pool->esize;
- curnode->next = (BLI_freenode *)addr;
-
- if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
- curnode->freeword = FREEWORD;
- if (j != pool->pchunk - 1)
- curnode->next->freeword = FREEWORD;
- }
- }
- curnode->next = NULL; /* terminate the list */
-#ifdef USE_TOTALLOC
- pool->totalloc += pool->pchunk;
-#endif
+ BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool);
+ mempool_chunk_add(pool, mpchunk, NULL);
}
retval = pool->free;
@@ -238,7 +308,11 @@ void *BLI_mempool_alloc(BLI_mempool *pool)
}
pool->free = pool->free->next;
- //memset(retval, 0, pool->esize);
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_ALLOC(pool, retval, pool->esize);
+#endif
+
return retval;
}
@@ -258,6 +332,27 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
{
BLI_freenode *newhead = addr;
+#ifndef NDEBUG
+ {
+ BLI_mempool_chunk *chunk;
+ bool found = false;
+ for (chunk = pool->chunks.first; chunk; chunk = chunk->next) {
+ if (ARRAY_HAS_ITEM((char *)addr, (char *)CHUNK_DATA(chunk), pool->csize)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ BLI_assert(!"Attempt to free data which is not in pool.\n");
+ }
+ }
+
+ /* enable for debugging */
+ if (UNLIKELY(mempool_debug_memset)) {
+ memset(addr, 255, pool->esize);
+ }
+#endif
+
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
#ifndef NDEBUG
/* this will detect double free's */
@@ -271,55 +366,52 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
pool->totused--;
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_FREE(pool, addr);
+#endif
+
/* nothing is in use; free all the chunks except the first */
- if (pool->totused == 0) {
+ if (UNLIKELY(pool->totused == 0)) {
BLI_freenode *curnode = NULL;
char *tmpaddr = NULL;
- int i;
-
- BLI_mempool_chunk *mpchunk = NULL;
- BLI_mempool_chunk *first = pool->chunks.first;
-
- BLI_remlink(&pool->chunks, first);
-
- if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
- for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) {
- free(mpchunk->data);
- }
- BLI_freelist(&(pool->chunks));
- }
- else {
- for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) {
- MEM_freeN(mpchunk->data);
- }
- BLI_freelistN(&(pool->chunks));
- }
+ unsigned int i;
+ BLI_mempool_chunk *first;
+ first = BLI_pophead(&pool->chunks);
+ mempool_chunk_free_all(&pool->chunks, pool->flag);
BLI_addtail(&pool->chunks, first);
#ifdef USE_TOTALLOC
pool->totalloc = pool->pchunk;
#endif
- pool->free = first->data; /* start of the list */
- for (tmpaddr = first->data, i = 0; i < pool->pchunk; i++) {
+ /* temp alloc so valgrind doesn't complain when setting free'd blocks 'next' */
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_ALLOC(pool, CHUNK_DATA(first), pool->csize);
+#endif
+ pool->free = CHUNK_DATA(first); /* start of the list */
+ for (tmpaddr = CHUNK_DATA(first), i = 0; i < pool->pchunk; i++) {
curnode = ((BLI_freenode *)tmpaddr);
tmpaddr += pool->esize;
curnode->next = (BLI_freenode *)tmpaddr;
}
curnode->next = NULL; /* terminate the list */
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_MEMPOOL_FREE(pool, CHUNK_DATA(first));
+#endif
}
}
int BLI_mempool_count(BLI_mempool *pool)
{
- return pool->totused;
+ return (int)pool->totused;
}
-void *BLI_mempool_findelem(BLI_mempool *pool, int index)
+void *BLI_mempool_findelem(BLI_mempool *pool, unsigned int index)
{
BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER);
- if ((index >= 0) && (index < pool->totused)) {
+ if (index < pool->totused) {
/* we could have some faster mem chunk stepping code inline */
BLI_mempool_iter iter;
void *elem;
@@ -337,6 +429,7 @@ void *BLI_mempool_findelem(BLI_mempool *pool, int index)
* Fill in \a data with pointers to each element of the mempool,
* to create lookup table.
*
+ * \param pool Pool to create a table from.
* \param data array of pointers at least the size of 'pool->totused'
*/
void BLI_mempool_as_table(BLI_mempool *pool, void **data)
@@ -349,7 +442,7 @@ void BLI_mempool_as_table(BLI_mempool *pool, void **data)
while ((elem = BLI_mempool_iterstep(&iter))) {
*p++ = elem;
}
- BLI_assert((p - data) == pool->totused);
+ BLI_assert((unsigned int)(p - data) == pool->totused);
}
/**
@@ -375,7 +468,7 @@ void BLI_mempool_as_array(BLI_mempool *pool, void *data)
memcpy(p, elem, (size_t)pool->esize);
p += pool->esize;
}
- BLI_assert((p - (char *)data) == pool->totused * pool->esize);
+ BLI_assert((unsigned int)(p - (char *)data) == pool->totused * pool->esize);
}
/**
@@ -388,6 +481,9 @@ void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
return data;
}
+/**
+ * Create a new mempool iterator, \a BLI_MEMPOOL_ALLOW_ITER flag must be set.
+ */
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
{
BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER);
@@ -406,11 +502,11 @@ static void *bli_mempool_iternext(BLI_mempool_iter *iter)
if (!iter->curchunk || !iter->pool->totused) return NULL;
- ret = ((char *)iter->curchunk->data) + iter->pool->esize * iter->curindex;
+ ret = ((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex);
iter->curindex++;
- if (iter->curindex >= iter->pool->pchunk) {
+ if (iter->curindex == iter->pool->pchunk) {
iter->curchunk = iter->curchunk->next;
iter->curindex = 0;
}
@@ -433,23 +529,22 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
/* optimized version of code above */
+/**
+ * Step over the iterator, returning the mempool item or NULL.
+ */
void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
{
BLI_freenode *ret;
- if (UNLIKELY(iter->pool->totused == 0)) {
- return NULL;
- }
-
do {
if (LIKELY(iter->curchunk)) {
- ret = (BLI_freenode *)(((char *)iter->curchunk->data) + iter->pool->esize * iter->curindex);
+ ret = (BLI_freenode *)(((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex));
}
else {
return NULL;
}
- if (UNLIKELY(++iter->curindex >= iter->pool->pchunk)) {
+ if (UNLIKELY(++iter->curindex == iter->pool->pchunk)) {
iter->curindex = 0;
iter->curchunk = iter->curchunk->next;
}
@@ -461,27 +556,85 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
#endif
/**
+ * Empty the pool, as if it were just created.
+ *
+ * \param pool The pool to clear.
+ * \param totelem_reserve Optionally reserve how many items should be kept from clearing.
+ */
+void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve)
+{
+ BLI_mempool_chunk *mpchunk;
+ BLI_mempool_chunk *mpchunk_next;
+ unsigned int maxchunks;
+
+ ListBase chunks_temp;
+ BLI_freenode *lasttail = NULL;
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(pool);
+ VALGRIND_CREATE_MEMPOOL(pool, 0, false);
+#endif
+
+ if (totelem_reserve == -1) {
+ maxchunks = pool->maxchunks;
+ }
+ else {
+ maxchunks = mempool_maxchunks((unsigned int)totelem_reserve, pool->pchunk);
+ }
+
+ /* free all after pool->maxchunks */
+
+ for (mpchunk = BLI_findlink(&pool->chunks, (int)maxchunks); mpchunk; mpchunk = mpchunk_next) {
+ mpchunk_next = mpchunk->next;
+ BLI_remlink(&pool->chunks, mpchunk);
+ mempool_chunk_free(mpchunk, pool->flag);
+ }
+
+ /* re-initialize */
+ pool->free = NULL;
+ pool->totused = 0;
+#ifdef USE_TOTALLOC
+ pool->totalloc = 0;
+#endif
+
+ chunks_temp = pool->chunks;
+ pool->chunks.first = pool->chunks.last = NULL;
+
+ while ((mpchunk = BLI_pophead(&chunks_temp))) {
+ lasttail = mempool_chunk_add(pool, mpchunk, lasttail);
+ }
+}
+
+/**
+ * Wrap #BLI_mempool_clear_ex with no reserve set.
+ */
+void BLI_mempool_clear(BLI_mempool *pool)
+{
+ BLI_mempool_clear_ex(pool, -1);
+}
+
+/**
* Free the mempool its self (and all elements).
*/
void BLI_mempool_destroy(BLI_mempool *pool)
{
- BLI_mempool_chunk *mpchunk = NULL;
- BLI_mempool_chunk *mpchunk_next;
+ mempool_chunk_free_all(&pool->chunks, pool->flag);
+
+#ifdef WITH_MEM_VALGRIND
+ VALGRIND_DESTROY_MEMPOOL(pool);
+#endif
if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
- for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk_next) {
- mpchunk_next = mpchunk->next;
- free(mpchunk->data);
- free(mpchunk);
- }
free(pool);
}
else {
- for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk_next) {
- mpchunk_next = mpchunk->next;
- MEM_freeN(mpchunk->data);
- MEM_freeN(mpchunk);
- }
MEM_freeN(pool);
}
}
+
+#ifndef NDEBUG
+void BLI_mempool_set_memory_debug(void)
+{
+ mempool_debug_memset = true;
+}
+#endif
diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c
index 8a97fdcab67..8707be46196 100644
--- a/source/blender/blenlib/intern/boxpack2d.c
+++ b/source/blender/blenlib/intern/boxpack2d.c
@@ -27,7 +27,9 @@
#include <stdlib.h> /* for qsort */
#include "MEM_guardedalloc.h"
-#include "BLI_boxpack2d.h"
+#include "BLI_strict_flags.h"
+
+#include "BLI_boxpack2d.h" /* own include */
/* BoxPacker for backing 2D rectangles into a square
*
@@ -154,7 +156,7 @@ static int vertex_sort(const void *p1, const void *p2)
* len - the number of boxes in the array.
* tot_width and tot_height are set so you can normalize the data.
* */
-void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *tot_height)
+void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *tot_height)
{
BoxVert *vert; /* the current vert */
int box_index, verts_pack_len, i, j, k, isect;
@@ -169,11 +171,11 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *
}
/* Sort boxes, biggest first */
- qsort(boxarray, len, sizeof(BoxPack), box_areasort);
+ qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort);
/* add verts to the boxes, these are only used internally */
- vert = vertarray = MEM_mallocN(len * 4 * sizeof(BoxVert), "BoxPack Verts");
- vertex_pack_indices = MEM_mallocN(len * 3 * sizeof(int), "BoxPack Indices");
+ vert = vertarray = MEM_mallocN((size_t)len * 4 * sizeof(BoxVert), "BoxPack Verts");
+ vertex_pack_indices = MEM_mallocN((size_t)len * 3 * sizeof(int), "BoxPack Indices");
for (box = boxarray, box_index = 0, i = 0; box_index < len; box_index++, box++) {
@@ -241,7 +243,7 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *
box_width = box->w;
box_height = box->h;
- qsort(vertex_pack_indices, verts_pack_len, sizeof(int), vertex_sort);
+ qsort(vertex_pack_indices, (size_t)verts_pack_len, sizeof(int), vertex_sort);
/* Pack the box in with the others */
/* sort the verts */
@@ -318,7 +320,7 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float *
(*tot_height) = max_ff(BOXTOP(box), (*tot_height));
/* Place the box */
- vert->free &= ~quad_flags[j];
+ vert->free &= (short)~quad_flags[j];
switch (j) {
case TR:
diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c
index 36fb04a7bb7..4e570823319 100644
--- a/source/blender/blenlib/intern/buffer.c
+++ b/source/blender/blenlib/intern/buffer.c
@@ -18,6 +18,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenlib/intern/buffer.c
+ * \ingroup bli
+ */
+
#include "MEM_guardedalloc.h"
#include "BLI_buffer.h"
diff --git a/source/blender/blenlib/intern/callbacks.c b/source/blender/blenlib/intern/callbacks.c
index 614a9a63d90..719809e6bcd 100644
--- a/source/blender/blenlib/intern/callbacks.c
+++ b/source/blender/blenlib/intern/callbacks.c
@@ -20,6 +20,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenlib/intern/callbacks.c
+ * \ingroup bli
+ */
+
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_callbacks.h"
diff --git a/source/blender/blenlib/intern/convexhull2d.c b/source/blender/blenlib/intern/convexhull2d.c
new file mode 100644
index 00000000000..5669a302bd8
--- /dev/null
+++ b/source/blender/blenlib/intern/convexhull2d.c
@@ -0,0 +1,338 @@
+/*
+ * ***** 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/blenlib/intern/convexhull2d.c
+ * \ingroup bli
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_convexhull2d.h"
+#include "BLI_math.h"
+#include "BLI_strict_flags.h"
+#include "BLI_utildefines.h"
+
+/* Copyright 2001, softSurfer (www.softsurfer.com)
+ * This code may be freely used and modified for any purpose
+ * providing that this copyright notice is included with it.
+ * SoftSurfer makes no warranty for this code, and cannot be held
+ * liable for any real or imagined damage resulting from its use.
+ * Users of this code must verify correctness for their application.
+ * http://softsurfer.com/Archive/algorithm_0203/algorithm_0203.htm
+ */
+
+/** \name Main Convex-Hull Calculation
+ * \{ */
+
+/**
+ * tests if a point is Left|On|Right of an infinite line.
+ * Input: three points P0, P1, and P2
+ * \returns > 0.0 for P2 left of the line through P0 and P1.
+ * = 0.0 for P2 on the line.
+ * < 0.0 for P2 right of the line.
+ */
+static float is_left(const float p0[2], const float p1[2], const float p2[2])
+{
+ return (p1[0] - p0[0]) * (p2[1] - p0[1]) - (p2[0] - p0[0]) * (p1[1] - p0[1]);
+}
+
+/**
+ * A.M. Andrew's monotone chain 2D convex hull algorithm
+ *
+ * \param points An array of 2D points presorted by increasing x and y-coords.
+ * \param n The number of points in points.
+ * \param r_points An array of the convex hull vertex indices (max is n).
+ * \returns the number of points in r_points.
+ */
+int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points[])
+{
+ /* the output array r_points[] will be used as the stack */
+ int bot = 0;
+ int top = -1; /* indices for bottom and top of the stack */
+ int i; /* array scan index */
+ int minmin, minmax;
+ int maxmin, maxmax;
+ float xmax;
+
+ /* Get the indices of points with min x-coord and min|max y-coord */
+ float xmin = points[0][0];
+ for (i = 1; i < n; i++) {
+ if (points[i][0] != xmin) {
+ break;
+ }
+ }
+
+ minmin = 0;
+ minmax = i - 1;
+ if (minmax == n - 1) { /* degenerate case: all x-coords == xmin */
+ r_points[++top] = minmin;
+ if (points[minmax][1] != points[minmin][1]) /* a nontrivial segment */
+ r_points[++top] = minmax;
+ r_points[++top] = minmin; /* add polygon endpoint */
+ return top + 1;
+ }
+
+ /* Get the indices of points with max x-coord and min|max y-coord */
+
+ maxmax = n - 1;
+ xmax = points[n - 1][0];
+ for (i = n - 2; i >= 0; i--) {
+ if (points[i][0] != xmax) {
+ break;
+ }
+ }
+ maxmin = i + 1;
+
+ /* Compute the lower hull on the stack r_points */
+ r_points[++top] = minmin; /* push minmin point onto stack */
+ i = minmax;
+ while (++i <= maxmin) {
+ /* the lower line joins points[minmin] with points[maxmin] */
+ if (is_left(points[minmin], points[maxmin], points[i]) >= 0 && i < maxmin) {
+ continue; /* ignore points[i] above or on the lower line */
+ }
+
+ while (top > 0) { /* there are at least 2 points on the stack */
+ /* test if points[i] is left of the line at the stack top */
+ if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) {
+ break; /* points[i] is a new hull vertex */
+ }
+ else {
+ top--; /* pop top point off stack */
+ }
+ }
+
+ r_points[++top] = i; /* push points[i] onto stack */
+ }
+
+ /* Next, compute the upper hull on the stack r_points above the bottom hull */
+ if (maxmax != maxmin) { /* if distinct xmax points */
+ r_points[++top] = maxmax; /* push maxmax point onto stack */
+ }
+
+ bot = top; /* the bottom point of the upper hull stack */
+ i = maxmin;
+ while (--i >= minmax) {
+ /* the upper line joins points[maxmax] with points[minmax] */
+ if (is_left(points[maxmax], points[minmax], points[i]) >= 0 && i > minmax) {
+ continue; /* ignore points[i] below or on the upper line */
+ }
+
+ while (top > bot) { /* at least 2 points on the upper stack */
+ /* test if points[i] is left of the line at the stack top */
+ if (is_left(points[r_points[top - 1]], points[r_points[top]], points[i]) > 0.0f) {
+ break; /* points[i] is a new hull vertex */
+ }
+ else {
+ top--; /* pop top point off stack */
+ }
+ }
+
+ if (points[i][0] == points[r_points[0]][0] && points[i][1] == points[r_points[0]][1]) {
+ return top + 1; /* special case (mgomes) */
+ }
+
+ r_points[++top] = i; /* push points[i] onto stack */
+ }
+
+ if (minmax != minmin) {
+ r_points[++top] = minmin; /* push joining endpoint onto stack */
+ }
+
+ return top + 1;
+}
+
+struct PointRef {
+ const float *pt; /* 2d vector */
+};
+
+static int pointref_cmp_x(const void *a_, const void *b_)
+{
+ const struct PointRef *a = a_;
+ const struct PointRef *b = b_;
+ if (a->pt[0] > b->pt[0]) return 1;
+ else if (a->pt[0] < b->pt[0]) return -1;
+ else return 0;
+}
+
+static int pointref_cmp_y(const void *a_, const void *b_)
+{
+ const struct PointRef *a = a_;
+ const struct PointRef *b = b_;
+ if (a->pt[1] > b->pt[1]) return 1;
+ else if (a->pt[1] < b->pt[1]) return -1;
+ else return 0;
+}
+
+/**
+ * A.M. Andrew's monotone chain 2D convex hull algorithm
+ *
+ * \param points An array of 2D points.
+ * \param n The number of points in points.
+ * \param r_points An array of the convex hull vertex indices (max is n).
+ * \returns the number of points in r_points.
+ */
+int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[])
+{
+ struct PointRef *points_ref = MEM_mallocN(sizeof(*points_ref) * (size_t)n, __func__);
+ float (*points_sort)[2] = MEM_mallocN(sizeof(*points_sort) * (size_t)n, __func__);
+ int *points_map;
+ int tot, i;
+
+ for (i = 0; i < n; i++) {
+ points_ref[i].pt = points[i];
+ }
+
+ /* Sort the points by X, then by Y (required by the algorithm) */
+ qsort(points_ref, (size_t)n, sizeof(struct PointRef), pointref_cmp_x);
+ qsort(points_ref, (size_t)n, sizeof(struct PointRef), pointref_cmp_y);
+
+ for (i = 0; i < n; i++) {
+ memcpy(points_sort[i], points_ref[i].pt, sizeof(float[2]));
+ }
+
+ tot = BLI_convexhull_2d_sorted((const float (*)[2])points_sort, n, r_points);
+
+ /* map back to the original index values */
+ points_map = (int *)points_sort; /* abuse float array for temp storage */
+ for (i = 0; i < tot; i++) {
+ points_map[i] = (int)((const float(*)[2])points_ref[r_points[i]].pt - points);
+ }
+
+ memcpy(r_points, points_map, (size_t)tot * sizeof(*points_map));
+
+ MEM_freeN(points_ref);
+ MEM_freeN(points_sort);
+
+ return tot;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Helper functions */
+
+/** \name Utility Convex-Hull Functions
+ * \{ */
+
+/**
+ * \return The best angle for fitting the convex hull to an axis aligned bounding box.
+ *
+ * Intended to be used with #BLI_convexhull_2d
+ *
+ * \param points Orded hull points
+ * (result of #BLI_convexhull_2d mapped to a contiguous array).
+ *
+ * \note we could return the index of the best edge too if its needed.
+ */
+float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n)
+{
+ unsigned int i, i_prev;
+ float area_best = FLT_MAX;
+ float angle_best = 0.0f;
+
+ i_prev = n - 1;
+ for (i = 0; i < n; i++) {
+ const float *ev_a = points_hull[i];
+ const float *ev_b = points_hull[i_prev];
+ float dvec[2];
+
+ sub_v2_v2v2(dvec, ev_a, ev_b);
+ if (normalize_v2(dvec) != 0.0f) {
+ float mat[2][2];
+ float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX};
+
+ unsigned int j;
+ const float angle = atan2f(dvec[0], dvec[1]);
+ float area;
+
+ angle_to_mat2(mat, angle);
+
+ for (j = 0; j < n; j++) {
+ float tvec[2];
+ mul_v2_m2v2(tvec, mat, points_hull[j]);
+
+ min[0] = min_ff(min[0], tvec[0]);
+ min[1] = min_ff(min[1], tvec[1]);
+
+ max[0] = max_ff(max[0], tvec[0]);
+ max[1] = max_ff(max[1], tvec[1]);
+
+ area = (max[0] - min[0]) * (max[1] - min[1]);
+ if (area > area_best) {
+ break;
+ }
+ }
+
+ if (area < area_best) {
+ area_best = area;
+ angle_best = angle;
+ }
+ }
+
+ i_prev = i;
+ }
+
+ return angle_best;
+}
+
+/**
+ * Wrap #BLI_convexhull_aabb_fit_hull_2d and do the convex hull calculation.
+ *
+ * \param points arbitrary 2d points.
+ */
+float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], unsigned int n)
+{
+ int *index_map;
+ int tot;
+
+ float angle;
+
+ index_map = MEM_mallocN(sizeof(*index_map) * n, __func__);
+
+ tot = BLI_convexhull_2d((const float (*)[2])points, (int)n, index_map);
+
+ if (tot) {
+ float (*points_hull)[2];
+ int j;
+
+ points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)tot, __func__);
+ for (j = 0; j < tot; j++) {
+ copy_v2_v2(points_hull[j], points[index_map[j]]);
+ }
+
+ angle = BLI_convexhull_aabb_fit_hull_2d((const float (*)[2])points_hull, (unsigned int)tot);
+ MEM_freeN(points_hull);
+ }
+ else {
+ angle = 0.0f;
+ }
+
+ MEM_freeN(index_map);
+
+ return angle;
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index a3360921ee4..b26e007b3e6 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -18,12 +18,13 @@
* Contributor(s): Daniel Dunbar, Joseph Eagar
*
* ***** END GPL LICENSE BLOCK *****
- * A general (pointer -> pointer) hash table ADT
*/
/** \file blender/blenlib/intern/edgehash.c
* \ingroup bli
*
+ * A general (pointer -> pointer) hash table ADT
+ *
* \note Based on 'BLI_ghash.c', make sure these stay in sync.
*/
@@ -37,14 +38,7 @@
#include "BLI_utildefines.h"
#include "BLI_edgehash.h"
#include "BLI_mempool.h"
-
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
-# pragma GCC diagnostic error "-Wsign-compare"
-# pragma GCC diagnostic error "-Wconversion"
-# endif
-#endif
+#include "BLI_strict_flags.h"
/**************inlined code************/
static const unsigned int _ehash_hashsizes[] = {
@@ -54,7 +48,15 @@ static const unsigned int _ehash_hashsizes[] = {
268435459
};
-#define EDGE_HASH(v0, v1) ((v0 * 39) ^ (v1 * 31))
+/* internal flag to ensure sets values aren't used */
+#ifndef NDEBUG
+# define EDGEHASH_FLAG_IS_SET (1 << 8)
+# define IS_EDGEHASH_ASSERT(eh) BLI_assert((eh->flag & EDGEHASH_FLAG_IS_SET) == 0)
+// # define IS_EDGESET_ASSERT(es) BLI_assert((es->flag & EDGEHASH_FLAG_IS_SET) != 0)
+#else
+# define IS_EDGEHASH_ASSERT(eh)
+// # define IS_EDGESET_ASSERT(es)
+#endif
/* ensure v0 is smaller */
#define EDGE_ORD(v0, v1) \
@@ -66,131 +68,340 @@ static const unsigned int _ehash_hashsizes[] = {
/***/
-typedef struct EdgeEntry EdgeEntry;
-struct EdgeEntry {
- EdgeEntry *next;
+typedef struct EdgeEntry {
+ struct EdgeEntry *next;
unsigned int v0, v1;
void *val;
-};
+} EdgeEntry;
struct EdgeHash {
EdgeEntry **buckets;
BLI_mempool *epool;
- unsigned int nbuckets, nentries, cursize;
+ unsigned int nbuckets, nentries;
+ unsigned int cursize, flag;
};
-/***/
-EdgeHash *BLI_edgehash_new(void)
+/* -------------------------------------------------------------------- */
+/* EdgeHash API */
+
+/** \name Internal Utility API
+ * \{ */
+
+/**
+ * Get the hash for a key.
+ */
+BLI_INLINE unsigned int edgehash_keyhash(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
- EdgeHash *eh = MEM_callocN(sizeof(*eh), "EdgeHash");
- eh->cursize = 0;
- eh->nentries = 0;
- eh->nbuckets = _ehash_hashsizes[eh->cursize];
-
- eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets 2");
- eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, BLI_MEMPOOL_SYSMALLOC);
+ BLI_assert(v0 < v1);
- return eh;
+ return ((v0 * 39) ^ (v1 * 31)) % eh->nbuckets;
}
+/**
+ * Check if the number of items in the GHash is large enough to require more buckets.
+ */
+BLI_INLINE bool edgehash_test_expand_buckets(const unsigned int nentries, const unsigned int nbuckets)
+{
+ return (nentries > nbuckets * 3);
+}
-void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
+/**
+ * Expand buckets to the next size up.
+ */
+BLI_INLINE void edgehash_resize_buckets(EdgeHash *eh, const unsigned int nbuckets)
+{
+ EdgeEntry **buckets_old = eh->buckets;
+ EdgeEntry **buckets_new;
+ const unsigned int nbuckets_old = eh->nbuckets;
+ unsigned int i;
+ EdgeEntry *e;
+
+ BLI_assert(eh->nbuckets != nbuckets);
+
+ eh->nbuckets = nbuckets;
+ buckets_new = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets");
+
+ for (i = 0; i < nbuckets_old; i++) {
+ EdgeEntry *e_next;
+ for (e = buckets_old[i]; e; e = e_next) {
+ const unsigned hash = edgehash_keyhash(eh, e->v0, e->v1);
+ e_next = e->next;
+ e->next = buckets_new[hash];
+ buckets_new[hash] = e;
+ }
+ }
+
+ eh->buckets = buckets_new;
+ MEM_freeN(buckets_old);
+}
+
+/**
+ * Increase initial bucket size to match a reserved ammount.
+ */
+BLI_INLINE void edgehash_buckets_reserve(EdgeHash *eh, const unsigned int nentries_reserve)
+{
+ while (edgehash_test_expand_buckets(nentries_reserve, eh->nbuckets)) {
+ eh->nbuckets = _ehash_hashsizes[++eh->cursize];
+ }
+}
+
+/**
+ * Internal lookup function.
+ * Takes a hash argument to avoid calling #ghash_keyhash multiple times.
+ */
+BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(EdgeHash *eh, unsigned int v0, unsigned int v1,
+ const unsigned int hash)
+{
+ EdgeEntry *e;
+ BLI_assert(v0 < v1);
+ for (e = eh->buckets[hash]; e; e = e->next) {
+ if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) {
+ return e;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Internal lookup function. Only wraps #edgehash_lookup_entry_ex
+ */
+BLI_INLINE EdgeEntry *edgehash_lookup_entry(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
unsigned int hash;
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
+ return edgehash_lookup_entry_ex(eh, v0, v1, hash);
+}
+
+
+static EdgeHash *edgehash_new(const char *info,
+ const unsigned int nentries_reserve,
+ const unsigned int entry_size)
+{
+ EdgeHash *eh = MEM_mallocN(sizeof(*eh), info);
+
+ eh->nbuckets = _ehash_hashsizes[0]; /* eh->cursize */
+ eh->nentries = 0;
+ eh->cursize = 0;
+ eh->flag = 0;
+
+ /* if we have reserved the number of elements that this hash will contain */
+ if (nentries_reserve) {
+ edgehash_buckets_reserve(eh, nentries_reserve);
+ }
+
+ eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets");
+ eh->epool = BLI_mempool_create(entry_size, 512, 512, BLI_MEMPOOL_SYSMALLOC);
+
+ return eh;
+}
+
+/**
+ * Internal insert function.
+ * Takes a hash argument to avoid calling #edgehash_keyhash multiple times.
+ */
+BLI_INLINE void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val,
+ unsigned int hash)
+{
EdgeEntry *e = BLI_mempool_alloc(eh->epool);
+ BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0));
+ IS_EDGEHASH_ASSERT(eh);
+
/* this helps to track down errors with bad edge data */
+ BLI_assert(v0 < v1);
BLI_assert(v0 != v1);
- EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ e->next = eh->buckets[hash];
+ e->v0 = v0;
+ e->v1 = v1;
+ e->val = val;
+ eh->buckets[hash] = e;
- hash = EDGE_HASH(v0, v1) % eh->nbuckets;
+ if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) {
+ edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]);
+ }
+}
+
+/**
+ * Insert function that doesn't set the value (use for EdgeSet)
+ */
+BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsigned int v1,
+ unsigned int hash)
+{
+ EdgeEntry *e = BLI_mempool_alloc(eh->epool);
+
+ BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0));
+
+ /* this helps to track down errors with bad edge data */
+ BLI_assert(v0 < v1);
+ BLI_assert(v0 != v1);
e->next = eh->buckets[hash];
e->v0 = v0;
e->v1 = v1;
- e->val = val;
+ /* intentionally leave value unset */
eh->buckets[hash] = e;
- if (UNLIKELY(++eh->nentries > eh->nbuckets / 2)) {
- EdgeEntry **old = eh->buckets;
- const unsigned int nold = eh->nbuckets;
- unsigned int i;
+ if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) {
+ edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]);
+ }
+}
- eh->nbuckets = _ehash_hashsizes[++eh->cursize];
- eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets");
-
- for (i = 0; i < nold; i++) {
- EdgeEntry *e_next;
- for (e = old[i]; e; e = e_next) {
- e_next = e->next;
- hash = EDGE_HASH(e->v0, e->v1) % eh->nbuckets;
- e->next = eh->buckets[hash];
- eh->buckets[hash] = e;
- }
- }
+BLI_INLINE void edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
+{
+ unsigned int hash;
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
+ edgehash_insert_ex(eh, v0, v1, val, hash);
+}
+
+/**
+ * Run free callbacks for freeing entries.
+ */
+static void edgehash_free_cb(EdgeHash *eh, EdgeHashFreeFP valfreefp)
+{
+ unsigned int i;
+
+ BLI_assert(valfreefp);
+
+ for (i = 0; i < eh->nbuckets; i++) {
+ EdgeEntry *e;
+
+ for (e = eh->buckets[i]; e; ) {
+ EdgeEntry *e_next = e->next;
- MEM_freeN(old);
+ if (valfreefp) valfreefp(e->val);
+
+ e = e_next;
+ }
}
}
-void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1)
+/** \} */
+
+
+/** \name Public API
+ * \{ */
+
+/* Public API */
+
+EdgeHash *BLI_edgehash_new_ex(const char *info,
+ const unsigned int nentries_reserve)
+{
+ return edgehash_new(info,
+ nentries_reserve,
+ sizeof(EdgeEntry));
+}
+
+EdgeHash *BLI_edgehash_new(const char *info)
+{
+ return BLI_edgehash_new_ex(info, 0);
+}
+
+/**
+ * Insert edge (\a v0, \a v1) into hash with given value, does
+ * not check for duplicates.
+ */
+void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
+{
+ edgehash_insert(eh, v0, v1, val);
+}
+
+/**
+ * Assign a new value to a key that may already be in edgehash.
+ */
+bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
{
unsigned int hash;
EdgeEntry *e;
+ IS_EDGEHASH_ASSERT(eh);
+
EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash(eh, v0, v1);
- hash = EDGE_HASH(v0, v1) % eh->nbuckets;
- for (e = eh->buckets[hash]; e; e = e->next)
- if (v0 == e->v0 && v1 == e->v1)
- return &e->val;
+ e = edgehash_lookup_entry_ex(eh, v0, v1, hash);
+ if (e) {
+ e->val = val;
+ return false;
+ }
+ else {
+ edgehash_insert_ex(eh, v0, v1, val, hash);
+ return true;
+ }
+}
- return NULL;
+/**
+ * Return pointer to value for given edge (\a v0, \a v1),
+ * or NULL if key does not exist in hash.
+ */
+void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1)
+{
+ EdgeEntry *e = edgehash_lookup_entry(eh, v0, v1);
+ IS_EDGEHASH_ASSERT(eh);
+ return e ? &e->val : NULL;
}
+/**
+ * Return value for given edge (\a v0, \a v1), or NULL if
+ * if key does not exist in hash. (If need exists
+ * to differentiate between key-value being NULL and
+ * lack of key then see BLI_edgehash_lookup_p().
+ */
void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
- void **value_p = BLI_edgehash_lookup_p(eh, v0, v1);
-
- return value_p ? *value_p : NULL;
+ EdgeEntry *e = edgehash_lookup_entry(eh, v0, v1);
+ IS_EDGEHASH_ASSERT(eh);
+ return e ? e->val : NULL;
}
+/**
+ * Return boolean true/false if edge (v0,v1) in hash.
+ */
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
- return BLI_edgehash_lookup_p(eh, v0, v1) != NULL;
+ return (edgehash_lookup_entry(eh, v0, v1) != NULL);
}
+/**
+ * Return number of keys in hash.
+ */
int BLI_edgehash_size(EdgeHash *eh)
{
return (int)eh->nentries;
}
-void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp)
+/**
+ * Remove all edges from hash.
+ */
+void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp,
+ const unsigned int nentries_reserve)
{
- unsigned int i;
-
- for (i = 0; i < eh->nbuckets; i++) {
- EdgeEntry *e;
-
- for (e = eh->buckets[i]; e; ) {
- EdgeEntry *n = e->next;
-
- if (valfreefp) valfreefp(e->val);
- BLI_mempool_free(eh->epool, e);
-
- e = n;
- }
- eh->buckets[i] = NULL;
- }
+ if (valfreefp)
+ edgehash_free_cb(eh, valfreefp);
+ eh->nbuckets = _ehash_hashsizes[0]; /* eh->cursize */
eh->nentries = 0;
+ eh->cursize = 0;
+
+ if (nentries_reserve) {
+ edgehash_buckets_reserve(eh, nentries_reserve);
+ }
+
+ MEM_freeN(eh->buckets);
+ eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets");
+
+ BLI_mempool_clear_ex(eh->epool, nentries_reserve ? (int)nentries_reserve : -1);
}
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp)
{
- BLI_edgehash_clear(eh, valfreefp);
+ BLI_assert((int)eh->nentries == BLI_mempool_count(eh->epool));
+
+ if (valfreefp)
+ edgehash_free_cb(eh, valfreefp);
BLI_mempool_destroy(eh->epool);
@@ -199,7 +410,24 @@ void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp)
}
-/***/
+void BLI_edgehash_flag_set(EdgeHash *eh, unsigned int flag)
+{
+ eh->flag |= flag;
+}
+
+void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned int flag)
+{
+ eh->flag &= ~flag;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* EdgeHash Iterator API */
+
+/** \name Iterator API
+ * \{ */
struct EdgeHashIterator {
EdgeHash *eh;
@@ -207,6 +435,12 @@ struct EdgeHashIterator {
EdgeEntry *curEntry;
};
+
+/**
+ * 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(gh) times before becoming done.
+ */
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
{
EdgeHashIterator *ehi = MEM_mallocN(sizeof(*ehi), "eh iter");
@@ -221,11 +455,18 @@ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
}
return ehi;
}
+
+/**
+ * Free an EdgeHashIterator.
+ */
void BLI_edgehashIterator_free(EdgeHashIterator *ehi)
{
MEM_freeN(ehi);
}
+/**
+ * Retrieve the key from an iterator.
+ */
void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r)
{
if (ehi->curEntry) {
@@ -233,11 +474,26 @@ void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsi
*v1_r = ehi->curEntry->v1;
}
}
+
+/**
+ * Retrieve the value from an iterator.
+ */
void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi)
{
return ehi->curEntry ? ehi->curEntry->val : NULL;
}
+/**
+ * Retrieve the pointer to the value from an iterator.
+ */
+void **BLI_edgehashIterator_getValue_p(EdgeHashIterator *ehi)
+{
+ return ehi->curEntry ? &ehi->curEntry->val : NULL;
+}
+
+/**
+ * Set the value for an iterator.
+ */
void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val)
{
if (ehi->curEntry) {
@@ -245,6 +501,9 @@ void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val)
}
}
+/**
+ * Steps the iterator to the next index.
+ */
void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
{
if (ehi->curEntry) {
@@ -259,7 +518,88 @@ void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
}
}
}
+
+/**
+ * Determine if an iterator is done.
+ */
bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi)
{
return (ehi->curEntry == NULL);
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/* EdgeSet API */
+
+/* Use edgehash API to give 'set' functionality */
+
+/** \name EdgeSet Functions
+ * \{ */
+EdgeSet *BLI_edgeset_new_ex(const char *info,
+ const unsigned int nentries_reserve)
+{
+ EdgeSet *es = (EdgeSet *)edgehash_new(info,
+ nentries_reserve,
+ sizeof(EdgeEntry) - sizeof(void *));
+#ifndef NDEBUG
+ ((EdgeHash *)es)->flag |= EDGEHASH_FLAG_IS_SET;
+#endif
+ return es;
+}
+
+EdgeSet *BLI_edgeset_new(const char *info)
+{
+ return BLI_edgeset_new_ex(info, 0);
+}
+
+int BLI_edgeset_size(EdgeSet *es)
+{
+ return (int)((EdgeHash *)es)->nentries;
+}
+
+/**
+ * Adds the key to the set (no checks for unique keys!).
+ * Matching #BLI_edgehash_insert
+ */
+void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1)
+{
+ unsigned int hash;
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash((EdgeHash *)es, v0, v1);
+ edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, hash);
+}
+
+/**
+ * Assign a new value to a key that may already be in edgehash.
+ */
+bool BLI_edgeset_reinsert(EdgeSet *es, unsigned int v0, unsigned int v1)
+{
+ unsigned int hash;
+ EdgeEntry *e;
+
+ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
+ hash = edgehash_keyhash((EdgeHash *)es, v0, v1);
+
+ e = edgehash_lookup_entry_ex((EdgeHash *)es, v0, v1, hash);
+ if (e) {
+ return false;
+ }
+ else {
+ edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, hash);
+ return true;
+ }
+}
+
+bool BLI_edgeset_haskey(EdgeSet *es, unsigned int v0, unsigned int v1)
+{
+ return (edgehash_lookup_entry((EdgeHash *)es, v0, v1) != NULL);
+}
+
+
+void BLI_edgeset_free(EdgeSet *es)
+{
+ BLI_edgehash_free((EdgeHash *)es, NULL);
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index 4809ba59aaf..55726565f59 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -215,6 +215,11 @@ bool BLI_file_touch(const char *file)
#ifdef WIN32
+static void callLocalErrorCallBack(const char *err)
+{
+ printf("%s\n", err);
+}
+
static char str[MAXPATHLEN + 12];
FILE *BLI_fopen(const char *filename, const char *mode)
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
index 7f158bc3efb..6967742f89b 100644
--- a/source/blender/blenlib/intern/gsqueue.c
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -35,6 +35,7 @@
#include "BLI_utildefines.h"
#include "BLI_gsqueue.h"
+#include "BLI_strict_flags.h"
typedef struct _GSQueueElem GSQueueElem;
struct _GSQueueElem {
@@ -93,7 +94,7 @@ int BLI_gsqueue_size(GSQueue *gq)
*/
void BLI_gsqueue_peek(GSQueue *gq, void *item_r)
{
- memcpy(item_r, &gq->head[1], gq->elem_size);
+ memcpy(item_r, &gq->head[1], (size_t)gq->elem_size);
}
/**
@@ -114,7 +115,7 @@ void BLI_gsqueue_pop(GSQueue *gq, void *item_r)
gq->head = gq->head->next;
}
- if (item_r) memcpy(item_r, &elem[1], gq->elem_size);
+ if (item_r) memcpy(item_r, &elem[1], (size_t)gq->elem_size);
MEM_freeN(elem);
}
@@ -130,11 +131,11 @@ void BLI_gsqueue_push(GSQueue *gq, void *item)
/* compare: prevent events added double in row */
if (!BLI_gsqueue_is_empty(gq)) {
- if (0 == memcmp(item, &gq->head[1], gq->elem_size))
+ if (0 == memcmp(item, &gq->head[1], (size_t)gq->elem_size))
return;
}
- elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push");
- memcpy(&elem[1], item, gq->elem_size);
+ elem = MEM_mallocN(sizeof(*elem) + (size_t)gq->elem_size, "gqueue_push");
+ memcpy(&elem[1], item, (size_t)gq->elem_size);
elem->next = NULL;
if (BLI_gsqueue_is_empty(gq)) {
@@ -154,8 +155,8 @@ void BLI_gsqueue_push(GSQueue *gq, void *item)
*/
void BLI_gsqueue_pushback(GSQueue *gq, void *item)
{
- GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push");
- memcpy(&elem[1], item, gq->elem_size);
+ GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + (size_t)gq->elem_size, "gqueue_push");
+ memcpy(&elem[1], item, (size_t)gq->elem_size);
elem->next = gq->head;
if (BLI_gsqueue_is_empty(gq)) {
@@ -176,5 +177,3 @@ void BLI_gsqueue_free(GSQueue *gq)
}
MEM_freeN(gq);
}
-
-
diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c
index aa08a780394..e89f7fd795b 100644
--- a/source/blender/blenlib/intern/lasso.c
+++ b/source/blender/blenlib/intern/lasso.c
@@ -34,12 +34,13 @@
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_strict_flags.h"
#include "BLI_lasso.h" /* own include */
-void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const short moves)
+void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const unsigned int moves)
{
- short a;
+ unsigned int a;
rect->xmin = rect->xmax = mcords[0][0];
rect->ymin = rect->ymax = mcords[0][1];
@@ -53,28 +54,28 @@ void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const short moves)
}
-bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves,
+bool BLI_lasso_is_point_inside(const int mcords[][2], const unsigned int moves,
const int sx, const int sy,
const int error_value)
{
- if (sx == error_value) {
+ if (sx == error_value || moves == 0) {
return false;
}
else {
int pt[2] = {sx, sy};
- return isect_point_poly_v2_int(pt, mcords, moves);
+ return isect_point_poly_v2_int(pt, mcords, moves, true);
}
}
/* edge version for lasso select. we assume boundbox check was done */
-bool BLI_lasso_is_edge_inside(const int mcords[][2], const short moves,
+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)
{
int v1[2], v2[2];
- int a;
+ unsigned int a;
- if (x0 == error_value || x1 == error_value) {
+ if (x0 == error_value || x1 == error_value || moves == 0) {
return false;
}
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index ded4f31ae05..2c59b940f8c 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -129,6 +129,30 @@ bool BLI_remlink_safe(ListBase *listbase, void *vlink)
}
}
+/**
+ * Removes the head from \a listbase and returns it.
+ */
+void *BLI_pophead(ListBase *listbase)
+{
+ Link *link;
+ if ((link = listbase->first)) {
+ BLI_remlink(listbase, link);
+ }
+ return link;
+}
+
+
+/**
+ * Removes the tail from \a listbase and returns it.
+ */
+void *BLI_poptail(ListBase *listbase)
+{
+ Link *link;
+ if ((link = listbase->last)) {
+ BLI_remlink(listbase, link);
+ }
+ return link;
+}
/**
* Removes \a vlink from listbase and disposes of it. Assumes it is linked into there!
@@ -557,19 +581,34 @@ void BLI_reverselist(ListBase *lb)
/**
* \param vlink Link to make first.
*/
-void BLI_rotatelist(ListBase *lb, void *vlink)
+void BLI_rotatelist_first(ListBase *lb, void *vlink)
{
/* make circular */
- ((LinkData *)lb->first)->prev = lb->last;
- ((LinkData *)lb->last)->next = lb->first;
+ ((Link *)lb->first)->prev = lb->last;
+ ((Link *)lb->last)->next = lb->first;
lb->first = vlink;
- lb->last = ((LinkData *)vlink)->prev;
+ lb->last = ((Link *)vlink)->prev;
- ((LinkData *)lb->first)->prev = NULL;
- ((LinkData *)lb->last)->next = NULL;
+ ((Link *)lb->first)->prev = NULL;
+ ((Link *)lb->last)->next = NULL;
}
+/**
+ * \param vlink Link to make last.
+ */
+void BLI_rotatelist_last(ListBase *lb, void *vlink)
+{
+ /* make circular */
+ ((Link *)lb->first)->prev = lb->last;
+ ((Link *)lb->last)->next = lb->first;
+
+ lb->first = ((Link *)vlink)->next;
+ lb->last = vlink;
+
+ ((Link *)lb->first)->prev = NULL;
+ ((Link *)lb->last)->next = NULL;
+}
/* create a generic list node containing link to provided data */
LinkData *BLI_genericNodeN(void *data)
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 3ffd96f62c7..e6509db1c5e 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -131,8 +131,9 @@ MINLINE int power_of_2_max_i(int n)
if (is_power_of_2_i(n))
return n;
- while (!is_power_of_2_i(n))
+ do {
n = n & (n - 1);
+ } while (!is_power_of_2_i(n));
return n * 2;
}
@@ -152,6 +153,14 @@ MINLINE int divide_round_i(int a, int b)
return (2 * a + b) / (2 * b);
}
+/**
+ * modulo that handles negative numbers, works the same as Python's.
+ */
+MINLINE int mod_i(int i, int n)
+{
+ return (i % n + n) % n;
+}
+
MINLINE unsigned int highest_order_bit_i(unsigned int n)
{
n |= (n >> 1);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 9b8fd0ad85b..0d15eede9ea 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -183,6 +183,28 @@ float area_poly_v2(int nr, float verts[][2])
return fabsf(0.5f * area);
}
+/********************************* Planes **********************************/
+
+/**
+ * Calculate a plane from a point and a direction,
+ * \note \a point_no isn't required to be normalized.
+ */
+void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
+{
+ copy_v3_v3(r_plane, plane_no);
+ r_plane[3] = -dot_v3v3(r_plane, plane_co);
+}
+
+/**
+ * Get a point and a normal from a plane.
+ */
+void plane_to_point_normal_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3])
+{
+ const float length = normalize_v3_v3(r_plane_no, plane);
+ madd_v3_v3v3fl(r_plane_co, r_plane_no, r_plane_no, (-plane[3] / length) - 1.0f);
+}
+
+
/********************************* Volume **********************************/
/**
@@ -283,45 +305,39 @@ void closest_to_line_segment_v3(float close_r[3], const float v1[3], const float
copy_v3_v3(close_r, cp);
}
-/* find the closest point on a plane to another point and store it in close_r
- * close_r: return coordinate
- * plane_co: a point on the plane
- * plane_no_unit: the plane's normal, and d is the last number in the plane equation 0 = ax + by + cz + d
- * pt: the point that you want the nearest of
+/**
+ * Find the closest point on a plane.
+ *
+ * \param close_r Return coordinate
+ * \param plane The plane to test against.
+ * \param pt The point to find the nearest of
+ *
+ * \note non-unit-length planes are supported.
*/
-
-void closest_to_plane_v3(float close_r[3], const float plane_co[3], const float plane_no_unit[3], const float pt[3])
+void closest_to_plane_v3(float close_r[3], const float plane[4], const float pt[3])
{
- float temp[3];
- float dotprod;
-
- sub_v3_v3v3(temp, pt, plane_co);
- dotprod = dot_v3v3(temp, plane_no_unit);
-
- close_r[0] = pt[0] - (plane_no_unit[0] * dotprod);
- close_r[1] = pt[1] - (plane_no_unit[1] * dotprod);
- close_r[2] = pt[2] - (plane_no_unit[2] * dotprod);
+ const float length = len_squared_v3(plane);
+ const float side = plane_point_side_v3(plane, pt);
+ madd_v3_v3v3fl(close_r, pt, plane, -side / length);
}
-/* signed distance from the point to the plane in 3D */
-float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3])
+float dist_squared_to_plane_v3(const float pt[3], const float plane[4])
{
- float plane_co_other[3];
-
- add_v3_v3v3(plane_co_other, plane_co, plane_no_unit);
-
- return line_point_factor_v3(p, plane_co, plane_co_other);
+ const float length = len_squared_v3(plane);
+ const float side = plane_point_side_v3(plane, pt);
+ const float fac = side / length;
+ return copysign(length * (fac * fac), side);
}
-float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3])
+/**
+ * Return the signed distance from the point to the plane.
+ */
+float dist_to_plane_v3(const float pt[3], const float plane[4])
{
- float plane_no_unit[3];
- float plane_co_other[3];
-
- normalize_v3_v3(plane_no_unit, plane_no);
- add_v3_v3v3(plane_co_other, plane_co, plane_no_unit);
-
- return line_point_factor_v3(p, plane_co, plane_co_other);
+ const float length = len_squared_v3(plane);
+ const float side = plane_point_side_v3(plane, pt);
+ const float fac = side / length;
+ return sqrtf(length) * fac;
}
/* distance v1 to line-piece l1-l2 in 3D */
@@ -696,16 +712,16 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2],
}
/* point in polygon (keep float and int versions in sync) */
-bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr)
+bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr,
+ const bool use_holes)
{
/* we do the angle rule, define that all added angles should be about zero or (2 * PI) */
float angletot = 0.0;
float fp1[2], fp2[2];
- int i;
+ unsigned int i;
const float *p1, *p2;
p1 = verts[nr - 1];
- p2 = verts[0];
/* first vector */
fp1[0] = (float)(p1[0] - pt[0]);
@@ -714,6 +730,8 @@ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr
for (i = 0; i < nr; i++) {
float dot, ang, cross;
+ p2 = verts[i];
+
/* second vector */
fp2[0] = (float)(p2[0] - pt[0]);
fp2[1] = (float)(p2[1] - pt[1]);
@@ -730,21 +748,28 @@ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr
/* circulate */
copy_v2_v2(fp1, fp2);
p1 = p2;
- p2 = verts[i + 1];
}
- return (fabsf(angletot) > 4.0f);
+ angletot = fabsf(angletot);
+ if (use_holes) {
+ const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
+ angletot -= nested * (float)(M_PI * 2.0);
+ return (angletot > 4.0f) != (nested % 2);
+ }
+ else {
+ return (angletot > 4.0f);
+ }
}
-bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr)
+bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr,
+ const bool use_holes)
{
/* we do the angle rule, define that all added angles should be about zero or (2 * PI) */
float angletot = 0.0;
float fp1[2], fp2[2];
- int i;
+ unsigned int i;
const int *p1, *p2;
p1 = verts[nr - 1];
- p2 = verts[0];
/* first vector */
fp1[0] = (float)(p1[0] - pt[0]);
@@ -753,6 +778,8 @@ bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr
for (i = 0; i < nr; i++) {
float dot, ang, cross;
+ p2 = verts[i];
+
/* second vector */
fp2[0] = (float)(p2[0] - pt[0]);
fp2[1] = (float)(p2[1] - pt[1]);
@@ -769,10 +796,17 @@ bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr
/* circulate */
copy_v2_v2(fp1, fp2);
p1 = p2;
- p2 = verts[i + 1];
}
- return (fabsf(angletot) > 4.0f);
+ angletot = fabsf(angletot);
+ if (use_holes) {
+ const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f);
+ angletot -= nested * (float)(M_PI * 2.0);
+ return (angletot > 4.0f) != (nested % 2);
+ }
+ else {
+ return (angletot > 4.0f);
+ }
}
/* point in tri */
@@ -878,6 +912,45 @@ bool isect_line_tri_v3(const float p1[3], const float p2[3],
return 1;
}
+/* like isect_line_tri_v3, but allows epsilon tolerance around triangle */
+bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float *r_lambda, float r_uv[2], const float epsilon)
+{
+
+ float p[3], s[3], d[3], e1[3], e2[3], q[3];
+ float a, f, u, v;
+
+ sub_v3_v3v3(e1, v1, v0);
+ sub_v3_v3v3(e2, v2, v0);
+ sub_v3_v3v3(d, p2, p1);
+
+ cross_v3_v3v3(p, d, e2);
+ a = dot_v3v3(e1, p);
+ if ((a > -0.000001f) && (a < 0.000001f)) return 0;
+ f = 1.0f / a;
+
+ sub_v3_v3v3(s, p1, v0);
+
+ u = f * dot_v3v3(s, p);
+ if ((u < -epsilon) || (u > 1.0f + epsilon)) return 0;
+
+ cross_v3_v3v3(q, s, e1);
+
+ v = f * dot_v3v3(d, q);
+ if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return 0;
+
+ *r_lambda = f * dot_v3v3(e2, q);
+ if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
+
+ if (r_uv) {
+ r_uv[0] = u;
+ r_uv[1] = v;
+ }
+
+ return 1;
+}
+
/* moved from effect.c
* test if the ray starting at p1 going in d direction intersects the triangle v0..v2
* return non zero if it does
@@ -1043,57 +1116,51 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
}
/**
- * Intersect line/plane, optionally treat line as directional (like a ray) with the no_flip argument.
+ * Check if a point is behind all planes.
+ */
+bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3])
+{
+ int i;
+
+ for (i = 0; i < totplane; i++) {
+ if (plane_point_side_v3(planes[i], p) > 0.0f) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Intersect line/plane.
*
* \param out The intersection point.
* \param l1 The first point of the line.
* \param l2 The second point of the line.
* \param plane_co A point on the plane to intersect with.
* \param plane_no The direction of the plane (does not need to be normalized).
- * \param no_flip When true, the intersection point will always be from l1 to l2, even if this is not on the plane.
+ *
+ * \note #line_plane_factor_v3() shares logic.
*/
bool isect_line_plane_v3(float out[3],
const float l1[3], const float l2[3],
- const float plane_co[3], const float plane_no[3], const bool no_flip)
+ const float plane_co[3], const float plane_no[3])
{
- float l_vec[3]; /* l1 -> l2 normalized vector */
- float p_no[3]; /* 'plane_no' normalized */
+ float u[3], h[3];
float dot;
- sub_v3_v3v3(l_vec, l2, l1);
-
- normalize_v3(l_vec);
- normalize_v3_v3(p_no, plane_no);
+ sub_v3_v3v3(u, l2, l1);
+ sub_v3_v3v3(h, l1, plane_co);
+ dot = dot_v3v3(plane_no, u);
- dot = dot_v3v3(l_vec, p_no);
- if (dot == 0.0f) {
- return 0;
+ if (fabsf(dot) > FLT_EPSILON) {
+ float lambda = -dot_v3v3(plane_no, h) / dot;
+ madd_v3_v3v3fl(out, l1, u, lambda);
+ return true;
}
else {
- float l1_plane[3]; /* line point aligned with the plane */
- float dist; /* 'plane_no' aligned distance to the 'plane_co' */
-
- /* for predictable flipping since the plane is only used to
- * define a direction, ignore its flipping and aligned with 'l_vec' */
- if (dot < 0.0f) {
- dot = -dot;
- negate_v3(p_no);
- }
-
- add_v3_v3v3(l1_plane, l1, p_no);
-
- dist = line_point_factor_v3(plane_co, l1, l1_plane);
-
- /* treat line like a ray, when 'no_flip' is set */
- if (no_flip && dist < 0.0f) {
- dist = -dist;
- }
-
- mul_v3_fl(l_vec, dist / dot);
-
- add_v3_v3v3(out, l1, l_vec);
-
- return 1;
+ /* The segment is parallel to plane */
+ return false;
}
}
@@ -1119,7 +1186,7 @@ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); /* direction is simply the cross product */
cross_v3_v3v3(plane_a_co_other, plane_a_no, r_isect_no);
add_v3_v3(plane_a_co_other, plane_a_co);
- isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no, FALSE);
+ isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no);
}
@@ -1561,7 +1628,7 @@ bool isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3],
tymax = (bbox[1 - data->sign[1]][1] - data->ray_start[1]) * data->ray_inv_dir[1];
if ((tmin > tymax) || (tymin > tmax))
- return FALSE;
+ return false;
if (tymin > tmin)
tmin = tymin;
@@ -1573,7 +1640,7 @@ bool isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3],
tzmax = (bbox[1 - data->sign[2]][2] - data->ray_start[2]) * data->ray_inv_dir[2];
if ((tmin > tzmax) || (tzmin > tmax))
- return FALSE;
+ return false;
if (tzmin > tmin)
tmin = tzmin;
@@ -1585,7 +1652,7 @@ bool isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3],
if (tmin_out)
(*tmin_out) = tmin;
- return TRUE;
+ return true;
}
/* find closest point to p on line through (l1, l2) and return lambda,
@@ -1645,6 +1712,20 @@ float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2
#endif
}
+/**
+ * \note #isect_line_plane_v3() shares logic
+ */
+float line_plane_factor_v3(const float plane_co[3], const float plane_no[3],
+ const float l1[3], const float l2[3])
+{
+ float u[3], h[3];
+ float dot;
+ sub_v3_v3v3(u, l2, l1);
+ sub_v3_v3v3(h, l1, plane_co);
+ dot = dot_v3v3(plane_no, u);
+ return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f;
+}
+
/* ensure the distance between these points is no greater then 'dist'
* if it is, scale then both into the center */
void limit_dist_v3(float v1[3], float v2[3], const float dist)
@@ -1757,7 +1838,7 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
if (div == 0.0f) /* parallel */
return 1;
- t = -(dot_v3v3(p1, plane) + plane[3]) / div;
+ t = -plane_point_side_v3(plane, p1) / div;
if (div > 0.0f) {
/* behind plane, completely clipped */
@@ -1811,7 +1892,7 @@ bool clip_segment_v3_plane_n(float r_p1[3], float r_p2[3], float plane_array[][4
const float div = dot_v3v3(dp, plane);
if (div != 0.0f) {
- const float t = -(dot_v3v3(p1, plane) + plane[3]) / div;
+ const float t = -plane_point_side_v3(plane, p1) / div;
if (div > 0.0f) {
/* clip a */
if (t >= 1.0f) {
@@ -1916,6 +1997,59 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int
}
}
+void fill_poly_v2i_n(
+ const int xmin, const int ymin, const int xmax, const int ymax,
+ const int verts[][2], const int nr,
+ void (*callback)(int, int, void *), void *userData)
+{
+ /* originally by Darel Rex Finley, 2007 */
+
+ int nodes, pixel_y, i, j, swap;
+ int *node_x = MEM_mallocN(sizeof(*node_x) * (nr + 1), __func__);
+
+ /* Loop through the rows of the image. */
+ for (pixel_y = ymin; pixel_y < ymax; pixel_y++) {
+
+ /* Build a list of nodes. */
+ nodes = 0; j = nr - 1;
+ for (i = 0; i < nr; i++) {
+ if ((verts[i][1] < pixel_y && verts[j][1] >= pixel_y) ||
+ (verts[j][1] < pixel_y && verts[i][1] >= pixel_y))
+ {
+ node_x[nodes++] = (int)(verts[i][0] +
+ ((double)(pixel_y - verts[i][1]) / (verts[j][1] - verts[i][1])) *
+ (verts[j][0] - verts[i][0]));
+ }
+ j = i;
+ }
+
+ /* Sort the nodes, via a simple "Bubble" sort. */
+ i = 0;
+ while (i < nodes - 1) {
+ if (node_x[i] > node_x[i + 1]) {
+ SWAP_TVAL(swap, node_x[i], node_x[i + 1]);
+ if (i) i--;
+ }
+ else {
+ i++;
+ }
+ }
+
+ /* Fill the pixels between node pairs. */
+ for (i = 0; i < nodes; i += 2) {
+ if (node_x[i] >= xmax) break;
+ if (node_x[i + 1] > xmin) {
+ if (node_x[i ] < xmin) node_x[i ] = xmin;
+ if (node_x[i + 1] > xmax) node_x[i + 1] = xmax;
+ for (j = node_x[i]; j < node_x[i + 1]; j++) {
+ callback(j - xmin, pixel_y - ymin, userData);
+ }
+ }
+ }
+ }
+ MEM_freeN(node_x);
+}
+
/****************************** Axis Utils ********************************/
/**
@@ -2137,8 +2271,6 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \
fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : 0.0f)
- float wtot, area;
-
const float dirs[4][2] = {
{v1[0] - co[0], v1[1] - co[1]},
{v2[0] - co[0], v2[1] - co[1]},
@@ -2153,20 +2285,29 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
len_v2(dirs[3]),
};
- /* variable 'area' is just for storage,
- * the order its initialized doesn't matter */
+ /* avoid divide by zero */
+ if (UNLIKELY(lens[0] < FLT_EPSILON)) { w[0] = 1.0f; w[1] = w[2] = w[3] = 0.0f; }
+ else if (UNLIKELY(lens[1] < FLT_EPSILON)) { w[1] = 1.0f; w[0] = w[2] = w[3] = 0.0f; }
+ else if (UNLIKELY(lens[2] < FLT_EPSILON)) { w[2] = 1.0f; w[0] = w[1] = w[3] = 0.0f; }
+ else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f;
+ }
+ else {
+ float wtot, area;
+
+ /* variable 'area' is just for storage,
+ * the order its initialized doesn't matter */
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunsequenced"
#endif
- /* inline mean_value_half_tan four times here */
- float t[4] = {
- MEAN_VALUE_HALF_TAN_V2(area, 0, 1),
- MEAN_VALUE_HALF_TAN_V2(area, 1, 2),
- MEAN_VALUE_HALF_TAN_V2(area, 2, 3),
- MEAN_VALUE_HALF_TAN_V2(area, 3, 0),
- };
+ /* inline mean_value_half_tan four times here */
+ float t[4] = {
+ MEAN_VALUE_HALF_TAN_V2(area, 0, 1),
+ MEAN_VALUE_HALF_TAN_V2(area, 1, 2),
+ MEAN_VALUE_HALF_TAN_V2(area, 2, 3),
+ MEAN_VALUE_HALF_TAN_V2(area, 3, 0),
+ };
#ifdef __clang__
# pragma clang diagnostic pop
@@ -2174,18 +2315,19 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
#undef MEAN_VALUE_HALF_TAN_V2
- w[0] = (t[3] + t[0]) / lens[0];
- w[1] = (t[0] + t[1]) / lens[1];
- w[2] = (t[1] + t[2]) / lens[2];
- w[3] = (t[2] + t[3]) / lens[3];
+ w[0] = (t[3] + t[0]) / lens[0];
+ w[1] = (t[0] + t[1]) / lens[1];
+ w[2] = (t[1] + t[2]) / lens[2];
+ w[3] = (t[2] + t[3]) / lens[3];
- wtot = w[0] + w[1] + w[2] + w[3];
+ wtot = w[0] + w[1] + w[2] + w[3];
- if (wtot != 0.0f) {
- mul_v4_fl(w, 1.0f / wtot);
- }
- else { /* dummy values for zero area face */
- copy_v4_fl(w, 1.0f / 4.0f);
+ if (wtot != 0.0f) {
+ mul_v4_fl(w, 1.0f / wtot);
+ }
+ else { /* dummy values for zero area face */
+ copy_v4_fl(w, 1.0f / 4.0f);
+ }
}
}
@@ -2323,17 +2465,16 @@ int interp_sparse_array(float *array, int const list_size, const float skipval)
* more than 3 vertices */
static float mean_value_half_tan_v3(const float v1[3], const float v2[3], const float v3[3])
{
- float d2[3], d3[3], cross[3], area, dot, len;
+ float d2[3], d3[3], cross[3], area;
sub_v3_v3v3(d2, v2, v1);
sub_v3_v3v3(d3, v3, v1);
cross_v3_v3v3(cross, d2, d3);
area = len_v3(cross);
- dot = dot_v3v3(d2, d3);
- len = len_v3(d2) * len_v3(d3);
-
if (LIKELY(area != 0.0f)) {
+ const float dot = dot_v3v3(d2, d3);
+ const float len = len_v3(d2) * len_v3(d3);
return (len - dot) / area;
}
else {
@@ -2342,18 +2483,16 @@ static float mean_value_half_tan_v3(const float v1[3], const float v2[3], const
}
static float mean_value_half_tan_v2(const float v1[2], const float v2[2], const float v3[2])
{
- float d2[2], d3[2], area, dot, len;
+ float d2[2], d3[2], area;
sub_v2_v2v2(d2, v2, v1);
sub_v2_v2v2(d3, v3, v1);
/* different from the 3d version but still correct */
area = cross_v2v2(d2, d3);
-
- dot = dot_v2v2(d2, d3);
- len = len_v2(d2) * len_v2(d3);
-
if (LIKELY(area != 0.0f)) {
+ const float dot = dot_v2v2(d2, d3);
+ const float len = len_v2(d2) * len_v2(d3);
return (len - dot) / area;
}
else {
@@ -3616,4 +3755,3 @@ int is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], c
/* linetests, the 2 diagonals have to instersect to be convex */
return (isect_line_line_v2(v1, v3, v2, v4) > 0);
}
-
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index f32b477787b..ac5c0033067 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -185,4 +185,9 @@ MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
}
}
+MINLINE float plane_point_side_v3(const float plane[4], const float co[3])
+{
+ return dot_v3v3(co, plane) + plane[3];
+}
+
#endif /* __MATH_GEOM_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c
index 81d931cfba6..d1acd45e40e 100644
--- a/source/blender/blenlib/intern/math_interp.c
+++ b/source/blender/blenlib/intern/math_interp.c
@@ -26,6 +26,10 @@
*
*/
+/** \file blender/blenlib/intern/math_interp.c
+ * \ingroup bli
+ */
+
#include <math.h>
#include "BLI_math.h"
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 611b3298c38..d24200fc0b7 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -322,6 +322,24 @@ void mul_serie_m4(float answ[4][4], float m1[4][4],
}
}
+void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
+{
+ float temp[3], warped[3];
+
+ copy_v2_v2(temp, v);
+ temp[2] = 1.0f;
+
+ mul_v3_m3v3(warped, m, temp);
+
+ r[0] = warped[0] / warped[2];
+ r[1] = warped[1] / warped[2];
+}
+
+void mul_m3_v2(float m[3][3], float r[2])
+{
+ mul_v2_m3v2(r, m, r);
+}
+
void mul_m4_v3(float mat[4][4], float vec[3])
{
float x, y;
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 9fd8c479d6e..6bac102e1b1 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -62,7 +62,7 @@ void copy_qt_qt(float q1[4], const float q2[4])
q1[3] = q2[3];
}
-int is_zero_qt(float *q)
+bool is_zero_qt(const float q[4])
{
return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0);
}
@@ -817,7 +817,8 @@ void mat4_to_axis_angle(float axis[3], float *angle, float mat[4][4])
quat_to_axis_angle(axis, angle, q);
}
-void single_axis_angle_to_mat3(float mat[3][3], const char axis, const float angle)
+/* rotation matrix from a single axis */
+void axis_angle_to_mat3_single(float mat[3][3], const char axis, const float angle)
{
const float angle_cos = cosf(angle);
const float angle_sin = sinf(angle);
@@ -862,6 +863,18 @@ void single_axis_angle_to_mat3(float mat[3][3], const char axis, const float ang
}
}
+void angle_to_mat2(float mat[2][2], const float angle)
+{
+ const float angle_cos = cosf(angle);
+ const float angle_sin = sinf(angle);
+
+ /* 2D rotation matrix */
+ mat[0][0] = angle_cos;
+ mat[0][1] = angle_sin;
+ mat[1][0] = -angle_sin;
+ mat[1][1] = angle_cos;
+}
+
/******************************** XYZ Eulers *********************************/
/* XYZ order */
@@ -993,7 +1006,7 @@ void quat_to_eul(float *eul, const float quat[4])
}
/* XYZ order */
-void eul_to_quat(float *quat, const float eul[3])
+void eul_to_quat(float quat[4], const float eul[3])
{
float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
@@ -1018,7 +1031,7 @@ void eul_to_quat(float *quat, const float eul[3])
}
/* XYZ order */
-void rotate_eul(float *beul, const char axis, const float ang)
+void rotate_eul(float beul[3], const char axis, const float ang)
{
float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
@@ -1229,7 +1242,7 @@ void eulO_to_mat3(float M[3][3], const float e[3], const short order)
}
/* returns two euler calculation methods, so we can pick the best */
-static void mat3_to_eulo2(float M[3][3], float *e1, float *e2, const short order)
+static void mat3_to_eulo2(float M[3][3], float e1[3], float e2[3], const short order)
{
const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order);
short i = R->axis[0], j = R->axis[1], k = R->axis[2];
@@ -1478,9 +1491,10 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
dq->trans[3] = 0.5f * ( t[0] * q[2] - t[1] * q[1] + t[2] * q[0]);
}
-void dquat_to_mat4(float mat[4][4], DualQuat *dq)
+void dquat_to_mat4(float mat[4][4], const DualQuat *dq)
{
- float len, *t, q0[4];
+ float len, q0[4];
+ const float *t;
/* regular quaternion */
copy_qt_qt(q0, dq->quat);
@@ -1502,7 +1516,7 @@ void dquat_to_mat4(float mat[4][4], DualQuat *dq)
/* note: this does not handle scaling */
}
-void add_weighted_dq_dq(DualQuat *dqsum, DualQuat *dq, float weight)
+void add_weighted_dq_dq(DualQuat *dqsum, const DualQuat *dq, float weight)
{
int flipped = 0;
@@ -1530,7 +1544,7 @@ void add_weighted_dq_dq(DualQuat *dqsum, DualQuat *dq, float weight)
if (flipped) /* we don't want negative weights for scaling */
weight = -weight;
- copy_m4_m4(wmat, dq->scale);
+ copy_m4_m4(wmat, (float(*)[4])dq->scale);
mul_m4_fl(wmat, weight);
add_m4_m4m4(dqsum->scale, dqsum->scale, wmat);
dqsum->scale_weight += weight;
@@ -1609,7 +1623,7 @@ void mul_v3m3_dq(float co[3], float mat[3][3], DualQuat *dq)
}
}
-void copy_dq_dq(DualQuat *dq1, DualQuat *dq2)
+void copy_dq_dq(DualQuat *dq1, const DualQuat *dq2)
{
memcpy(dq1, dq2, sizeof(DualQuat));
}
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 8e5040d983b..ce5d9657c7f 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -771,61 +771,76 @@ MINLINE void normal_float_to_short_v3(short out[3], const float in[3])
/********************************* Comparison ********************************/
-MINLINE int is_zero_v2(const float v[2])
+MINLINE bool is_zero_v2(const float v[2])
{
return (v[0] == 0 && v[1] == 0);
}
-MINLINE int is_zero_v3(const float v[3])
+MINLINE bool is_zero_v3(const float v[3])
{
return (v[0] == 0 && v[1] == 0 && v[2] == 0);
}
-MINLINE int is_zero_v4(const float v[4])
+MINLINE bool is_zero_v4(const float v[4])
{
return (v[0] == 0 && v[1] == 0 && v[2] == 0 && v[3] == 0);
}
-MINLINE int is_one_v3(const float v[3])
+MINLINE bool is_finite_v2(const float v[2])
+{
+ return (finite(v[0]) && finite(v[1]));
+}
+
+MINLINE bool is_finite_v3(const float v[3])
+{
+ return (finite(v[0]) && finite(v[1]) && finite(v[2]));
+}
+
+MINLINE bool is_finite_v4(const float v[4])
+{
+ return (finite(v[0]) && finite(v[1]) && finite(v[2]) && finite(v[3]));
+}
+
+MINLINE bool is_one_v3(const float v[3])
{
return (v[0] == 1 && v[1] == 1 && v[2] == 1);
}
-MINLINE int equals_v2v2(const float v1[2], const float v2[2])
+MINLINE bool equals_v2v2(const float v1[2], const float v2[2])
{
return ((v1[0] == v2[0]) && (v1[1] == v2[1]));
}
-MINLINE int equals_v3v3(const float v1[3], const float v2[3])
+MINLINE bool equals_v3v3(const float v1[3], const float v2[3])
{
return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]));
}
-MINLINE int equals_v4v4(const float v1[4], const float v2[4])
+MINLINE bool equals_v4v4(const float v1[4], const float v2[4])
{
return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3]));
}
-MINLINE int compare_v2v2(const float v1[2], const float v2[2], const float limit)
+MINLINE bool compare_v2v2(const float v1[2], const float v2[2], const float limit)
{
if (fabsf(v1[0] - v2[0]) < limit)
if (fabsf(v1[1] - v2[1]) < limit)
- return 1;
+ return true;
- return 0;
+ return false;
}
-MINLINE int compare_v3v3(const float v1[3], const float v2[3], const float limit)
+MINLINE bool compare_v3v3(const float v1[3], const float v2[3], const float limit)
{
if (fabsf(v1[0] - v2[0]) < limit)
if (fabsf(v1[1] - v2[1]) < limit)
if (fabsf(v1[2] - v2[2]) < limit)
- return 1;
+ return true;
- return 0;
+ return false;
}
-MINLINE int compare_len_v3v3(const float v1[3], const float v2[3], const float limit)
+MINLINE bool compare_len_v3v3(const float v1[3], const float v2[3], const float limit)
{
float x, y, z;
@@ -836,15 +851,15 @@ MINLINE int compare_len_v3v3(const float v1[3], const float v2[3], const float l
return ((x * x + y * y + z * z) < (limit * limit));
}
-MINLINE int compare_v4v4(const float v1[4], const float v2[4], const float limit)
+MINLINE bool compare_v4v4(const float v1[4], const float v2[4], const float limit)
{
if (fabsf(v1[0] - v2[0]) < limit)
if (fabsf(v1[1] - v2[1]) < limit)
if (fabsf(v1[2] - v2[2]) < limit)
if (fabsf(v1[3] - v2[3]) < limit)
- return 1;
+ return true;
- return 0;
+ return false;
}
MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2])
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 2c06a812c8a..d323098827b 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -46,20 +46,12 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
+#include "BLI_fnmatch.h"
#include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */
#include "GHOST_Path-api.h"
-#if defined WIN32 && !defined _LIBC || defined __sun
-# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
-#else
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-# endif
-# include <fnmatch.h>
-#endif
-
#ifdef WIN32
# include "utf_winfunc.h"
# include "utfconv.h"
@@ -1332,15 +1324,20 @@ const char *BLI_get_folder_version(const int id, const int ver, const bool do_ch
#endif
/**
- * Sets the specified environment variable to the specified value.
+ * Sets the specified environment variable to the specified value,
+ * and clears it if val == NULL.
*/
void BLI_setenv(const char *env, const char *val)
{
/* free windows */
#if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
- char *envstr = MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
+ char *envstr;
+
+ if (val)
+ envstr = BLI_sprintfN("%s=%s", env, val);
+ else
+ envstr = BLI_sprintfN("%s=", env);
- sprintf(envstr, "%s=%s", env, val);
putenv(envstr);
MEM_freeN(envstr);
@@ -1351,7 +1348,10 @@ void BLI_setenv(const char *env, const char *val)
#else
/* linux/osx/bsd */
- setenv(env, val, 1);
+ if (val)
+ setenv(env, val, 1);
+ else
+ unsetenv(env);
#endif
}
@@ -1649,6 +1649,16 @@ bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
return true;
}
+bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename)
+{
+ char *c = (char *)BLI_last_slash(filepath);
+ if (!c || ((c - filepath) < maxlen - (strlen(filename) + 1))) {
+ strcpy(c ? &c[1] : filepath, filename);
+ return true;
+ }
+ return false;
+}
+
/* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
* - wont change 'string'
* - wont create any directories
@@ -1693,7 +1703,7 @@ void BLI_split_file_part(const char *string, char *file, const size_t filelen)
/**
* Append a filename to a dir, ensuring slash separates.
*/
-void BLI_path_append(char *dst, const size_t maxlen, const char *file)
+void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file)
{
size_t dirlen = BLI_strnlen(dst, maxlen);
@@ -1714,7 +1724,7 @@ void BLI_path_append(char *dst, const size_t maxlen, const char *file)
* Simple appending of filename to dir, does not check for valid path!
* Puts result into *dst, which may be same area as *dir.
*/
-void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
+void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file)
{
size_t dirlen = BLI_strnlen(dir, maxlen);
diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c
index b06534d282a..8c831bdada0 100644
--- a/source/blender/blenlib/intern/quadric.c
+++ b/source/blender/blenlib/intern/quadric.c
@@ -35,6 +35,8 @@
//#include <string.h>
#include "BLI_math.h"
+#include "BLI_strict_flags.h"
+
#include "BLI_quadric.h" /* own include */
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 743d910e418..c5b58e5a61b 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -175,20 +175,10 @@ float BLI_frand(void)
float BLI_hash_frand(unsigned int seed)
{
- r_uint64 X;
-
- seed = seed + hash[seed & 255];
- X = (((r_uint64) seed) << 16) | LOWSEED;
- seed = (int)(((MULTIPLIER * X + ADDEND) & MASK) >> 17);
-
- seed = seed + hash[seed & 255];
- X = (((r_uint64) seed) << 16) | LOWSEED;
- X = (int)(((MULTIPLIER * X + ADDEND) & MASK) >> 17);
-
- seed = seed + hash[seed & 255];
- X = (((r_uint64) seed) << 16) | LOWSEED;
+ RNG rng;
- return (int)(((MULTIPLIER * X + ADDEND) & MASK) >> 17);
+ BLI_rng_srandom(&rng, seed);
+ return BLI_rng_get_float(&rng);
}
void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed)
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index c7163874dca..a292c2275c9 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -40,49 +40,17 @@
#include "BLI_callbacks.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_scanfill.h"
+#include "BLI_memarena.h"
#include "BLI_utildefines.h"
+#include "BLI_strict_flags.h"
-/* callbacks for errors and interrupts and some goo */
-static void (*BLI_localErrorCallBack)(const char *) = NULL;
-
-/**
- * Set a function taking a (char *) as argument to flag errors. If the
- * callback is not set, the error is discarded.
- * \param f The function to use as callback
- * \attention used in creator.c
- */
-void BLI_setErrorCallBack(void (*f)(const char *))
-{
- BLI_localErrorCallBack = f;
-}
-
-/* just flush the error to /dev/null if the error handler is missing */
-void callLocalErrorCallBack(const char *msg)
-{
- if (BLI_localErrorCallBack) {
- BLI_localErrorCallBack(msg);
- }
-}
-
-#if 0
-/* ignore if the interrupt wasn't set */
-static int callLocalInterruptCallBack(void)
-{
- if (BLI_localInterruptCallBack) {
- return BLI_localInterruptCallBack();
- }
- else {
- return 0;
- }
-}
-#endif
+#include "BLI_scanfill.h" /* own include */
/* local types */
typedef struct PolyFill {
- int edges, verts;
+ unsigned int edges, verts;
float min_xy[2], max_xy[2];
- short f, nr;
+ unsigned short f, nr;
} PolyFill;
typedef struct ScanFillVertLink {
@@ -132,99 +100,45 @@ static int vergpoly(const void *a1, const void *a2)
return 0;
}
-/* ************* MEMORY MANAGEMENT ************* */
-
-/* memory management */
-struct mem_elements {
- struct mem_elements *next, *prev;
- char *data;
-};
+/* **** FILL ROUTINES *************************** */
-static void *mem_element_new(ScanFillContext *sf_ctx, int size)
+ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
{
- BLI_assert(!(size > 10000 || size == 0)); /* this is invalid use! */
-
- size = (size + 3) & ~3; /* allocate in units of 4 */
+ ScanFillVert *sf_v;
- if (sf_ctx->melem__cur && (size + sf_ctx->melem__offs < MEM_ELEM_BLOCKSIZE)) {
- void *adr = (void *) (sf_ctx->melem__cur->data + sf_ctx->melem__offs);
- sf_ctx->melem__offs += size;
- return adr;
- }
- else {
- sf_ctx->melem__cur = MEM_callocN(sizeof(struct mem_elements), "newmem");
- sf_ctx->melem__cur->data = MEM_callocN(MEM_ELEM_BLOCKSIZE, "newmem");
- BLI_addtail(&sf_ctx->melem__lb, sf_ctx->melem__cur);
-
- sf_ctx->melem__offs = size;
- return sf_ctx->melem__cur->data;
- }
-}
-static void mem_element_reset(ScanFillContext *sf_ctx, int keep_first)
-{
- struct mem_elements *first;
-
- if ((first = sf_ctx->melem__lb.first)) { /* can be false if first fill fails */
- if (keep_first) {
- BLI_remlink(&sf_ctx->melem__lb, first);
- }
-
- sf_ctx->melem__cur = sf_ctx->melem__lb.first;
- while (sf_ctx->melem__cur) {
- MEM_freeN(sf_ctx->melem__cur->data);
- sf_ctx->melem__cur = sf_ctx->melem__cur->next;
- }
- BLI_freelistN(&sf_ctx->melem__lb);
+ sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert));
- /*reset the block we're keeping*/
- if (keep_first) {
- BLI_addtail(&sf_ctx->melem__lb, first);
- memset(first->data, 0, MEM_ELEM_BLOCKSIZE);
- }
- else {
- first = NULL;
-
- }
- }
-
- sf_ctx->melem__cur = first;
- sf_ctx->melem__offs = 0;
-}
-
-void BLI_scanfill_end(ScanFillContext *sf_ctx)
-{
- mem_element_reset(sf_ctx, FALSE);
-
- sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL;
- sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL;
- sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL;
-}
+ BLI_addtail(&sf_ctx->fillvertbase, sf_v);
-/* **** FILL ROUTINES *************************** */
+ sf_v->tmp.p = NULL;
+ copy_v3_v3(sf_v->co, vec);
-ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
-{
- ScanFillVert *eve;
-
- eve = mem_element_new(sf_ctx, sizeof(ScanFillVert));
- BLI_addtail(&sf_ctx->fillvertbase, eve);
-
- copy_v3_v3(eve->co, vec);
+ /* just zero out the rest */
+ zero_v2(sf_v->xy);
+ sf_v->keyindex = 0;
+ sf_v->poly_nr = 0;
+ sf_v->edge_tot = 0;
+ sf_v->f = 0;
- return eve;
+ return sf_v;
}
ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2)
{
- ScanFillEdge *newed;
+ ScanFillEdge *sf_ed;
- newed = mem_element_new(sf_ctx, sizeof(ScanFillEdge));
- BLI_addtail(&sf_ctx->filledgebase, newed);
+ sf_ed = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillEdge));
+ BLI_addtail(&sf_ctx->filledgebase, sf_ed);
- newed->v1 = v1;
- newed->v2 = v2;
+ sf_ed->v1 = v1;
+ sf_ed->v2 = v2;
- return newed;
+ /* just zero out the rest */
+ sf_ed->poly_nr = 0;
+ sf_ed->f = 0;
+ sf_ed->tmp.c = 0;
+
+ return sf_ed;
}
static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2, ScanFillVert *v3)
@@ -232,7 +146,7 @@ static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert
/* does not make edges */
ScanFillFace *sf_tri;
- sf_tri = mem_element_new(sf_ctx, sizeof(ScanFillFace));
+ sf_tri = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillFace));
BLI_addtail(&sf_ctx->fillfacebase, sf_tri);
sf_tri->v1 = v1;
@@ -240,7 +154,7 @@ static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert
sf_tri->v3 = v3;
}
-static int boundisect(PolyFill *pf2, PolyFill *pf1)
+static bool boundisect(PolyFill *pf2, PolyFill *pf1)
{
/* has pf2 been touched (intersected) by pf1 ? with bounding box */
/* test first if polys exist */
@@ -287,7 +201,7 @@ static void mergepolysSimp(ScanFillContext *sf_ctx, PolyFill *pf1, PolyFill *pf2
pf1->f = (pf1->f | pf2->f);
}
-static short testedgeside(const float v1[2], const float v2[2], const float v3[2])
+static bool testedgeside(const float v1[2], const float v2[2], const float v3[2])
/* is v3 to the right of v1-v2 ? With exception: v3 == v1 || v3 == v2 */
{
float inp;
@@ -298,14 +212,14 @@ static short testedgeside(const float v1[2], const float v2[2], const float v3[2
if (inp < 0.0f) {
return 0;
}
- else if (inp == 0) {
+ else if (inp == 0.0f) {
if (v1[0] == v3[0] && v1[1] == v3[1]) return 0;
if (v2[0] == v3[0] && v2[1] == v3[1]) return 0;
}
return 1;
}
-static short addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
+static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
{
/* find first edge to the right of eed, and insert eed before that */
ScanFillEdge *ed;
@@ -354,7 +268,7 @@ static short addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
}
-static ScanFillVertLink *addedgetoscanlist(ScanFillContext *sf_ctx, ScanFillEdge *eed, int len)
+static ScanFillVertLink *addedgetoscanlist(ScanFillContext *sf_ctx, ScanFillEdge *eed, unsigned int len)
{
/* inserts edge at correct location in ScanFillVertLink list */
/* returns sc when edge already exists */
@@ -379,13 +293,17 @@ static ScanFillVertLink *addedgetoscanlist(ScanFillContext *sf_ctx, ScanFillEdge
sc = (ScanFillVertLink *)bsearch(&scsearch, sf_ctx->_scdata, len,
sizeof(ScanFillVertLink), vergscdata);
- if (sc == NULL) printf("Error in search edge: %p\n", (void *)eed);
- else if (addedgetoscanvert(sc, eed) == 0) return sc;
+ if (UNLIKELY(sc == NULL)) {
+ printf("Error in search edge: %p\n", (void *)eed);
+ }
+ else if (addedgetoscanvert(sc, eed) == false) {
+ return sc;
+ }
return NULL;
}
-static short boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve)
+static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve)
/* is eve inside boundbox eed */
{
float minx, maxx, miny, maxy;
@@ -476,7 +394,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
}
}
-static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, short nr)
+static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, unsigned short nr)
{
/* everything is in templist, write only poly nr to fillist */
ScanFillVert *eve, *nextve;
@@ -505,15 +423,14 @@ static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *tempe
}
}
-static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
+static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
{
ScanFillVertLink *sc = NULL, *sc1;
ScanFillVert *eve, *v1, *v2, *v3;
ScanFillEdge *eed, *nexted, *ed1, *ed2, *ed3;
- int a, b, verts, maxface, totface;
- short nr, twoconnected = 0;
-
- nr = pf->nr;
+ unsigned int a, b, verts, maxface, totface;
+ const unsigned short nr = pf->nr;
+ bool twoconnected = false;
/* PRINTS */
#if 0
@@ -629,7 +546,8 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
/* STEP 2: FILL LOOP */
- if (pf->f == 0) twoconnected = 1;
+ if (pf->f == 0)
+ twoconnected = true;
/* (temporal) security: never much more faces than vertices */
totface = 0;
@@ -826,14 +744,36 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
void BLI_scanfill_begin(ScanFillContext *sf_ctx)
{
memset(sf_ctx, 0, sizeof(*sf_ctx));
+ sf_ctx->arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
}
-int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag)
+void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, MemArena *arena)
{
- return BLI_scanfill_calc_ex(sf_ctx, flag, NULL);
+ memset(sf_ctx, 0, sizeof(*sf_ctx));
+ sf_ctx->arena = arena;
}
-int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3])
+void BLI_scanfill_end(ScanFillContext *sf_ctx)
+{
+ BLI_memarena_free(sf_ctx->arena);
+ sf_ctx->arena = NULL;
+
+ sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL;
+ sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL;
+ sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL;
+}
+
+void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, MemArena *arena)
+{
+ BLI_memarena_clear(arena);
+ BLI_assert(sf_ctx->arena == arena);
+
+ sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL;
+ sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL;
+ sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL;
+}
+
+unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3])
{
/*
* - fill works with its own lists, so create that first (no faces!)
@@ -845,34 +785,36 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
*/
ListBase tempve, temped;
ScanFillVert *eve;
- ScanFillEdge *eed, *nexted;
+ ScanFillEdge *eed, *eed_next;
PolyFill *pflist, *pf;
float *min_xy_p, *max_xy_p;
- short a, c, poly = 0, ok = 0, toggle = 0;
- int totfaces = 0; /* total faces added */
+ unsigned int totverts = 0, toggle = 0;
+ unsigned int totfaces = 0; /* total faces added */
+ unsigned short a, c, poly = 0;
+ bool ok;
float mat_2d[3][3];
BLI_assert(!nor_proj || len_squared_v3(nor_proj) > FLT_EPSILON);
- /* reset variables */
eve = sf_ctx->fillvertbase.first;
- a = 0;
while (eve) {
- eve->f = 0;
- eve->poly_nr = 0;
- eve->edge_tot = 0;
+ /* these values used to be set,
+ * however they should always be zero'd so check instead */
+ BLI_assert(eve->f == 0);
+ BLI_assert(eve->poly_nr == 0);
+ BLI_assert(eve->edge_tot == 0);
+ totverts++;
eve = eve->next;
- a += 1;
}
if (flag & BLI_SCANFILL_CALC_QUADTRI_FASTPATH) {
- if (a == 3) {
+ if (totverts == 3) {
eve = sf_ctx->fillvertbase.first;
addfillface(sf_ctx, eve, eve->next, eve->next->next);
return 1;
}
- else if (a == 4) {
+ else if (totverts == 4) {
float vec1[3], vec2[3];
eve = sf_ctx->fillvertbase.first;
@@ -897,23 +839,24 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
/* including resetting of flags */
eed = sf_ctx->filledgebase.first;
while (eed) {
- eed->poly_nr = 0;
+ BLI_assert(eed->poly_nr == 0);
eed->v1->f = SF_VERT_AVAILABLE;
eed->v2->f = SF_VERT_AVAILABLE;
eed = eed->next;
}
+ ok = false;
eve = sf_ctx->fillvertbase.first;
while (eve) {
if (eve->f & SF_VERT_AVAILABLE) {
- ok = 1;
+ ok = true;
break;
}
eve = eve->next;
}
- if (ok == 0) {
+ if (UNLIKELY(ok == false)) {
return 0;
}
else {
@@ -959,35 +902,33 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
if (eve->poly_nr == 0) {
poly++;
/* now a sort of select connected */
- ok = 1;
+ ok = true;
eve->poly_nr = poly;
while (ok) {
- ok = 0;
- toggle++;
- if (toggle & 1) eed = sf_ctx->filledgebase.first;
- else eed = sf_ctx->filledgebase.last;
+ ok = false;
+ toggle++;
+ eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last;
while (eed) {
if (eed->v1->poly_nr == 0 && eed->v2->poly_nr == poly) {
eed->v1->poly_nr = poly;
eed->poly_nr = poly;
- ok = 1;
+ ok = true;
}
else if (eed->v2->poly_nr == 0 && eed->v1->poly_nr == poly) {
eed->v2->poly_nr = poly;
eed->poly_nr = poly;
- ok = 1;
+ ok = true;
}
else if (eed->poly_nr == 0) {
if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) {
eed->poly_nr = poly;
- ok = 1;
+ ok = true;
}
}
- if (toggle & 1) eed = eed->next;
- else eed = eed->prev;
+ eed = (toggle & 1) ? eed->next : eed->prev;
}
}
}
@@ -1020,35 +961,36 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
}
if (eed) {
/* otherwise it's impossible to be sure you can clear vertices */
- callLocalErrorCallBack("No vertices with 250 edges allowed!");
+#ifdef DEBUG
+ printf("No vertices with 250 edges allowed!\n");
+#endif
return 0;
}
/* does it only for vertices with (->h == 1) */
testvertexnearedge(sf_ctx);
- ok = 1;
+ ok = true;
while (ok) {
- ok = 0;
+ ok = false;
+
toggle++;
- if (toggle & 1) eed = sf_ctx->filledgebase.first;
- else eed = sf_ctx->filledgebase.last;
+ eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last;
while (eed) {
- if (toggle & 1) nexted = eed->next;
- else nexted = eed->prev;
+ eed_next = (toggle & 1) ? eed->next : eed->prev;
if (eed->v1->edge_tot == 1) {
eed->v2->edge_tot--;
BLI_remlink(&sf_ctx->fillvertbase, eed->v1);
BLI_remlink(&sf_ctx->filledgebase, eed);
- ok = 1;
+ ok = true;
}
else if (eed->v2->edge_tot == 1) {
eed->v1->edge_tot--;
BLI_remlink(&sf_ctx->fillvertbase, eed->v2);
BLI_remlink(&sf_ctx->filledgebase, eed);
- ok = 1;
+ ok = true;
}
- eed = nexted;
+ eed = eed_next;
}
}
if (sf_ctx->filledgebase.first == NULL) {
@@ -1069,12 +1011,12 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
/* STEP 3: MAKE POLYFILL STRUCT */
- pflist = (PolyFill *)MEM_callocN(poly * sizeof(PolyFill), "edgefill");
+ pflist = (PolyFill *)MEM_callocN((size_t)poly * sizeof(PolyFill), "edgefill");
pf = pflist;
for (a = 1; a <= poly; a++) {
pf->nr = a;
- pf->min_xy[0] = pf->min_xy[1] = 1.0e20;
- pf->max_xy[0] = pf->max_xy[1] = -1.0e20;
+ pf->min_xy[0] = pf->min_xy[1] = 1.0e20f;
+ pf->max_xy[0] = pf->max_xy[1] = -1.0e20f;
pf++;
}
eed = sf_ctx->filledgebase.first;
@@ -1104,10 +1046,10 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
* WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */
if (poly > 1) {
- short *polycache, *pc;
+ unsigned short *polycache, *pc;
/* so, sort first */
- qsort(pflist, poly, sizeof(PolyFill), vergpoly);
+ qsort(pflist, (size_t)poly, sizeof(PolyFill), vergpoly);
#if 0
pf = pflist;
@@ -1118,10 +1060,10 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
}
#endif
- polycache = pc = MEM_callocN(sizeof(short) * poly, "polycache");
+ polycache = pc = MEM_callocN(sizeof(short) * (size_t)poly, "polycache");
pf = pflist;
for (a = 0; a < poly; a++, pf++) {
- for (c = a + 1; c < poly; c++) {
+ for (c = (unsigned short)(a + 1); c < poly; c++) {
/* if 'a' inside 'c': join (bbox too)
* Careful: 'a' can also be inside another poly.
@@ -1177,3 +1119,8 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
return totfaces;
}
+
+unsigned int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag)
+{
+ return BLI_scanfill_calc_ex(sf_ctx, flag, NULL);
+}
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index d255b4a9af6..19eb88f9e15 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -25,12 +25,17 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenlib/intern/smallhash.c
+ * \ingroup bli
+ */
+
#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_smallhash.h"
+#include "BLI_strict_flags.h"
/* SMHASH_CELL_UNUSED means this cell is inside a key series,
* while SMHASH_CELL_FREE means this cell terminates a key series.
@@ -43,18 +48,10 @@
#define SMHASH_CELL_UNUSED ((void *)0x7FFFFFFF)
#define SMHASH_CELL_FREE ((void *)0x7FFFFFFD)
-#ifdef __GNUC__
-# pragma GCC diagnostic error "-Wsign-conversion"
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
-# pragma GCC diagnostic error "-Wsign-compare"
-# pragma GCC diagnostic error "-Wconversion"
-# endif
-#endif
-
/* typically this re-assigns 'h' */
#define SMHASH_NEXT(h, hoff) ( \
- CHECK_TYPE_INLINE(&(h), unsigned int), \
- CHECK_TYPE_INLINE(&(hoff), unsigned int), \
+ CHECK_TYPE_INLINE(&(h), unsigned int *), \
+ CHECK_TYPE_INLINE(&(hoff), unsigned int *), \
((h) + (((hoff) = ((hoff) * 2) + 1), (hoff))) \
)
diff --git a/source/blender/blenlib/intern/sort.c b/source/blender/blenlib/intern/sort.c
new file mode 100644
index 00000000000..44110564948
--- /dev/null
+++ b/source/blender/blenlib/intern/sort.c
@@ -0,0 +1,173 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Benoit Bolsee,
+ * Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/sort.c
+ * \ingroup bli
+ */
+
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+
+#include "BLI_sort.h"
+
+/* **** qsort based on FreeBSD source (libkern\qsort.c) **** */
+BLI_INLINE char *med3(char *, char *, char *, BLI_sort_cmp_t, void *);
+BLI_INLINE void swapfunc(char *, char *, int, int);
+
+#define min(a, b) (a) < (b) ? a : b
+#define swapcode(TYPE, parmi, parmj, n) \
+{ \
+ long i = (n) / sizeof(TYPE); \
+ TYPE *pi = (TYPE *) (parmi); \
+ TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+BLI_INLINE void swapfunc(char *a, char *b, int n, int swaptype)
+{
+ if (swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b);\
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+#define CMP(t, x, y) (cmp((t), (x), (y)))
+
+BLI_INLINE char *med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk)
+{
+ return CMP(thunk, a, b) < 0 ?
+ (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
+ :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+}
+
+/**
+ * Quick sort reentrant.
+ *
+ * \note Follows BSD arg order (incompatible with glibc).
+ */
+void BLI_qsort_r(void *a, size_t n, size_t es, void *thunk, BLI_sort_cmp_t cmp)
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype, swap_cnt;
+
+loop:
+ SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) {
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ {
+ swap(pl, pl - es);
+ }
+ }
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = (char *)a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+ pm = med3(pm - d, pm, pm + d, cmp, thunk);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
+ }
+ pm = med3(pl, pm, pn, cmp, thunk);
+ }
+ swap((char *)a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) {
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ {
+ swap(pl, pl - es);
+ }
+ }
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap((char *)a, pb - r, r);
+ r = min(pd - pc, pn - pd - es);
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > es)
+ BLI_qsort_r(a, r / es, es, thunk, cmp);
+ if ((r = pd - pc) > es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+}
diff --git a/source/blender/blenlib/intern/sort_utils.c b/source/blender/blenlib/intern/sort_utils.c
new file mode 100644
index 00000000000..c75e8e7455f
--- /dev/null
+++ b/source/blender/blenlib/intern/sort_utils.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.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/sort_utils.c
+ * \ingroup bli
+ *
+ * Utility functions for sorting common types.
+ */
+
+#include "BLI_sort_utils.h" /* own include */
+
+struct SortAnyByFloat {
+ float sort_value;
+};
+
+struct SortAnyByInt {
+ int sort_value;
+};
+
+int BLI_sortutil_cmp_float(const void *a_, const void *b_)
+{
+ const struct SortAnyByFloat *a = a_;
+ const struct SortAnyByFloat *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_float_reverse(const void *a_, const void *b_)
+{
+ const struct SortAnyByFloat *a = a_;
+ const struct SortAnyByFloat *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_int(const void *a_, const void *b_)
+{
+ const struct SortAnyByInt *a = a_;
+ const struct SortAnyByInt *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_int_reverse(const void *a_, const void *b_)
+{
+ const struct SortAnyByInt *a = a_;
+ const struct SortAnyByInt *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 34c6e632131..e40527b1bb6 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -70,7 +70,6 @@
#ifdef WIN32
# include <io.h>
# include <direct.h>
-# include <limits.h> /* PATH_MAX */
# include "BLI_winstuff.h"
# include "utfconv.h"
#else
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index 2b6fb52c49c..c8b84d9310a 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -107,7 +107,7 @@ static void *thread_tls_data;
* BLI_end_threads(&lb);
*
************************************************ */
-static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER;
+static SpinLock _malloc_lock;
static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _image_draw_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -134,17 +134,24 @@ typedef struct ThreadSlot {
static void BLI_lock_malloc_thread(void)
{
- pthread_mutex_lock(&_malloc_lock);
+ BLI_spin_lock(&_malloc_lock);
}
static void BLI_unlock_malloc_thread(void)
{
- pthread_mutex_unlock(&_malloc_lock);
+ BLI_spin_unlock(&_malloc_lock);
}
void BLI_threadapi_init(void)
{
mainid = pthread_self();
+
+ BLI_spin_init(&_malloc_lock);
+}
+
+void BLI_threadapi_exit(void)
+{
+ BLI_spin_end(&_malloc_lock);
}
/* tot = 0 only initializes malloc mutex in a safe way (see sequence.c)
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 00ff5863e59..58d0cf6d264 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -265,7 +265,10 @@ void BLO_main_expander(void (*expand_doit_func)(void *, struct Main *, void *));
* \param mainvar the Main database to expand
*/
void BLO_expand_main(void *fdhandle, struct Main *mainvar);
-
+
+/* Update defaults in startup.blend, without having to save and embed it */
+void BLO_update_defaults_startup_blend(struct Main *mainvar);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 104c58b1c9e..f865962bac9 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -46,6 +46,7 @@ set(SRC
intern/runtime.c
intern/undofile.c
intern/versioning_250.c
+ intern/versioning_defaults.c
intern/versioning_legacy.c
intern/writefile.c
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index aec91dedf8f..9ae2858f526 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -222,7 +222,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
{
FileData *fd = (FileData *) bh;
- GHash *gathered = BLI_ghash_ptr_new("linkable_groups gh");
+ GSet *gathered = BLI_gset_ptr_new("linkable_groups gh");
LinkNode *names = NULL;
BHead *bhead;
@@ -234,15 +234,15 @@ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
if (BKE_idcode_is_linkable(bhead->code)) {
const char *str = BKE_idcode_to_name(bhead->code);
- if (!BLI_ghash_haskey(gathered, (void *)str)) {
+ if (!BLI_gset_haskey(gathered, (void *)str)) {
BLI_linklist_prepend(&names, strdup(str));
- BLI_ghash_insert(gathered, (void *)str, NULL);
+ BLI_gset_insert(gathered, (void *)str);
}
}
}
}
- BLI_ghash_free(gathered, NULL, NULL);
+ BLI_gset_free(gathered, NULL);
return names;
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1f8bbfbec88..077b476c408 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -151,6 +151,7 @@
#include "BKE_text.h" // for txt_extended_ascii_as_utf8
#include "BKE_texture.h"
#include "BKE_tracking.h"
+#include "BKE_treehash.h"
#include "BKE_sound.h"
#include "IMB_imbuf.h" // for proxy / timecode versioning stuff
@@ -249,11 +250,7 @@ static void convert_tface_mt(FileData *fd, Main *main);
* we could alternatively have a versions of a report function which forces printing - campbell
*/
-static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 3, 4)))
-#endif
-;
+static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4);
static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
{
char fixed_buf[1024]; /* should be long enough */
@@ -1779,6 +1776,27 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData
}
}
+#define IDP_DirectLinkGroup_OrFree(prop, switch_endian, fd) \
+ _IDP_DirectLinkGroup_OrFree(prop, switch_endian, fd, __func__)
+
+static void _IDP_DirectLinkGroup_OrFree(IDProperty **prop, int switch_endian, FileData *fd,
+ const char *caller_func_id)
+{
+ if (*prop) {
+ if ((*prop)->type == IDP_GROUP) {
+ IDP_DirectLinkGroup(*prop, switch_endian, fd);
+ }
+ else {
+ /* corrupt file! */
+ printf("%s: found non group data, freeing type %d!\n",
+ caller_func_id, (*prop)->type);
+ /* don't risk id, data's likely corrupt. */
+ // IDP_FreeProperty(*prop);
+ *prop = NULL;
+ }
+ }
+}
+
/* stub function */
static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endian), FileData *UNUSED(fd))
{
@@ -1791,9 +1809,8 @@ static void direct_link_id(FileData *fd, ID *id)
/*link direct data of ID properties*/
if (id->properties) {
id->properties = newdataadr(fd, id->properties);
- if (id->properties) { /* this case means the data was written incorrectly, it should not happen */
- IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
+ /* this case means the data was written incorrectly, it should not happen */
+ IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
@@ -2044,7 +2061,7 @@ static void direct_link_fmodifiers(FileData *fd, ListBase *list)
FMod_Python *data = (FMod_Python *)fcm->data;
data->prop = newdataadr(fd, data->prop);
- IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
break;
}
@@ -2599,8 +2616,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
{
sock->prop = newdataadr(fd, sock->prop);
- if (sock->prop)
- IDP_DirectLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
sock->link = newdataadr(fd, sock->link);
sock->typeinfo = NULL;
@@ -2638,8 +2654,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link_list(fd, &node->outputs);
node->prop = newdataadr(fd, node->prop);
- if (node->prop)
- IDP_DirectLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
link_list(fd, &node->internal_links);
for (link = node->internal_links.first; link; link = link->next) {
@@ -2797,8 +2812,7 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
link_list(fd, &data->targets);
data->prop = newdataadr(fd, data->prop);
- if (data->prop)
- IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
break;
}
case CONSTRAINT_TYPE_SPLINEIK:
@@ -2897,8 +2911,7 @@ static void direct_link_bones(FileData *fd, Bone *bone)
bone->parent = newdataadr(fd, bone->parent);
bone->prop = newdataadr(fd, bone->prop);
- if (bone->prop)
- IDP_DirectLinkProperty(bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
bone->flag &= ~BONE_DRAW_ACTIVE;
@@ -3123,7 +3136,6 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
mb->disp.first = mb->disp.last = NULL;
mb->editelems = NULL;
- mb->bb = NULL;
/* mb->edit_elems.first= mb->edit_elems.last= NULL;*/
mb->lastelem = NULL;
}
@@ -3399,11 +3411,9 @@ static void direct_link_curve(FileData *fd, Curve *cu)
if (cu->wordspace == 0.0f) cu->wordspace = 1.0f;
}
- cu->bev.first = cu->bev.last = NULL;
cu->disp.first = cu->disp.last = NULL;
cu->editnurb = NULL;
cu->lastsel = NULL;
- cu->path = NULL;
cu->editfont = NULL;
for (nu = cu->nurb.first; nu; nu = nu->next) {
@@ -4106,6 +4116,8 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count)
if (layer->flag & CD_FLAG_EXTERNAL)
layer->flag &= ~CD_FLAG_IN_MEMORY;
+
+ layer->flag &= ~CD_FLAG_NOFREE;
if (CustomData_verify_versions(data, i)) {
layer->data = newdataadr(fd, layer->data);
@@ -4152,7 +4164,7 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
direct_link_customdata(fd, &mesh->fdata, mesh->totface);
direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
-
+
mesh->bb = NULL;
mesh->edit_btmesh = NULL;
@@ -4161,6 +4173,12 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->totselect = 0;
}
+ if (mesh->mloopuv || mesh->mtpoly) {
+ /* for now we have to ensure texpoly and mloopuv layers are aligned
+ * in the future we may allow non-aligned layers */
+ BKE_mesh_cd_validate(mesh);
+ }
+
/* Multires data */
mesh->mr= newdataadr(fd, mesh->mr);
if (mesh->mr) {
@@ -4345,7 +4363,7 @@ static void lib_link_object(FileData *fd, Main *main)
/* Only expand so as not to loose any object materials that might be set. */
if (totcol_data && (*totcol_data > ob->totcol)) {
/* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */
- resize_object_material(ob, *totcol_data);
+ BKE_material_resize_object(ob, *totcol_data, false);
}
}
@@ -4373,12 +4391,8 @@ static void lib_link_object(FileData *fd, Main *main)
for (sens = ob->sensors.first; sens; sens = sens->next) {
for (a = 0; a < sens->totlinks; a++)
sens->links[a] = newglobadr(fd, sens->links[a]);
-
- if (sens->type == SENS_TOUCH) {
- bTouchSensor *ts = sens->data;
- ts->ma = newlibadr(fd, ob->id.lib, ts->ma);
- }
- else if (sens->type == SENS_MESSAGE) {
+
+ if (sens->type == SENS_MESSAGE) {
bMessageSensor *ms = sens->data;
ms->fromObject =
newlibadr(fd, ob->id.lib, ms->fromObject);
@@ -4536,8 +4550,7 @@ static void direct_link_pose(FileData *fd, bPose *pose)
direct_link_constraints(fd, &pchan->constraints);
pchan->prop = newdataadr(fd, pchan->prop);
- if (pchan->prop)
- IDP_DirectLinkProperty(pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
pchan->mpath = newdataadr(fd, pchan->mpath);
if (pchan->mpath)
@@ -4829,8 +4842,6 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
}
- ob->disp.first = ob->disp.last = NULL;
-
ob->adt = newdataadr(fd, ob->adt);
direct_link_animdata(fd, ob->adt);
@@ -5025,6 +5036,9 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->gpulamp.first= ob->gpulamp.last = NULL;
link_list(fd, &ob->pc_ids);
+ /* Runtime curve data */
+ ob->curve_cache = NULL;
+
/* in case this value changes in future, clamp else we get undefined behavior */
CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
@@ -5433,20 +5447,17 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
if (sce->r.ffcodecdata.properties) {
sce->r.ffcodecdata.properties = newdataadr(fd, sce->r.ffcodecdata.properties);
- if (sce->r.ffcodecdata.properties) {
- IDP_DirectLinkProperty(sce->r.ffcodecdata.properties,
- (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
+ IDP_DirectLinkGroup_OrFree(&sce->r.ffcodecdata.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
link_list(fd, &(sce->markers));
link_list(fd, &(sce->transform_spaces));
link_list(fd, &(sce->r.layers));
- for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
link_list(fd, &(srl->freestyleConfig.modules));
}
- for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
link_list(fd, &(srl->freestyleConfig.linesets));
}
@@ -5703,12 +5714,8 @@ static void lib_link_screen(FileData *fd, Main *main)
tselem->id = newlibadr(fd, NULL, tselem->id);
}
if (so->treehash) {
- /* update hash table, because it depends on ids too */
- BLI_ghash_clear(so->treehash, NULL, NULL);
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- BLI_ghash_insert(so->treehash, tselem, tselem);
- }
+ /* rebuild hash table, because it depends on ids too */
+ BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore);
}
}
}
@@ -6044,12 +6051,8 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
tselem->id = restore_pointer_by_name(newmain, tselem->id, 0);
}
if (so->treehash) {
- /* update hash table, because it depends on ids too */
- BLI_ghash_clear(so->treehash, NULL, NULL);
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- BLI_ghash_insert(so->treehash, tselem, tselem);
- }
+ /* rebuild hash table, because it depends on ids too */
+ BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore);
}
}
}
@@ -6136,6 +6139,9 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
ui_list->type = NULL;
+ ui_list->dyn_data = NULL;
+ ui_list->properties = newdataadr(fd, ui_list->properties);
+ IDP_DirectLinkGroup_OrFree(&ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
if (spacetype == SPACE_EMPTY) {
@@ -6324,7 +6330,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
else if (sl->spacetype == SPACE_OUTLINER) {
SpaceOops *soops = (SpaceOops *) sl;
- /* use newdataadr_no_us and do not free old memory avoidign double
+ /* use newdataadr_no_us and do not free old memory avoiding double
* frees and use of freed memory. this could happen because of a
* bug fixed in revision 58959 where the treestore memory address
* was not unique */
@@ -6687,6 +6693,28 @@ static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase)
}
}
+static void direct_link_moviePlaneTracks(FileData *fd, ListBase *plane_tracks_base)
+{
+ MovieTrackingPlaneTrack *plane_track;
+
+ link_list(fd, plane_tracks_base);
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ int i;
+
+ plane_track->point_tracks = newdataadr(fd, plane_track->point_tracks);
+
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ plane_track->point_tracks[i] = newdataadr(fd, plane_track->point_tracks[i]);
+ }
+
+ plane_track->markers = newdataadr(fd, plane_track->markers);
+ }
+}
+
static void direct_link_movieclip(FileData *fd, MovieClip *clip)
{
MovieTracking *tracking = &clip->tracking;
@@ -6701,9 +6729,11 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
else clip->tracking.camera.intrinsics = NULL;
direct_link_movieTracks(fd, &tracking->tracks);
+ direct_link_moviePlaneTracks(fd, &tracking->plane_tracks);
direct_link_movieReconstruction(fd, &tracking->reconstruction);
clip->tracking.act_track = newdataadr(fd, clip->tracking.act_track);
+ clip->tracking.act_plane_track = newdataadr(fd, clip->tracking.act_plane_track);
clip->anim = NULL;
clip->tracking_context = NULL;
@@ -6720,6 +6750,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
for (object = tracking->objects.first; object; object = object->next) {
direct_link_movieTracks(fd, &object->tracks);
+ direct_link_moviePlaneTracks(fd, &object->plane_tracks);
direct_link_movieReconstruction(fd, &object->reconstruction);
}
}
@@ -7008,16 +7039,16 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
linestyle->adt= newdataadr(fd, linestyle->adt);
direct_link_animdata(fd, linestyle->adt);
link_list(fd, &linestyle->color_modifiers);
- for(modifier = linestyle->color_modifiers.first; modifier; modifier = modifier->next)
+ for (modifier = linestyle->color_modifiers.first; modifier; modifier = modifier->next)
direct_link_linestyle_color_modifier(fd, modifier);
link_list(fd, &linestyle->alpha_modifiers);
- for(modifier = linestyle->alpha_modifiers.first; modifier; modifier = modifier->next)
+ for (modifier = linestyle->alpha_modifiers.first; modifier; modifier = modifier->next)
direct_link_linestyle_alpha_modifier(fd, modifier);
link_list(fd, &linestyle->thickness_modifiers);
- for(modifier = linestyle->thickness_modifiers.first; modifier; modifier = modifier->next)
+ for (modifier = linestyle->thickness_modifiers.first; modifier; modifier = modifier->next)
direct_link_linestyle_thickness_modifier(fd, modifier);
link_list(fd, &linestyle->geometry_modifiers);
- for(modifier = linestyle->geometry_modifiers.first; modifier; modifier = modifier->next)
+ for (modifier = linestyle->geometry_modifiers.first; modifier; modifier = modifier->next)
direct_link_linestyle_geometry_modifier(fd, modifier);
}
@@ -7054,7 +7085,9 @@ static const char *dataname(short id_code)
case ID_BR: return "Data from BR";
case ID_PA: return "Data from PA";
case ID_GD: return "Data from GD";
+ case ID_WM: return "Data from WM";
case ID_MC: return "Data from MC";
+ case ID_MSK: return "Data from MSK";
case ID_LS: return "Data from LS";
}
return "Data from Lib Block";
@@ -7123,7 +7156,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
if (id->flag & LIB_FAKEUSER) id->us= 1;
else id->us = 0;
id->icon_id = 0;
- id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA);
+ id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA|LIB_DOIT);
/* this case cannot be direct_linked: it's just the ID part */
if (bhead->code == ID_ID) {
@@ -9430,12 +9463,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
SceneRenderLayer *srl;
FreestyleLineStyle *linestyle;
- for(sce = main->scene.first; sce; sce = sce->id.next) {
+ for (sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->r.line_thickness_mode == 0) {
sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE;
sce->r.unit_line_thickness = 1.0f;
}
- for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
if (srl->freestyleConfig.mode == 0)
srl->freestyleConfig.mode = FREESTYLE_CONTROL_EDITOR_MODE;
if (srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE ||
@@ -9465,7 +9498,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
- for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+ for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
#if 1
/* disable the Misc panel for now */
if (linestyle->panel == LS_PANEL_MISC) {
@@ -9518,8 +9551,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
- if (MAIN_VERSION_OLDER(main, 267, 1))
- {
+ if (MAIN_VERSION_OLDER(main, 267, 1)) {
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next) {
@@ -9553,21 +9585,35 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
for (brush = main->brush.first; brush; brush = brush->id.next) {
brush->flag &= ~BRUSH_FIXED;
- if(brush->cursor_overlay_alpha < 2)
+ if (brush->cursor_overlay_alpha < 2)
brush->cursor_overlay_alpha = 33;
- if(brush->texture_overlay_alpha < 2)
+ if (brush->texture_overlay_alpha < 2)
brush->texture_overlay_alpha = 33;
- if(brush->mask_overlay_alpha <2)
+ if (brush->mask_overlay_alpha <2)
brush->mask_overlay_alpha = 33;
}
#undef BRUSH_FIXED
}
- {
+
+ if (!MAIN_VERSION_ATLEAST(main, 268, 4)) {
bScreen *sc;
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next) {
+ bConstraint *con;
+ for (con = ob->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
+ bShrinkwrapConstraint *data = (bShrinkwrapConstraint *)con->data;
+ if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) data->projAxis = OB_POSX;
+ else if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) data->projAxis = OB_POSY;
+ else data->projAxis = OB_POSZ;
+ data->projAxisSpace = CONSTRAINT_SPACE_LOCAL;
+ }
+ }
+ }
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
ModifierData *md;
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Smoke) {
@@ -9600,12 +9646,88 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ bSensor *sens;
+ bTouchSensor *ts;
+ bCollisionSensor *cs;
+ Material *ma;
+
+ for (sens = ob->sensors.first; sens; sens = sens->next) {
+ if (sens->type == SENS_TOUCH) {
+ ts = sens->data;
+ cs = MEM_callocN(sizeof(bCollisionSensor), "touch -> collision sensor do_version");
+
+ if (ts->ma) {
+ ma = blo_do_versions_newlibadr(fd, ob->id.lib, ts->ma);
+ BLI_strncpy(cs->materialName, ma->id.name+2, sizeof(cs->materialName));
+ }
+
+ cs->mode = SENS_COLLISION_MATERIAL;
+
+ MEM_freeN(ts);
+
+ sens->data = cs;
+ sens->type = sens->otype = SENS_COLLISION;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 268, 5)) {
+ bScreen *sc;
+ ScrArea *sa;
+
+ /* add missing (+) expander in node editor */
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ARegion *ar, *arnew;
+
+ if (sa->spacetype == SPACE_NODE) {
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
+
+ if (ar)
+ continue;
+
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+
+ /* is error! */
+ if (ar == NULL)
+ continue;
+
+ arnew = MEM_callocN(sizeof(ARegion), "node tools");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_TOOLS;
+ arnew->alignment = RGN_ALIGN_LEFT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 269, 1)) {
+ /* Removal of Cycles SSS Compatible falloff */
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_SUBSURFACE_SCATTERING) {
+ if (node->custom1 == SHD_SUBSURFACE_COMPATIBLE) {
+ node->custom1 = SHD_SUBSURFACE_CUBIC;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
- /* don't forget to set version number in blender.c! */
+ /* don't forget to set version number in BKE_blender.h! */
}
#if 0 // XXX: disabled for now... we still don't have this in the right place in the loading code for it to work
@@ -9661,8 +9783,7 @@ static void lib_link_all(FileData *fd, Main *main)
static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi)
{
kmi->properties = newdataadr(fd, kmi->properties);
- if (kmi->properties)
- IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_DirectLinkGroup_OrFree(&kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
kmi->ptr = NULL;
kmi->flag &= ~KMI_UPDATE;
}
@@ -9719,9 +9840,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
for (addon = user->addons.first; addon; addon = addon->next) {
addon->prop = newdataadr(fd, addon->prop);
- if (addon->prop) {
- IDP_DirectLinkProperty(addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
+ IDP_DirectLinkGroup_OrFree(&addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
// XXX
@@ -10501,11 +10620,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
expand_doit(fd, mainvar, psys->part);
for (sens = ob->sensors.first; sens; sens = sens->next) {
- if (sens->type == SENS_TOUCH) {
- bTouchSensor *ts = sens->data;
- expand_doit(fd, mainvar, ts->ma);
- }
- else if (sens->type == SENS_MESSAGE) {
+ if (sens->type == SENS_MESSAGE) {
bMessageSensor *ms = sens->data;
expand_doit(fd, mainvar, ms->fromObject);
}
@@ -10929,13 +11044,17 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
{
Group *group;
- /* give all objects which are LIB_INDIRECT a base, or for a group when *lib has been set */
+ /* give all objects which are tagged a base */
for (group = mainvar->group.first; group; group = group->id.next) {
- if (((group->id.flag & LIB_INDIRECT)==0 && (group->id.flag & LIB_PRE_EXISTING)==0)) {
+ if (group->id.flag & LIB_DOIT) {
Base *base;
+ Object *ob;
+
+ /* any indirect group should not have been tagged */
+ BLI_assert((group->id.flag & LIB_INDIRECT)==0);
/* BKE_object_add(...) messes with the selection */
- Object *ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2);
+ ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2);
ob->type = OB_EMPTY;
ob->lay = scene->lay;
@@ -11060,6 +11179,11 @@ static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, co
}
}
}
+ else if (id && (GS(id->name) == ID_GR)) {
+ /* tag as needing to be instanced */
+ if (flag & FILE_GROUP_INSTANCE)
+ id->flag |= LIB_DOIT;
+ }
return id;
}
@@ -11105,6 +11229,9 @@ static Main *library_append_begin(Main *mainvar, FileData **fd, const char *file
(*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist");
+ /* clear for group instancing tag */
+ tag_main_lb(&(mainvar->group), 0);
+
/* make mains */
blo_split_main((*fd)->mainlist, mainvar);
@@ -11181,6 +11308,10 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in
printf("library_append_end, scene is NULL (objects wont get bases)\n");
}
}
+
+ /* clear group instancing tag */
+ tag_main_lb(&(mainvar->group), 0);
+
/* has been removed... erm, why? s..ton) */
/* 20040907: looks like they are give base already in append_named_part(); -Nathan L */
/* 20041208: put back. It only linked direct, not indirect objects (ton) */
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index 2b63d13a9dd..12f4a295a34 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -51,9 +51,9 @@ void BLO_free_memfile(MemFile *memfile)
{
MemFileChunk *chunk;
- while ( (chunk = (memfile->chunks.first) ) ) {
- if (chunk->ident == 0) MEM_freeN(chunk->buf);
- BLI_remlink(&memfile->chunks, chunk);
+ while ((chunk = BLI_pophead(&memfile->chunks))) {
+ if (chunk->ident == 0)
+ MEM_freeN(chunk->buf);
MEM_freeN(chunk);
}
memfile->size = 0;
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
new file mode 100644
index 00000000000..6a0f1747d2f
--- /dev/null
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -0,0 +1,57 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/blenloader/intern/versioning_defaults.c
+ * \ingroup blenloader
+ */
+
+#include "BLI_utildefines.h"
+
+#include "DNA_freestyle_types.h"
+#include "DNA_linestyle_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_main.h"
+
+#include "BLO_readfile.h"
+
+/* Update defaults in startup.blend, without having to save and embed the file.
+ * This function can be emptied each time the startup.blend is updated. */
+void BLO_update_defaults_startup_blend(Main *main)
+{
+ Scene *scene;
+ SceneRenderLayer *srl;
+ FreestyleLineStyle *linestyle;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ scene->r.im_format.planes = R_IMF_PLANES_RGBA;
+
+ for (srl = scene->r.layers.first; srl; srl = srl->next)
+ srl->freestyleConfig.sphere_radius = 0.1f;
+ }
+
+ for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next)
+ linestyle->flag = LS_SAME_OBJECT;
+}
+
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 82040020ce4..067a8629906 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -518,11 +518,8 @@ static void do_version_free_effects_245(ListBase *lb)
{
Effect *eff;
- eff = lb->first;
- while (eff) {
- BLI_remlink(lb, eff);
+ while ((eff = BLI_pophead(lb))) {
do_version_free_effect_245(eff);
- eff = lb->first;
}
}
@@ -1997,15 +1994,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
while (sce) {
if (sce->toolsettings == NULL) {
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
- sce->toolsettings->cornertype =0;
- sce->toolsettings->degr = 90;
- sce->toolsettings->step = 9;
- sce->toolsettings->turn = 1;
- sce->toolsettings->extr_offs = 1;
sce->toolsettings->doublimit = 0.001f;
- sce->toolsettings->segments = 32;
- sce->toolsettings->rings = 32;
- sce->toolsettings->vertices = 32;
}
sce = sce->id.next;
}
@@ -2092,7 +2081,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (me = main->mesh.first; me; me = me->id.next) {
if (!me->medge) {
- BKE_mesh_make_edges(me, 1); /* 1 = use mface->edcode */
+ BKE_mesh_calc_edges_legacy(me, true); /* true = use mface->edcode */
}
else {
BKE_mesh_strip_loose_faces(me);
@@ -2152,9 +2141,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
for (; sce; sce = sce->id.next) {
- /* make 'innervert' the default subdivide type, for backwards compat */
- sce->toolsettings->cornertype = 1;
-
if (sce->r.scemode & R_PASSEPARTOUT) {
set_passepartout = 1;
sce->r.scemode &= ~R_PASSEPARTOUT;
@@ -2241,11 +2227,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
ntree_version_241(sce->nodetree);
/* uv calculation options moved to toolsettings */
- if (sce->toolsettings->uvcalc_radius == 0.0f) {
- sce->toolsettings->uvcalc_radius = 1.0f;
- sce->toolsettings->uvcalc_cubesize = 1.0f;
- sce->toolsettings->uvcalc_mapdir = 1;
- sce->toolsettings->uvcalc_mapalign = 1;
+ if (sce->toolsettings->unwrapper == 0) {
sce->toolsettings->uvcalc_flag = UVCALC_FILLHOLES;
sce->toolsettings->unwrapper = 1;
}
@@ -2346,8 +2328,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->toolsettings->select_thresh == 0.0f)
sce->toolsettings->select_thresh = 0.01f;
- if (sce->toolsettings->clean_thresh == 0.0f)
- sce->toolsettings->clean_thresh = 0.1f;
if (sce->r.threads == 0) {
if (sce->r.mode & R_THREADS)
@@ -2557,14 +2537,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
sce->r.bake_flag = R_BAKE_CLEAR;
}
}
-
- if (main->subversionfile < 5) {
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- /* improved triangle to quad conversion settings */
- if (sce->toolsettings->jointrilimit == 0.0f)
- sce->toolsettings->jointrilimit = 0.8f;
- }
- }
}
if (main->versionfile <= 243) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 4f0ccd3c626..a2c91969cf8 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1108,9 +1108,6 @@ static void write_sensors(WriteData *wd, ListBase *lb)
case SENS_MOUSE:
writestruct(wd, DATA, "bMouseSensor", 1, sens->data);
break;
- case SENS_TOUCH:
- writestruct(wd, DATA, "bTouchSensor", 1, sens->data);
- break;
case SENS_KEYBOARD:
writestruct(wd, DATA, "bKeyboardSensor", 1, sens->data);
break;
@@ -1739,7 +1736,7 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_
for (i = 0; i < count; ++i) {
GridPaintMask *gpm = &grid_paint_mask[i];
if (gpm->data) {
- const int gridsize = ccg_gridsize(gpm->level);
+ const int gridsize = BKE_ccg_gridsize(gpm->level);
writedata(wd, DATA,
sizeof(*gpm->data) * gridsize * gridsize,
gpm->data);
@@ -1750,16 +1747,26 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_
static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count)
{
+ CustomData data_tmp;
int i;
+ /* This copy will automatically ignore/remove layers set as NO_COPY (and TEMPORARY). */
+ CustomData_copy(data, &data_tmp, CD_MASK_EVERYTHING, CD_REFERENCE, count);
+
/* write external customdata (not for undo) */
- if (data->external && !wd->current)
- CustomData_external_write(data, id, CD_MASK_MESH, count, 0);
+ if (data_tmp.external && !wd->current)
+ CustomData_external_write(&data_tmp, id, CD_MASK_MESH, count, 0);
- writestruct(wd, DATA, "CustomDataLayer", data->maxlayer, data->layers);
+ for (i = 0; i < data_tmp.totlayer; i++)
+ data_tmp.layers[i].flag &= ~CD_FLAG_NOFREE;
- for (i=0; i<data->totlayer; i++) {
- CustomDataLayer *layer= &data->layers[i];
+ writestruct_at_address(wd, DATA, "CustomDataLayer", data_tmp.maxlayer, data->layers, data_tmp.layers);
+
+ for (i = 0; i < data_tmp.totlayer; i++)
+ data_tmp.layers[i].flag |= CD_FLAG_NOFREE;
+
+ for (i = 0; i < data_tmp.totlayer; i++) {
+ CustomDataLayer *layer= &data_tmp.layers[i];
const char *structname;
int structnum, datasize;
@@ -1795,11 +1802,13 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data,
}
}
- if (data->external)
- writestruct(wd, DATA, "CustomDataExternal", 1, data->external);
+ if (data_tmp.external)
+ writestruct_at_address(wd, DATA, "CustomDataExternal", 1, data->external, data_tmp.external);
+
+ CustomData_free(&data_tmp, count);
}
-static void write_meshs(WriteData *wd, ListBase *idbase)
+static void write_meshes(WriteData *wd, ListBase *idbase)
{
Mesh *mesh;
int save_for_old_blender= 0;
@@ -2394,6 +2403,15 @@ static void write_region(WriteData *wd, ARegion *ar, int spacetype)
}
}
+static void write_uilist(WriteData *wd, uiList *ui_list)
+{
+ writestruct(wd, DATA, "uiList", 1, ui_list);
+
+ if (ui_list->properties) {
+ IDP_WriteProperty(ui_list->properties, wd);
+ }
+}
+
static void write_soops(WriteData *wd, SpaceOops *so, LinkNode **tmp_mem_list)
{
BLI_mempool *ts = so->treestore;
@@ -2421,8 +2439,8 @@ static void write_soops(WriteData *wd, SpaceOops *so, LinkNode **tmp_mem_list)
* outliners in a screen we might get the same address on the next
* malloc, which makes the address no longer unique and so invalid for
* lookups on file read, causing crashes or double frees */
- BLI_linklist_append(tmp_mem_list, ts_flat);
- BLI_linklist_append(tmp_mem_list, data);
+ BLI_linklist_prepend(tmp_mem_list, ts_flat);
+ BLI_linklist_prepend(tmp_mem_list, data);
}
else {
so->treestore = NULL;
@@ -2431,7 +2449,8 @@ static void write_soops(WriteData *wd, SpaceOops *so, LinkNode **tmp_mem_list)
/* restore old treestore */
so->treestore = ts;
- } else {
+ }
+ else {
writestruct(wd, DATA, "SpaceOops", 1, so);
}
}
@@ -2475,7 +2494,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
writestruct(wd, DATA, "Panel", 1, pa);
for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next)
- writestruct(wd, DATA, "uiList", 1, ui_list);
+ write_uilist(wd, ui_list);
}
sl= sa->spacedata.first;
@@ -2920,6 +2939,21 @@ static void write_movieTracks(WriteData *wd, ListBase *tracks)
}
}
+static void write_moviePlaneTracks(WriteData *wd, ListBase *plane_tracks_base)
+{
+ MovieTrackingPlaneTrack *plane_track;
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ writestruct(wd, DATA, "MovieTrackingPlaneTrack", 1, plane_track);
+
+ writedata(wd, DATA, sizeof(MovieTrackingTrack *) * plane_track->point_tracksnr, plane_track->point_tracks);
+ writestruct(wd, DATA, "MovieTrackingPlaneMarker", plane_track->markersnr, plane_track->markers);
+ }
+}
+
static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction)
{
if (reconstruction->camnr)
@@ -2944,6 +2978,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
write_animdata(wd, clip->adt);
write_movieTracks(wd, &tracking->tracks);
+ write_moviePlaneTracks(wd, &tracking->plane_tracks);
write_movieReconstruction(wd, &tracking->reconstruction);
object= tracking->objects.first;
@@ -2951,6 +2986,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, "MovieTrackingObject", 1, object);
write_movieTracks(wd, &object->tracks);
+ write_moviePlaneTracks(wd, &object->plane_tracks);
write_movieReconstruction(wd, &object->reconstruction);
object= object->next;
@@ -3330,7 +3366,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_objects (wd, &mainvar->object);
write_materials(wd, &mainvar->mat);
write_textures (wd, &mainvar->tex);
- write_meshs (wd, &mainvar->mesh);
+ write_meshes (wd, &mainvar->mesh);
write_particlesettings(wd, &mainvar->particle);
write_nodetrees(wd, &mainvar->nodetree);
write_brushes (wd, &mainvar->brush);
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 228ebcb96c4..67f95cca6aa 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -41,6 +41,7 @@ set(INC_SYS
set(SRC
operators/bmo_beautify.c
operators/bmo_bevel.c
+ operators/bmo_bisect_plane.c
operators/bmo_bridge.c
operators/bmo_connect.c
operators/bmo_connect_nonplanar.c
@@ -50,6 +51,7 @@ set(SRC
operators/bmo_dupe.c
operators/bmo_edgenet.c
operators/bmo_extrude.c
+ operators/bmo_fill_attribute.c
operators/bmo_fill_edgeloop.c
operators/bmo_fill_grid.c
operators/bmo_fill_holes.c
@@ -119,10 +121,14 @@ set(SRC
tools/bmesh_bevel.c
tools/bmesh_bevel.h
+ tools/bmesh_bisect_plane.c
+ tools/bmesh_bisect_plane.h
tools/bmesh_decimate_collapse.c
tools/bmesh_decimate_dissolve.c
tools/bmesh_decimate_unsubdivide.c
tools/bmesh_decimate.h
+ tools/bmesh_edgenet.c
+ tools/bmesh_edgenet.h
tools/bmesh_edgesplit.c
tools/bmesh_edgesplit.h
tools/bmesh_path.c
@@ -130,8 +136,11 @@ set(SRC
tools/bmesh_triangulate.c
tools/bmesh_triangulate.h
- bmesh.h
bmesh_class.h
+
+ # public includes
+ bmesh.h
+ bmesh_tools.h
)
if(MSVC)
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index d1d93bbfd1d..52aeff77fca 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -45,9 +45,9 @@
* \subsection bm_header_flags Header Flags
* Each element (vertex/edge/face/loop) in a mesh has an associated bit-field called "header flags".
*
- * BMHeader flags should <b>never</b> be read or written to by bmesh operators (see Operators below).
+ * BMHeader flags should **never** be read or written to by bmesh operators (see Operators below).
*
- * Access to header flags is done with BM_elem_flag_*() functions.
+ * Access to header flags is done with ``BM_elem_flag_*()`` functions.
*
*
* \subsection bm_faces Faces
@@ -64,7 +64,8 @@
* Loops store several handy pointers:
*
* - BMLoop#v - pointer to the vertex associated with this loop.
- * - BMLoop#e - pointer to the edge associated with this loop.
+ * - BMLoop#e - pointer to the edge associated with this loop,
+ * between verts ``(loop->v, loop->next->v)``
* - BMLoop#f - pointer to the face associated with this loop.
*
*
@@ -124,14 +125,14 @@
* \subsection bm_ops Operators
*
* Operators are an integral part of BMesh. Unlike regular blender operators,
- * BMesh operators <b>bmo's</b> are designed to be nested (e.g. call other operators).
+ * BMesh operators **bmo's** are designed to be nested (e.g. call other operators).
*
* Each operator has a number of input/output "slots" which are used to pass settings & data into/out of the operator
* (and allows for chaining operators together).
*
* These slots are identified by name, using strings.
*
- * Access to slots is done with BMO_slot_*() functions.
+ * Access to slots is done with ``BMO_slot_***()`` functions.
*
*
* \subsection bm_tool_flags Tool Flags
@@ -145,9 +146,9 @@
* These flags should not be confused with header flags, which are used to store persistent flags
* (e.g. selection, hide status, etc).
*
- * Access to tool flags is done with BMO_elem_flag_*() functions.
+ * Access to tool flags is done with ``BMO_elem_flag_***()`` functions.
*
- * \warning Operators are never allowed to read or write to header flags.
+ * \warning Operators are **never** allowed to read or write to header flags.
* They act entirely on the data inside their input slots.
* For example an operator should not check the selected state of an element,
* there are some exceptions to this - some operators check of a face is smooth.
@@ -161,8 +162,10 @@
* - boolean - #BMO_OP_SLOT_BOOL
* - float - #BMO_OP_SLOT_FLT
* - pointer - #BMO_OP_SLOT_PNT
- * - element buffer - #BMO_OP_SLOT_ELEMENT_BUF - a list of verts/edges/faces
- * - map - BMO_OP_SLOT_MAPPING - simple hash map
+ * - matrix - #BMO_OP_SLOT_MAT
+ * - vector - #BMO_OP_SLOT_VEC
+ * - buffer - #BMO_OP_SLOT_ELEMENT_BUF - a list of verts/edges/faces.
+ * - map - BMO_OP_SLOT_MAPPING - simple hash map.
*
*
* \subsection bm_slot_iter Slot Iterators
@@ -185,33 +188,25 @@
*
* These conventions should be used throughout the bmesh module.
*
- * - BM_xxx() - High level BMesh API function for use anywhere.
- * - bmesh_xxx() - Low level API function.
- * - bm_xxx() - 'static' functions, not apart of the API at all, but use prefix since they operate on BMesh data.
- * - BMO_xxx() - High level operator API function for use anywhere.
- * - bmo_xxx() - Low level / internal operator API functions.
- * - _bm_xxx() - Functions which are called via macros only.
+ * - ``BM_***()`` - High level BMesh API function for use anywhere.
+ * - ``bmesh_***()`` - Low level API function.
+ * - ``bm_***()`` - 'static' functions, not apart of the API at all, but use prefix since they operate on BMesh data.
+ * - ``BMO_***()`` - High level operator API function for use anywhere.
+ * - ``bmo_***()`` - Low level / internal operator API functions.
+ * - ``_bm_***()`` - Functions which are called via macros only.
*
* \section bm_todo BMesh TODO's
*
* There may be a better place for this section, but adding here for now.
*
- * \subsection bm_todo_api API
- *
- * - make crease and bevel weight optional, they come for free in meshes but are allocated layers
- * in the bmesh data structure.
- *
- *
* \subsection bm_todo_tools Tools
*
* Probably most of these will be bmesh operators.
*
* - make ngons flat.
- * - make ngons into tris/quads (ngon poke?), many methods could be used here (triangulate/fan/quad-fan).
* - solidify (precise mode), keeps even wall thickness, re-creates outlines of offset faces with plane-plane
* intersections.
- * - split vert (we already have in our API, just no tool)
- * - bridge (add option to bridge between different edge loop counts, option to remove selected face regions)
+ * - split vert (we already have in our API, just no tool).
* - flip selected region (invert all faces about the plane defined by the selected region outline)
* - interactive dissolve (like the knife tool but draw over edges to dissolve)
*
@@ -222,16 +217,12 @@
* - skip BMO flag allocation, its not needed in many cases, this is fairly redundant to calc by default.
* - ability to call BMO's with option not to create return data (will save some time)
* - binary diff UNDO, currently this uses huge amount of ram when all shapes are stored for each undo step for eg.
- * - use two differnt iterator types for BMO map/buffer types.
- * - avoid string lookups for BMO slot lookups _especially_ when used in loops, this is very crappy.
+ * - use two different iterator types for BMO map/buffer types.
*
*
* \subsection bm_todo_tools_enhance Tool Enhancements
*
- * - face inset interpolate loop data from face (currently copies - but this stretches UV's in an ugly way)
* - vert slide UV correction (like we have for edge slide)
- * - fill-face edge net - produce consistent normals, currently it won't, fix should be to fill in edge-net node
- * connected with previous one - since they already check for normals of adjacent edge-faces before creating.
*/
#ifdef __cplusplus
@@ -251,8 +242,8 @@ extern "C" {
#include "intern/bmesh_operator_api.h"
#include "intern/bmesh_error.h"
-#include "intern/bmesh_construct.h"
#include "intern/bmesh_core.h"
+#include "intern/bmesh_construct.h"
#include "intern/bmesh_edgeloop.h"
#include "intern/bmesh_interp.h"
#include "intern/bmesh_iterators.h"
@@ -269,12 +260,6 @@ extern "C" {
#include "intern/bmesh_inline.h"
-#include "tools/bmesh_bevel.h"
-#include "tools/bmesh_decimate.h"
-#include "tools/bmesh_edgesplit.h"
-#include "tools/bmesh_path.h"
-#include "tools/bmesh_triangulate.h"
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 0e4c014a06a..90105b0dd81 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -65,7 +65,7 @@ typedef struct BMHeader {
void *data; /* customdata layers */
int index; /* notes:
* - Use BM_elem_index_get/set macros for index
- * - Unitialized to -1 so we can easily tell its not set.
+ * - Uninitialized to -1 so we can easily tell its not set.
* - Used for edge/vert/face, check BMesh.elem_index_dirty for valid index values,
* this is abused by various tools which set it dirty.
* - For loops this is used for sorting during tessellation. */
@@ -254,6 +254,8 @@ enum {
struct BPy_BMGeneric;
extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
+typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
+
/* defines */
#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
(assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
@@ -290,6 +292,12 @@ extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
* but should not error on valid cases */
#define BM_LOOP_RADIAL_MAX 10000
#define BM_NGON_MAX 100000
-#define BM_OMP_LIMIT 10000 /* 10000 */ /* setting zero so we can catch bugs in OpenMP/BMesh */
+
+/* setting zero so we can catch bugs in OpenMP/BMesh */
+#ifdef DEBUG
+# define BM_OMP_LIMIT 0
+#else
+# define BM_OMP_LIMIT 10000
+#endif
#endif /* __BMESH_CLASS_H__ */
diff --git a/source/blender/compositor/operations/COM_MixBurnOperation.h b/source/blender/bmesh/bmesh_tools.h
index 131ccfa2130..b2dac810bce 100644
--- a/source/blender/compositor/operations/COM_MixBurnOperation.h
+++ b/source/blender/bmesh/bmesh_tools.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * ***** 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
@@ -15,31 +15,35 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
-#ifndef _COM_MixBurnOperation_h
-#define _COM_MixBurnOperation_h
-#include "COM_MixBaseOperation.h"
-
+#ifndef __BMESH_TOOLS_H__
+#define __BMESH_TOOLS_H__
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
+/** \file blender/bmesh/bmesh_tools.h
+ * \ingroup bmesh
+ *
+ * Utility functions that operate directly on the BMesh,
+ * These can be used by both Modifiers and BMesh-Operators.
*/
-class MixBurnOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixBurnOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-};
+#ifdef __cplusplus
+extern "C" {
#endif
+
+#include "tools/bmesh_bevel.h"
+#include "tools/bmesh_bisect_plane.h"
+#include "tools/bmesh_decimate.h"
+#include "tools/bmesh_edgenet.h"
+#include "tools/bmesh_edgesplit.h"
+#include "tools/bmesh_path.h"
+#include "tools/bmesh_triangulate.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BMESH_TOOLS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index f5856ee94b3..1a7464ce340 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -35,6 +35,7 @@
#include "BLI_alloca.h"
#include "BLI_math.h"
+#include "BLI_sort_utils.h"
#include "BKE_customdata.h"
@@ -65,95 +66,69 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
BMFace *BM_face_create_quad_tri(BMesh *bm,
BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *example, const bool no_double)
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMVert *vtar[4] = {v1, v2, v3, v4};
- return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, no_double);
-}
-
-BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const bool no_double)
-{
- BMFace *f = NULL;
- bool is_overlap = false;
-
- /* sanity check - debug mode only */
- if (len == 3) {
- BLI_assert(verts[0] != verts[1]);
- BLI_assert(verts[0] != verts[2]);
- BLI_assert(verts[1] != verts[2]);
- }
- else if (len == 4) {
- BLI_assert(verts[0] != verts[1]);
- BLI_assert(verts[0] != verts[2]);
- BLI_assert(verts[0] != verts[3]);
-
- BLI_assert(verts[1] != verts[2]);
- BLI_assert(verts[1] != verts[3]);
-
- BLI_assert(verts[2] != verts[3]);
- }
- else {
- BLI_assert(0);
- }
-
-
- if (no_double) {
- /* check if face exists or overlaps */
- is_overlap = BM_face_exists(verts, len, &f);
- }
-
- /* make new face */
- if ((f == NULL) && (!is_overlap)) {
- BMEdge *edar[4] = {NULL};
- edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
- edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, BM_CREATE_NO_DOUBLE);
- if (len == 4) {
- edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, BM_CREATE_NO_DOUBLE);
- edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, BM_CREATE_NO_DOUBLE);
- }
- else {
- edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, BM_CREATE_NO_DOUBLE);
- }
-
- f = BM_face_create(bm, verts, edar, len, 0);
-
- if (example && f) {
- BM_elem_attrs_copy(bm, bm, example, f);
- }
- }
-
- return f;
+ return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
}
/**
* \brief copies face loop data from shared adjacent faces.
+ *
+ * \param filter_fn A function that filters the source loops before copying (don't always want to copy all)
+ *
* \note when a matching edge is found, both loops of that edge are copied
* this is done since the face may not be completely surrounded by faces,
- * this way: a quad with 2 connected quads on either side will still get all 4 loops updated */
-void BM_face_copy_shared(BMesh *bm, BMFace *f)
+ * this way: a quad with 2 connected quads on either side will still get all 4 loops updated
+ */
+void BM_face_copy_shared(BMesh *bm, BMFace *f,
+ BMElemFilterFunc filter_fn, void *user_data)
{
BMLoop *l_first;
BMLoop *l_iter;
+#ifdef DEBUG
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_OVERLAP) == 0);
+ } while ((l_iter = l_iter->next) != l_first);
+#endif
+
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
BMLoop *l_other = l_iter->radial_next;
if (l_other && l_other != l_iter) {
+ BMLoop *l_src[2];
+ BMLoop *l_dst[2] = {l_iter, l_iter->next};
+ unsigned int j;
+
if (l_other->v == l_iter->v) {
- bm_loop_attrs_copy(bm, bm, l_other, l_iter);
- bm_loop_attrs_copy(bm, bm, l_other->next, l_iter->next);
+ l_src[0] = l_other;
+ l_src[1] = l_other->next;
}
else {
- bm_loop_attrs_copy(bm, bm, l_other->next, l_iter);
- bm_loop_attrs_copy(bm, bm, l_other, l_iter->next);
+ l_src[0] = l_other->next;
+ l_src[1] = l_other;
}
- /* since we copy both loops of the shared edge, step over the next loop here */
- if ((l_iter = l_iter->next) == l_first) {
- break;
+
+ for (j = 0; j < 2; j++) {
+ BLI_assert(l_dst[j]->v == l_src[j]->v);
+ if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
+ if ((filter_fn == NULL) || filter_fn((BMElem *)l_src[j], user_data)) {
+ bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j]);
+ BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP);
+ }
+ }
}
}
} while ((l_iter = l_iter->next) != l_first);
+
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_OVERLAP);
+ } while ((l_iter = l_iter->next) != l_first);
}
/**
@@ -171,7 +146,8 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f)
* #BM_face_create should be considered over this function as it
* avoids some unnecessary work.
*/
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const int create_flag)
+BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1);
@@ -290,7 +266,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, c
BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
}
- f = BM_face_create(bm, verts_sort, edges_sort, len, create_flag);
+ f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
/* clean up flags */
for (i = 0; i < len; i++) {
@@ -318,7 +294,8 @@ err:
* - Optionally create edges between vertices.
* - Uses verts so no need to find edges (handy when you only have verts)
*/
-BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const int create_flag,
+BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
const bool calc_winding, const bool create_edges)
{
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
@@ -378,21 +355,8 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, c
bm,
v_winding[winding[0]],
v_winding[winding[1]],
- edge_arr, len, create_flag);
-}
-
-
-typedef struct AngleIndexPair {
- float angle;
- int index;
-} AngleIndexPair;
-
-static int angle_index_pair_cmp(const void *e1, const void *e2)
-{
- const AngleIndexPair *p1 = e1, *p2 = e2;
- if (p1->angle > p2->angle) return 1;
- else if (p1->angle < p2->angle) return -1;
- else return 0;
+ edge_arr, len,
+ f_example, create_flag);
}
/**
@@ -411,8 +375,12 @@ static int angle_index_pair_cmp(const void *e1, const void *e2)
*
* \note Since this is a vcloud there is no direction.
*/
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag)
+BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
+ struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
+ BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
+
BMFace *f;
float totv_inv = 1.0f / (float)len;
@@ -429,10 +397,6 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const
float far_dist, far_best;
float far_cross_dist, far_cross_best = 0.0f;
- AngleIndexPair *vang;
-
- BMVert **vert_arr_map;
-
/* get the center point and collect vector array since we loop over these a lot */
zero_v3(cent);
for (i = 0; i < len; i++) {
@@ -492,8 +456,6 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const
/* --- */
/* now calculate every points angle around the normal (signed) */
- vang = MEM_mallocN(sizeof(AngleIndexPair) * len, __func__);
-
for (i = 0; i < len; i++) {
float co[3];
float proj_vec[3];
@@ -513,26 +475,21 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const
angle = -angle;
}
- vang[i].angle = angle;
- vang[i].index = i;
+ vang[i].sort_value = angle;
+ vang[i].data = i;
}
/* sort by angle and magic! - we have our ngon */
- qsort(vang, len, sizeof(AngleIndexPair), angle_index_pair_cmp);
+ qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float);
/* --- */
/* create edges and find the winding (if faces are attached to any existing edges) */
- vert_arr_map = MEM_mallocN(sizeof(BMVert *) * len, __func__);
-
for (i = 0; i < len; i++) {
- vert_arr_map[i] = vert_arr[vang[i].index];
+ vert_arr_map[i] = vert_arr[vang[i].data];
}
- MEM_freeN(vang);
-
- f = BM_face_create_ngon_verts(bm, vert_arr_map, len, create_flag, true, true);
- MEM_freeN(vert_arr_map);
+ f = BM_face_create_ngon_verts(bm, vert_arr_map, len, f_example, create_flag, true, true);
return f;
}
@@ -543,10 +500,10 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const
*/
void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
{
- BMFace *f;
+ BMFace *f, *f_next;
BMIter iter;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
if (BMO_elem_flag_test(bm, f, oflag)) {
BM_face_kill(bm, f);
}
@@ -555,10 +512,10 @@ void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
void BMO_remove_tagged_edges(BMesh *bm, const short oflag)
{
- BMEdge *e;
+ BMEdge *e, *e_next;
BMIter iter;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
if (BMO_elem_flag_test(bm, e, oflag)) {
BM_edge_kill(bm, e);
}
@@ -567,10 +524,10 @@ void BMO_remove_tagged_edges(BMesh *bm, const short oflag)
void BMO_remove_tagged_verts(BMesh *bm, const short oflag)
{
- BMVert *v;
+ BMVert *v, *v_next;
BMIter iter;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, oflag)) {
BM_vert_kill(bm, v);
}
@@ -824,6 +781,7 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v,
BMHeader *ele_dst = ele_dst_v;
BLI_assert(ele_src->htype == ele_dst->htype);
+ BLI_assert(ele_src != ele_dst);
if ((hflag_mask & BM_ELEM_SELECT) == 0) {
/* First we copy select */
@@ -903,7 +861,7 @@ static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old,
j++;
} while ((l_iter = l_iter->next) != l_first);
- f_new = BM_face_create(bm_new, verts, edges, f->len, BM_CREATE_SKIP_CD);
+ f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
if (UNLIKELY(f_new == NULL)) {
return NULL;
@@ -953,10 +911,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
BMEditSelection *ese;
BMIter iter;
int i;
- const BMAllocTemplate allocsize = {bm_old->totvert,
- bm_old->totedge,
- bm_old->totloop,
- bm_old->totface};
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
/* allocate a bmesh */
bm_new = BM_mesh_create(&allocsize);
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index f0bd7b316e9..e85c97dffd9 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -29,20 +29,20 @@
struct BMAllocTemplate;
-BMFace *BM_face_create_quad_tri_v(BMesh *bm,
- BMVert **verts, int len,
- const BMFace *example, const bool no_double);
-
BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *example, const bool no_double);
+ const BMFace *f_example, const eBMCreateFlag create_flag);
-void BM_face_copy_shared(BMesh *bm, BMFace *f);
+void BM_face_copy_shared(BMesh *bm, BMFace *f,
+ BMElemFilterFunc filter_fn, void *user_data);
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const int create_flag);
-BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const int create_flag,
+BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
const bool calc_winding, const bool create_edges);
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag);
+BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
void BMO_remove_tagged_faces(BMesh *bm, const short oflag);
void BMO_remove_tagged_edges(BMesh *bm, const short oflag);
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index b296c367575..164a92125cd 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -56,7 +56,8 @@
/**
* \brief Main function for creating a new vertex.
*/
-BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag)
+BMVert *BM_vert_create(BMesh *bm, const float co[3],
+ const BMVert *v_example, const eBMCreateFlag create_flag)
{
BMVert *v = BLI_mempool_calloc(bm->vpool);
@@ -86,10 +87,10 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons
}
if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (example) {
+ if (v_example) {
int *keyi;
- BM_elem_attrs_copy(bm, bm, example, v);
+ BM_elem_attrs_copy(bm, bm, v_example, v);
/* exception: don't copy the original shapekey index */
keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
@@ -113,7 +114,8 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons
* \note Duplicate edges are supported by the API however users should _never_ see them.
* so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true
*/
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag)
+BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
+ const BMEdge *e_example, const eBMCreateFlag create_flag)
{
BMEdge *e;
@@ -148,8 +150,8 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example,
bmesh_disk_edge_append(e, e->v2);
if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (example) {
- BM_elem_attrs_copy(bm, bm, example, e);
+ if (e_example) {
+ BM_elem_attrs_copy(bm, bm, e_example, e);
}
else {
CustomData_bmesh_set_default(&bm->edata, &e->head.data);
@@ -190,7 +192,8 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
return l;
}
-static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const int create_flag)
+static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte,
+ const eBMCreateFlag create_flag)
{
#ifdef USE_BMESH_HOLES
BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
@@ -228,7 +231,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
i = 0;
do {
if (copy_verts) {
- verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, 0);
+ verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, BM_CREATE_NOP);
}
else {
verts[i] = l_iter->v;
@@ -251,7 +254,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
v1 = verts[(i + 1) % f->len];
}
- edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, 0);
+ edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, BM_CREATE_NOP);
}
else {
edges[i] = l_iter->e;
@@ -259,7 +262,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
i++;
} while ((l_iter = l_iter->next) != l_first);
- f_copy = BM_face_create(bm_dst, verts, edges, f->len, BM_CREATE_SKIP_CD);
+ f_copy = BM_face_create(bm_dst, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy);
@@ -320,11 +323,12 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag creat
* \param len Length of the face
* \param create_flag Options for creating the face
*/
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag)
+BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMFace *f = NULL;
BMLoop *l, *startl, *lastl;
- int i, overlap;
+ int i;
if (len == 0) {
/* just return NULL for now */
@@ -333,8 +337,8 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
if (create_flag & BM_CREATE_NO_DOUBLE) {
/* Check if face already exists */
- overlap = BM_face_exists(verts, len, &f);
- if (overlap) {
+ const bool is_overlap = BM_face_exists(verts, len, &f);
+ if (is_overlap) {
return f;
}
else {
@@ -364,11 +368,48 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
f->len = len;
+ if (!(create_flag & BM_CREATE_SKIP_CD)) {
+ if (f_example) {
+ BM_elem_attrs_copy(bm, bm, f_example, f);
+ }
+ else {
+ CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+ }
+ }
+
BM_CHECK_ELEMENT(f);
return f;
}
+/**
+ * Wrapper for #BM_face_create when you don't have an edge array
+ */
+BMFace *BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
+{
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
+ int i, i_prev = len - 1;
+
+ if (create_edges) {
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
+ i_prev = i;
+ }
+ }
+ else {
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
+ if (edge_arr[i_prev] == NULL) {
+ return NULL;
+ }
+ i_prev = i;
+ }
+ }
+
+ return BM_face_create(bm, vert_arr, edge_arr, len, f_example, create_flag);
+}
+
#ifndef NDEBUG
/**
@@ -1053,7 +1094,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
}
/* create region face */
- f_new = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL;
+ f_new = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, faces[0], BM_CREATE_NOP) : NULL;
if (UNLIKELY(!f_new || BMO_error_occurred(bm))) {
if (!BMO_error_occurred(bm))
err = N_("Invalid boundary region to join faces");
@@ -1080,8 +1121,6 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
BM_elem_attrs_copy(bm, bm, l2, l_iter);
}
} while ((l_iter = l_iter->next) != l_first);
-
- BM_elem_attrs_copy(bm, bm, faces[0], f_new);
#ifdef USE_BMESH_HOLES
/* add holes */
@@ -1239,11 +1278,12 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
}
if (!l_v1 || !l_v2) {
+ BLI_assert(0);
return NULL;
}
/* allocate new edge between v1 and v2 */
- e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : 0);
+ e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
f2 = bm_face_create__sfme(bm, f);
l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0);
@@ -1384,8 +1424,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
valence2 = bmesh_disk_count(tv);
#endif
- v_new = BM_vert_create(bm, tv->co, tv, 0);
- e_new = BM_edge_create(bm, v_new, tv, e, 0);
+ v_new = BM_vert_create(bm, tv->co, tv, BM_CREATE_NOP);
+ e_new = BM_edge_create(bm, v_new, tv, e, BM_CREATE_NOP);
bmesh_disk_edge_remove(e_new, tv);
bmesh_disk_edge_remove(e_new, v_new);
@@ -1970,7 +2010,7 @@ void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len
verts[0] = v;
for (i = 1; i < maxindex; i++) {
- verts[i] = BM_vert_create(bm, v->co, v, 0);
+ verts[i] = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
if (copy_select) {
BM_elem_select_copy(bm, bm, verts[i], v);
}
@@ -2136,7 +2176,7 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
e->l = l_sep->radial_next;
}
- e_new = BM_edge_create(bm, e->v1, e->v2, e, 0);
+ e_new = BM_edge_create(bm, e->v1, e->v2, e, BM_CREATE_NOP);
bmesh_radial_loop_remove(l_sep, e);
bmesh_radial_append(e_new, l_sep);
l_sep->e = e_new;
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index c9e806335dd..a18c2ebd32c 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -31,6 +31,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
const bool copy_verts, const bool copy_edges);
typedef enum eBMCreateFlag {
+ BM_CREATE_NOP = 0,
/* faces and edges only */
BM_CREATE_NO_DOUBLE = (1 << 1),
/* Skip CustomData - for all element types data,
@@ -39,9 +40,15 @@ typedef enum eBMCreateFlag {
BM_CREATE_SKIP_CD = (1 << 2),
} eBMCreateFlag;
-BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag);
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag);
+BMVert *BM_vert_create(BMesh *bm, const float co[3],
+ const BMVert *v_example, const eBMCreateFlag create_flag);
+BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
+ const BMEdge *e_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_verts(BMesh *bm, BMVert **verts, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool create_edges);
void BM_face_edges_kill(BMesh *bm, BMFace *f);
void BM_face_verts_kill(BMesh *bm, BMFace *f);
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index 1f052bd206a..fe3f6551b70 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -230,7 +230,7 @@ static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const in
/* on the same side - do nothing */
}
else {
- /* we have met out match! (vertices from differnt sides meet) */
+ /* we have met out match! (vertices from different sides meet) */
if (dir == 1) {
v_match[0] = vs->v;
v_match[1] = v_next;
@@ -361,8 +361,7 @@ bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops,
void BM_mesh_edgeloops_free(ListBase *eloops)
{
BMEdgeLoopStore *el_store;
- while ((el_store = eloops->first)) {
- BLI_remlink(eloops, el_store);
+ while ((el_store = BLI_pophead(eloops))) {
BM_edgeloop_free(el_store);
}
}
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h
index b46509d4030..527dba120e1 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.h
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.h
@@ -70,7 +70,7 @@ bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a
(elink)->next ? elink->next : (BM_edgeloop_is_closed(el_store) ? BM_edgeloop_verts_get(el_store)->first : NULL)
#define BM_EDGELOOP_NEXT(el_store) \
- (CHECK_TYPE_INLINE(el_store, struct BMEdgeLoopStore), \
+ (CHECK_TYPE_INLINE(el_store, struct BMEdgeLoopStore *), \
(struct BMEdgeLoopStore *)((LinkData *)el_store)->next)
#endif /* __BMESH_EDGELOOP_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h
index 102e9d47ffd..5ac6d7da61b 100644
--- a/source/blender/bmesh/intern/bmesh_inline.h
+++ b/source/blender/bmesh/intern/bmesh_inline.h
@@ -56,7 +56,7 @@ BLI_INLINE void _bm_elem_flag_enable(BMHeader *head, const char hflag)
BLI_INLINE void _bm_elem_flag_disable(BMHeader *head, const char hflag)
{
- head->hflag &= ~hflag;
+ head->hflag &= (char)~hflag;
}
BLI_INLINE void _bm_elem_flag_set(BMHeader *head, const char hflag, const int val)
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 4555de7b13d..91b9774634d 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -54,6 +54,32 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
};
/**
+ * Utility function.
+ */
+int BM_iter_mesh_count(BMesh *bm, const char itype)
+{
+ int count;
+
+ switch (itype) {
+ case BM_VERTS_OF_MESH:
+ count = bm->totvert;
+ break;
+ case BM_EDGES_OF_MESH:
+ count = bm->totedge;
+ break;
+ case BM_FACES_OF_MESH:
+ count = bm->totface;
+ break;
+ default:
+ count = 0;
+ BLI_assert(0);
+ break;
+ }
+
+ return count;
+}
+
+/**
* \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays.
*/
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
@@ -304,36 +330,66 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const
* VERT OF MESH CALLBACKS
*/
+/* see bug [#36923] for why we need this,
+ * allow adding but not removing, this isnt _totally_ safe since
+ * you could add/remove within the same loop, but catches common cases
+ */
+#ifdef DEBUG
+# define USE_IMMUTABLE_ASSERT
+#endif
+
void bmiter__vert_of_mesh_begin(struct BMIter__vert_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ ((BMIter *)iter)->count = iter->bm->totvert;
+#endif
BLI_mempool_iternew(iter->bm->vpool, &iter->pooliter);
}
void *bmiter__vert_of_mesh_step(struct BMIter__vert_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ BLI_assert(((BMIter *)iter)->count <= iter->bm->totvert);
+#endif
return BLI_mempool_iterstep(&iter->pooliter);
}
void bmiter__edge_of_mesh_begin(struct BMIter__edge_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ ((BMIter *)iter)->count = iter->bm->totedge;
+#endif
BLI_mempool_iternew(iter->bm->epool, &iter->pooliter);
}
void *bmiter__edge_of_mesh_step(struct BMIter__edge_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ BLI_assert(((BMIter *)iter)->count <= iter->bm->totedge);
+#endif
return BLI_mempool_iterstep(&iter->pooliter);
}
void bmiter__face_of_mesh_begin(struct BMIter__face_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ ((BMIter *)iter)->count = iter->bm->totface;
+#endif
BLI_mempool_iternew(iter->bm->fpool, &iter->pooliter);
}
void *bmiter__face_of_mesh_step(struct BMIter__face_of_mesh *iter)
{
+#ifdef USE_IMMUTABLE_ASSERT
+ BLI_assert(((BMIter *)iter)->count <= iter->bm->totface);
+#endif
return BLI_mempool_iterstep(&iter->pooliter);
}
+#ifdef USE_IMMUTABLE_ASSERT
+# undef USE_IMMUTABLE_ASSERT
+#endif
+
/*
* EDGE OF VERT CALLBACKS
*/
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index b5535b59321..fdf0f27f05f 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -39,6 +39,7 @@
*
*/
+#include "BLI_compiler_attrs.h"
#include "BLI_mempool.h"
/* Defines for passing to BM_iter_new.
@@ -88,6 +89,20 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \
for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++)
+/* a version of BM_ITER_MESH which keeps the next item in storage
+ * so we can delete the current item, see bug [#36923] */
+#ifdef DEBUG
+# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
+ for (ele = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((void)((iter)->count = BM_iter_mesh_count(bm, itype)), \
+ (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
+ ele = ele_next)
+#else
+# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
+ for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next)
+#endif
+
+
#define BM_ITER_ELEM(ele, iter, data, itype) \
for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter))
@@ -181,18 +196,11 @@ typedef struct BMIter {
char itype;
} BMIter;
-void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-#endif
-;
+int BM_iter_mesh_count(BMesh *bm, const char itype);
+void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT;
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
- void **stack_array, int stack_array_size)
-#ifdef __GNUC__
-__attribute__((warn_unused_result))
-#endif
-;
+ void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT;
int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
void **array, const int len);
void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index c7be4424a21..b302ca7b8b2 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -18,6 +18,21 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/bmesh/intern/bmesh_log.c
+ * \ingroup bmesh
+ *
+ * The BMLog is an interface for storing undo/redo steps as a BMesh is
+ * modified. It only stores changes to the BMesh, not full copies.
+ *
+ * Currently it supports the following types of changes:
+ *
+ * - Adding and removing vertices
+ * - Adding and removing faces
+ * - Moving vertices
+ * - Setting vertex paint-mask values
+ * - Setting vertex hflags
+ */
+
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
@@ -95,6 +110,7 @@ struct BMLog {
typedef struct {
float co[3];
+ short no[3];
float mask;
char hflag;
} BMLogVert;
@@ -117,10 +133,8 @@ static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id)
{
void *vid = SET_INT_IN_POINTER(id);
- BLI_ghash_remove(log->id_to_elem, vid, NULL, NULL);
- BLI_ghash_insert(log->id_to_elem, vid, v);
- BLI_ghash_remove(log->elem_to_id, v, NULL, NULL);
- BLI_ghash_insert(log->elem_to_id, v, vid);
+ BLI_ghash_reinsert(log->id_to_elem, vid, v, NULL, NULL);
+ BLI_ghash_reinsert(log->elem_to_id, v, vid, NULL, NULL);
}
/* Get a vertex from its unique ID */
@@ -142,11 +156,9 @@ static unsigned int bm_log_face_id_get(BMLog *log, BMFace *f)
static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id)
{
void *fid = SET_INT_IN_POINTER(id);
-
- BLI_ghash_remove(log->id_to_elem, fid, NULL, NULL);
- BLI_ghash_insert(log->id_to_elem, fid, f);
- BLI_ghash_remove(log->elem_to_id, f, NULL, NULL);
- BLI_ghash_insert(log->elem_to_id, f, fid);
+
+ BLI_ghash_reinsert(log->id_to_elem, fid, f, NULL, NULL);
+ BLI_ghash_reinsert(log->elem_to_id, f, fid, NULL, NULL);
}
/* Get a face from its unique ID */
@@ -191,6 +203,7 @@ static void vert_mask_set(BMesh *bm, BMVert *v, float new_mask)
static void bm_log_vert_bmvert_copy(BMesh *bm, BMLogVert *lv, BMVert *v)
{
copy_v3_v3(lv->co, v->co);
+ normal_float_to_short_v3(lv->no, v->no);
lv->mask = vert_mask_get(bm, v);
lv->hflag = v->head.hflag;
}
@@ -277,9 +290,10 @@ static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts)
GHASH_ITER (gh_iter, verts) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
- BMVert *v = BM_vert_create(bm, lv->co, NULL, 0);
+ BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP);
v->head.hflag = lv->hflag;
vert_mask_set(bm, v, lv->mask);
+ normal_short_to_float_v3(v->no, lv->no);
bm_log_vert_id_set(log, v, GET_INT_FROM_POINTER(key));
}
}
@@ -295,7 +309,7 @@ static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces)
bm_log_vert_from_id(log, lf->v_ids[2])};
BMFace *f;
- f = BM_face_create_quad_tri_v(bm, v, 3, NULL, false);
+ f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_NOP, true);
bm_log_face_id_set(log, f, GET_INT_FROM_POINTER(key));
}
}
@@ -309,8 +323,12 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts)
unsigned int id = GET_INT_FROM_POINTER(key);
BMVert *v = bm_log_vert_from_id(log, id);
float mask;
+ short normal[3];
swap_v3_v3(v->co, lv->co);
+ copy_v3_v3_short(normal, lv->no);
+ normal_float_to_short_v3(lv->no, v->no);
+ normal_short_to_float_v3(v->no, normal);
SWAP(char, v->head.hflag, lv->hflag);
mask = lv->mask;
lv->mask = vert_mask_get(bm, v);
@@ -404,7 +422,7 @@ static int uint_compare(const void *a_v, const void *b_v)
*/
static GHash *bm_log_compress_ids_to_indices(unsigned int *ids, int totid)
{
- GHash *map = BLI_ghash_int_new(AT);
+ GHash *map = BLI_ghash_int_new_ex(AT, totid);
int i;
qsort(ids, totid, sizeof(*ids), uint_compare);
@@ -438,8 +456,8 @@ BMLog *BM_log_create(BMesh *bm)
BMLog *log = MEM_callocN(sizeof(*log), AT);
log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
- log->id_to_elem = BLI_ghash_ptr_new(AT);
- log->elem_to_id = BLI_ghash_ptr_new(AT);
+ log->id_to_elem = BLI_ghash_ptr_new_ex(AT, bm->totvert + bm->totface);
+ log->elem_to_id = BLI_ghash_ptr_new_ex(AT, bm->totvert + bm->totface);
/* Assign IDs to all existing vertices and faces */
bm_log_assign_ids(bm, log);
@@ -931,6 +949,24 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
return lv->co;
}
+/* Get the logged normal of a vertex
+ *
+ * Does not modify the log or the vertex */
+const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
+{
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = SET_INT_IN_POINTER(v_id);
+
+ BLI_assert(entry);
+
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ return lv->no;
+}
+
/* Get the logged mask of a vertex
*
* Does not modify the log or the vertex */
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
index 958ff340b43..3cd2fd70081 100644
--- a/source/blender/bmesh/intern/bmesh_log.h
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -21,16 +21,8 @@
#ifndef __BMESH_LOG_H__
#define __BMESH_LOG_H__
-/* The BMLog is an interface for storing undo/redo steps as a BMesh is
- * modified. It only stores changes to the BMesh, not full copies.
- *
- * Currently it supports the following types of changes:
- *
- * - Adding and removing vertices
- * - Adding and removing faces
- * - Moving vertices
- * - Setting vertex paint-mask values
- * - Setting vertex hflags
+/** \file blender/bmesh/intern/bmesh_log.h
+ * \ingroup bmesh
*/
struct BMFace;
@@ -92,6 +84,9 @@ void BM_log_before_all_removed(BMesh *bm, BMLog *log);
/* Get the logged coordinates of a vertex */
const float *BM_log_original_vert_co(BMLog *log, BMVert *v);
+/* Get the logged normal of a vertex */
+const short *BM_log_original_vert_no(BMLog *log, BMVert *v);
+
/* Get the logged mask of a vertex */
float BM_log_original_mask(BMLog *log, BMVert *v);
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 64368390444..cc2324ba34a 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -667,14 +667,14 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx)
if (!(vert_idx || edge_idx || face_idx))
return;
- /* Remap vertices */
+ /* Remap Verts */
if (vert_idx) {
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
int *new_idx = NULL;
/* Init the old-to-new vert pointers mapping */
- vptr_map = BLI_ghash_ptr_new("BM_mesh_remap vert pointers mapping");
+ vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
/* Make a copy of all vertices. */
verts_pool = MEM_callocN(sizeof(BMVert *) * totvert, "BM_mesh_remap verts pool");
@@ -701,14 +701,14 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx)
MEM_freeN(verts_copy);
}
- /* XXX Code not tested yet (though I don't why it would fail)! */
+ /* Remap Edges */
if (edge_idx) {
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
int *new_idx = NULL;
/* Init the old-to-new vert pointers mapping */
- eptr_map = BLI_ghash_ptr_new("BM_mesh_remap edge pointers mapping");
+ eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
/* Make a copy of all vertices. */
edges_pool = MEM_callocN(sizeof(BMEdge *) * totedge, "BM_mesh_remap edges pool");
@@ -734,14 +734,14 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx)
MEM_freeN(edges_copy);
}
- /* XXX Code not tested yet (though I don't why it would fail)! */
+ /* Remap Faces */
if (face_idx) {
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
int *new_idx = NULL;
/* Init the old-to-new vert pointers mapping */
- fptr_map = BLI_ghash_ptr_new("BM_mesh_remap face pointers mapping");
+ fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
/* Make a copy of all vertices. */
faces_pool = MEM_callocN(sizeof(BMFace *) * totface, "BM_mesh_remap faces pool");
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index efcd80b374b..583b1589290 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -60,6 +60,13 @@ typedef struct BMAllocTemplate {
extern const BMAllocTemplate bm_mesh_allocsize_default;
extern const BMAllocTemplate bm_mesh_chunksize_default;
+#define BMALLOC_TEMPLATE_FROM_BM(bm) { (CHECK_TYPE_INLINE(bm, BMesh *), \
+ (bm)->totvert), (bm)->totedge, (bm)->totloop, (bm)->totface}
+#define BMALLOC_TEMPLATE_FROM_ME(me) { (CHECK_TYPE_INLINE(me, Mesh *), \
+ (me)->totvert), (me)->totedge, (me)->totloop, (me)->totpoly}
+#define BMALLOC_TEMPLATE_FROM_DM(dm) { (CHECK_TYPE_INLINE(dm, DerivedMesh *), \
+ (dm)->getNumVerts(dm)), (dm)->getNumEdges(dm), (dm)->getNumLoops(dm), (dm)->getNumPolys(dm)}
+
enum {
BM_MESH_CREATE_USE_TOOLFLAGS = (1 << 0)
};
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 81d4aad0fdf..d92fe45afcd 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -212,7 +212,7 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
edges[j] = etable[ml->e];
}
- return BM_face_create(bm, verts, edges, mp->totloop, BM_CREATE_SKIP_CD);
+ return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD);
}
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 418fc16ea55..3ffdd0f86a6 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -356,10 +356,9 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l
if (f_new) {
BM_elem_attrs_copy(bm, bm, f, f_new);
- copy_v3_v3(f_new->no, f->no);
/* handle multires update */
- if (has_mdisp && (f_new != f)) {
+ if (has_mdisp) {
BMLoop *l_iter;
BMLoop *l_first;
@@ -373,8 +372,6 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l
BM_loop_interp_multires(bm, l_iter, f_tmp);
} while ((l_iter = l_iter->next) != l_first);
- BM_face_kill(bm, f_tmp);
-
#if 0
/* BM_face_multires_bounds_smooth doesn't flip displacement correct */
BM_face_multires_bounds_smooth(bm, f);
@@ -383,6 +380,10 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l
}
}
+ if (has_mdisp) {
+ BM_face_kill(bm, f_tmp);
+ }
+
return f_new;
}
@@ -1067,7 +1068,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f
/* first create the new edge, this is so we can copy the customdata from the old one
* if splice if disabled, always add in a new edge even if theres one there. */
- e_new = BM_edge_create(bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) != 0);
+ e_new = BM_edge_create(bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
f_hflag_prev_1 = l1->f->head.hflag;
f_hflag_prev_2 = l2->f->head.hflag;
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 4f8a851c780..775cb24b8c9 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -542,6 +542,7 @@ static BMOpDefine bmo_grid_fill_def = {
/* restricts edges to groups. maps edges to integer */
{"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
{"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
+ {"use_interp_simple", BMO_OP_SLOT_BOOL}, /* use simple interpolation */
{{'\0'}},
},
/* slots_out */
@@ -577,6 +578,28 @@ static BMOpDefine bmo_holes_fill_def = {
/*
+ * Face Attribute Fill.
+ *
+ * Fill in faces with data from adjacent faces.
+ */
+static BMOpDefine bmo_face_attribute_fill_def = {
+ "face_attribute_fill",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"use_normals", BMO_OP_SLOT_BOOL}, /* copy face winding */
+ {"use_data", BMO_OP_SLOT_BOOL}, /* copy face data */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces_fail.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* faces that could not be handled */
+ {{'\0'}},
+ },
+ bmo_face_attribute_fill_exec,
+ BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+};
+
+/*
* Edge Loop Fill.
*
* Create faces defined by one or more non overlapping edge loops.
@@ -609,19 +632,14 @@ static BMOpDefine bmo_edgenet_fill_def = {
"edgenet_fill",
/* slots_in */
{{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- /* restricts edges to groups. maps edges to integer */
- {"restrict", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_BOOL}},
- {"use_restrict", BMO_OP_SLOT_BOOL},
- {"use_fill_check", BMO_OP_SLOT_BOOL},
- {"exclude_faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* list of faces to ignore for manifold check */
- {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
- {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
+ {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
+ {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
+ {"sides", BMO_OP_SLOT_INT}, /* number of sides */
{{'\0'}},
},
/* slots_out */
/* maps new faces to the group numbers they came from */
- {{"face_groupmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
{{'\0'}},
},
bmo_edgenet_fill_exec,
@@ -1101,6 +1119,30 @@ static BMOpDefine bmo_subdivide_edgering_def = {
};
/*
+ * Bisect Plane.
+ *
+ * Bisects the mesh by a plane (cut the mesh in half).
+ */
+static BMOpDefine bmo_bisect_plane_def = {
+ "bisect_plane",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance when testing if a vert is exactly on the plane */
+ {"plane_co", BMO_OP_SLOT_VEC}, /* point on the plane */
+ {"plane_no", BMO_OP_SLOT_VEC}, /* direction of the plane */
+ {"use_snap_center", BMO_OP_SLOT_BOOL}, /* snap axis aligned verts to the center */
+ {"clear_outer", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the positive side of the plane */
+ {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */
+ {{'\0'}},
+ },
+ {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output new geometry from the cut */
+ {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */
+ {{'\0'}}},
+ bmo_bisect_plane_exec,
+ BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+};
+
+/*
* Delete Geometry.
*
* Utility operator to delete geometry.
@@ -1136,6 +1178,8 @@ static BMOpDefine bmo_duplicate_def = {
{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
/* facemap maps from source faces to dupe
* faces, and from dupe faces to source faces */
+ {"vert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"edge_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
@@ -1536,6 +1580,7 @@ static BMOpDefine bmo_beautify_fill_def = {
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */
{"use_restrict_tag", BMO_OP_SLOT_BOOL}, /* restrict edge rotation to mixed tagged vertices */
+ {"method", BMO_OP_SLOT_INT}, /* method to define what is beautiful */
{{'\0'}},
},
/* slots_out */
@@ -1555,7 +1600,9 @@ static BMOpDefine bmo_triangle_fill_def = {
"triangle_fill",
/* slots_in */
{{"use_beauty", BMO_OP_SLOT_BOOL},
+ {"use_dissolve", BMO_OP_SLOT_BOOL}, /* dissolve resulting faces */
{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"normal", BMO_OP_SLOT_VEC}, /* optionally pass the fill normal to use */
{{'\0'}},
},
/* slots_out */
@@ -1607,7 +1654,7 @@ static BMOpDefine bmo_inset_individual_def = {
{{'\0'}},
},
bmo_inset_individual_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ BMO_OPTYPE_FLAG_NORMALS_CALC, /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
};
/*
@@ -1734,6 +1781,7 @@ static BMOpDefine bmo_symmetrize_def = {
/* slots_in */
{{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
{"direction", BMO_OP_SLOT_INT},
+ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
{{'\0'}},
},
/* slots_out */
@@ -1776,6 +1824,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_dissolve_verts_def,
&bmo_duplicate_def,
&bmo_holes_fill_def,
+ &bmo_face_attribute_fill_def,
&bmo_edgeloop_fill_def,
&bmo_edgenet_fill_def,
&bmo_edgenet_prepare_def,
@@ -1816,6 +1865,7 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_split_edges_def,
&bmo_subdivide_edges_def,
&bmo_subdivide_edgering_def,
+ &bmo_bisect_plane_def,
&bmo_symmetrize_def,
&bmo_transform_def,
&bmo_translate_def,
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 24bfcd70d75..7de158f3c29 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -335,6 +335,11 @@ void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
+void BMO_mesh_selected_remap(BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map);
+
/* copies the values from another slot to the end of the output slot */
#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
op_dst, slots_dst, slot_name_dst) \
@@ -398,7 +403,7 @@ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot
int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data, const int len);
+ const void *element, const void *data);
/* flags all elements in a mapping. note that the mapping must only have
* bmesh elements in it.*/
@@ -452,7 +457,7 @@ typedef struct BMOIter {
BMOpSlot *slot;
int cur; //for arrays
GHashIterator giter;
- void *val;
+ void **val;
char restrictmask; /* bitwise '&' with BMHeader.htype */
} BMOIter;
@@ -463,15 +468,12 @@ void *BMO_iter_new(BMOIter *iter,
const char restrictmask);
void *BMO_iter_step(BMOIter *iter);
-/* returns a pointer to the key value when iterating over mappings.
- * remember for pointer maps this will be a pointer to a pointer.*/
-void *BMO_iter_map_value(BMOIter *iter);
-
-/* use this for pointer mappings */
-void *BMO_iter_map_value_p(BMOIter *iter);
+void **BMO_iter_map_value_p(BMOIter *iter);
+void *BMO_iter_map_value_ptr(BMOIter *iter);
-/* use this for float mappings */
-float BMO_iter_map_value_f(BMOIter *iter);
+float BMO_iter_map_value_float(BMOIter *iter);
+int BMO_iter_map_value_int(BMOIter *iter);
+bool BMO_iter_map_value_bool(BMOIter *iter);
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \
for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter))
@@ -479,16 +481,6 @@ float BMO_iter_map_value_f(BMOIter *iter);
/******************* Inlined Functions********************/
typedef void (*opexec)(BMesh *bm, BMOperator *op);
-/* mappings map elements to data, which
- * follows the mapping struct in memory. */
-typedef struct BMOElemMapping {
- BMHeader *element;
- int len;
-} BMOElemMapping;
-
-/* pointer after BMOElemMapping */
-#define BMO_OP_SLOT_MAPPING_DATA(var) (void *)(((BMOElemMapping *)var) + 1)
-
extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES];
int BMO_opcode_from_opname(const char *opname);
diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
index 724ddcf3b04..77310d958e6 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
@@ -55,13 +55,13 @@ BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const shor
BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
- oflags[bm->stackdepth - 1].f &= ~oflag;
+ oflags[bm->stackdepth - 1].f &= (short)~oflag;
}
BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val)
{
if (val) oflags[bm->stackdepth - 1].f |= oflag;
- else oflags[bm->stackdepth - 1].f &= ~oflag;
+ else oflags[bm->stackdepth - 1].f &= (short)~oflag;
}
BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag)
@@ -72,23 +72,26 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor
BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot,
void *element, const int val)
{
+ union { void *ptr; int val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
- BMO_slot_map_insert(op, slot, element, &val, sizeof(int));
+ BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr));
}
BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot,
void *element, const int val)
{
+ union { void *ptr; int val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
BLI_assert(val == false || val == true);
- BMO_slot_map_insert(op, slot, element, &val, sizeof(int));
+ BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr));
}
BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot,
void *element, const float val)
{
+ union { void *ptr; float val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
- BMO_slot_map_insert(op, slot, element, &val, sizeof(float));
+ BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr));
}
@@ -101,14 +104,14 @@ BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot,
const void *element, void *val)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
- BMO_slot_map_insert(op, slot, element, &val, sizeof(void *));
+ BMO_slot_map_insert(op, slot, element, val);
}
BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot,
const void *element, void *val)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
- BMO_slot_map_insert(op, slot, element, &val, sizeof(void *));
+ BMO_slot_map_insert(op, slot, element, val);
}
@@ -117,77 +120,66 @@ BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot,
const void *element)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY);
- BMO_slot_map_insert(op, slot, element, NULL, 0);
+ BMO_slot_map_insert(op, slot, element, NULL);
}
BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element)
{
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
-
- /* sanity check */
- if (UNLIKELY(slot->data.ghash == NULL)) {
- return false;
- }
-
return BLI_ghash_haskey(slot->data.ghash, element);
}
-BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
+BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
{
- BMOElemMapping *mapping;
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
-
- /* sanity check */
- if (UNLIKELY(slot->data.ghash == NULL)) {
- return NULL;
- }
-
- mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element);
-
- if (!mapping) {
- return NULL;
- }
- return mapping + 1;
+ return BLI_ghash_lookup_p(slot->data.ghash, element);
}
BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
{
- float *val;
+ void **data;
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
- val = (float *) BMO_slot_map_data_get(slot, element);
- if (val) return *val;
-
- return 0.0f;
+ data = BMO_slot_map_data_get(slot, element);
+ if (data) {
+ return **(float **)data;
+ }
+ else {
+ return 0.0f;
+ }
}
BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
{
- int *val;
+ void **data;
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
- val = (int *) BMO_slot_map_data_get(slot, element);
- if (val) return *val;
-
- return 0;
+ data = BMO_slot_map_data_get(slot, element);
+ if (data) {
+ return **(int **)data;
+ }
+ else {
+ return 0;
+ }
}
BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
{
- int *val;
+ void **data;
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
- val = (int *) BMO_slot_map_data_get(slot, element);
- BLI_assert(val == NULL || *val == false || *val == true);
- if (val) return (bool)*val;
-
- return false;
+ data = BMO_slot_map_data_get(slot, element);
+ if (data) {
+ return **(int **)data;
+ }
+ else {
+ return false;
+ }
}
BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
{
- void **val = (void **) BMO_slot_map_data_get(slot, element);
+ void **val = BMO_slot_map_data_get(slot, element);
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
if (val) return *val;
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index b71d5a7e7d4..611ee4d03b8 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -74,7 +74,7 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = {
0, /* 7: unused */
sizeof(float) * 3, /* 8: BMO_OP_SLOT_VEC */
sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */
- sizeof(BMOElemMapping) /* 10: BMO_OP_SLOT_MAPPING */
+ sizeof(void *) /* 10: BMO_OP_SLOT_MAPPING */
};
/* Dummy slot so there is something to return when slot name lookup fails */
@@ -127,12 +127,38 @@ void BMO_pop(BMesh *bm)
/* use for both slot_types_in and slot_types_out */
static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args)
{
+ BMOpSlot *slot;
+ unsigned int i;
+ for (i = 0; slot_types[i].type; i++) {
+ slot = &slot_args[i];
+ slot->slot_name = slot_types[i].name;
+ slot->slot_type = slot_types[i].type;
+ slot->slot_subtype = slot_types[i].subtype;
+ // slot->index = i; // UNUSED
+
+ switch (slot->slot_type) {
+ case BMO_OP_SLOT_MAPPING:
+ slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args)
+{
+ BMOpSlot *slot;
unsigned int i;
for (i = 0; slot_types[i].type; i++) {
- slot_args[i].slot_name = slot_types[i].name;
- slot_args[i].slot_type = slot_types[i].type;
- slot_args[i].slot_subtype = slot_types[i].subtype;
- // slot_args[i].index = i; // UNUSED
+ slot = &slot_args[i];
+ switch (slot->slot_type) {
+ case BMO_OP_SLOT_MAPPING:
+ BLI_ghash_free(slot->data.ghash, NULL, NULL);
+ break;
+ default:
+ break;
+ }
}
}
@@ -198,20 +224,6 @@ void BMO_op_exec(BMesh *bm, BMOperator *op)
BMO_pop(bm);
}
-static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args)
-{
- BMOpSlot *slot;
- unsigned int i;
- for (i = 0; slot_types[i].type; i++) {
- slot = &slot_args[i];
- if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
- if (slot->data.ghash) {
- BLI_ghash_free(slot->data.ghash, NULL, NULL);
- }
- }
- }
-}
-
/**
* \brief BMESH OPSTACK FINISH OP
*
@@ -333,28 +345,13 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_n
}
else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) {
GHashIterator it;
- BMOElemMapping *srcmap, *dstmap;
-
- /* sanity check */
- if (!slot_src->data.ghash) {
- return;
- }
-
- if (!slot_dst->data.ghash) {
- slot_dst->data.ghash = BLI_ghash_ptr_new("bmesh operator 2");
- }
-
for (BLI_ghashIterator_init(&it, slot_src->data.ghash);
- (srcmap = BLI_ghashIterator_getValue(&it));
+ BLI_ghashIterator_done(&it) == false;
BLI_ghashIterator_step(&it))
{
- dstmap = BLI_memarena_alloc(arena_dst, sizeof(*dstmap) + srcmap->len);
-
- dstmap->element = srcmap->element;
- dstmap->len = srcmap->len;
- memcpy(BMO_OP_SLOT_MAPPING_DATA(dstmap), BMO_OP_SLOT_MAPPING_DATA(srcmap), srcmap->len);
-
- BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap);
+ void *key = BLI_ghashIterator_getKey(&it);
+ void *val = BLI_ghashIterator_getValue(&it);
+ BLI_ghash_insert(slot_dst->data.ghash, key, val);
}
}
else {
@@ -605,6 +602,44 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
}
}
+void BMO_mesh_selected_remap(BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map)
+{
+ if (bm->selected.first) {
+ BMEditSelection *ese, *ese_next;
+ BMOpSlot *slot_elem_map;
+
+ for (ese = bm->selected.first; ese; ese = ese_next) {
+ ese_next = ese->next;
+
+ switch (ese->htype) {
+ case BM_VERT: slot_elem_map = slot_vert_map; break;
+ case BM_EDGE: slot_elem_map = slot_edge_map; break;
+ default: slot_elem_map = slot_face_map; break;
+ }
+
+ ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
+
+ if (UNLIKELY((ese->ele == NULL) ||
+ (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))
+ {
+ BLI_remlink(&bm->selected, ese);
+ MEM_freeN(ese);
+ }
+ }
+ }
+
+ if (bm->act_face) {
+ BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face);
+ if (f) {
+ bm->act_face = f;
+ }
+ }
+}
+
+
int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
@@ -621,38 +656,21 @@ 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);
-
- /* check if its actually a buffer */
- if (!(slot->slot_type == BMO_OP_SLOT_MAPPING))
- return 0;
-
- return slot->data.ghash ? BLI_ghash_size(slot->data.ghash) : 0;
+ return BLI_ghash_size(slot->data.ghash);
}
/* inserts a key/value mapping into a mapping slot. note that it copies the
* value, it doesn't store a reference to it. */
void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data, const int len)
+ const void *element, const void *data)
{
- BMOElemMapping *mapping;
+ (void) op; /* Ignored in release builds. */
+
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
BMO_ASSERT_SLOT_IN_OP(slot, op);
- mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
-
- mapping->element = (BMHeader *) element;
- mapping->len = len;
- memcpy(BMO_OP_SLOT_MAPPING_DATA(mapping), data, len);
-
- if (!slot->data.ghash) {
- slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash");
- }
- else {
- BLI_assert(slot->data.ghash);
- }
-
- BLI_ghash_insert(slot->data.ghash, (void *)element, mapping);
+ BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data);
}
#if 0
@@ -707,11 +725,11 @@ void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
- /* sanity check */
- if (!slot->data.ghash) return;
- BLI_ghashIterator_init(&it, slot->data.ghash);
- for ( ; (ele_f = BLI_ghashIterator_getKey(&it)); BLI_ghashIterator_step(&it)) {
+ for (BLI_ghashIterator_init(&it, slot->data.ghash);
+ (ele_f = BLI_ghashIterator_getKey(&it));
+ BLI_ghashIterator_step(&it))
+ {
if (ele_f->head.htype & htype) {
BMO_elem_flag_enable(bm, ele_f, oflag);
}
@@ -1360,12 +1378,7 @@ void *BMO_iter_new(BMOIter *iter,
iter->restrictmask = restrictmask;
if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) {
- if (iter->slot->data.ghash) {
- BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
- }
- else {
- return NULL;
- }
+ BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
}
else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
BLI_assert(restrictmask & slot->slot_subtype.elem);
@@ -1402,11 +1415,8 @@ void *BMO_iter_step(BMOIter *iter)
return ele;
}
else if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
- BMOElemMapping *map;
void *ret = BLI_ghashIterator_getKey(&iter->giter);
- map = BLI_ghashIterator_getValue(&iter->giter);
-
- iter->val = BMO_OP_SLOT_MAPPING_DATA(map);
+ iter->val = BLI_ghashIterator_getValue_p(&iter->giter);
BLI_ghashIterator_step(&iter->giter);
@@ -1420,19 +1430,40 @@ void *BMO_iter_step(BMOIter *iter)
}
/* used for iterating over mappings */
-void *BMO_iter_map_value(BMOIter *iter)
+
+/**
+ * Returns a pointer to the key-value when iterating over mappings.
+ * remember for pointer maps this will be a pointer to a pointer.
+ */
+void **BMO_iter_map_value_p(BMOIter *iter)
{
return iter->val;
}
-void *BMO_iter_map_value_p(BMOIter *iter)
+void *BMO_iter_map_value_ptr(BMOIter *iter)
+{
+ BLI_assert(ELEM(iter->slot->slot_subtype.map,
+ BMO_OP_SLOT_SUBTYPE_MAP_ELEM, BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL));
+ return iter->val ? *iter->val : NULL;
+}
+
+
+float BMO_iter_map_value_float(BMOIter *iter)
{
- return *((void **)iter->val);
+ BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
+ return **((float **)iter->val);
}
-float BMO_iter_map_value_f(BMOIter *iter)
+int BMO_iter_map_value_int(BMOIter *iter)
{
- return *((float *)iter->val);
+ BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
+ return **((int **)iter->val);
+}
+
+bool BMO_iter_map_value_bool(BMOIter *iter)
+{
+ BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
+ return **((int **)iter->val);
}
/* error system */
@@ -1608,9 +1639,9 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
// BMOpDefine *def;
char *opname, *ofmt, *fmt;
char slot_name[64] = {0};
- int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state;
+ int i, type;
+ bool noslot, state;
char htype;
- int noslot = 0;
/* basic useful info to help find where bmop formatting strings fail */
@@ -1631,7 +1662,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
i = strcspn(fmt, " ");
opname = fmt;
- if (!opname[i]) noslot = 1;
+ noslot = (opname[i] == '\0');
opname[i] = '\0';
fmt += i + (noslot ? 0 : 1);
@@ -1648,7 +1679,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
// def = bmo_opdefines[i];
i = 0;
- state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */
+ state = true; /* false: not inside slot_code name, true: inside slot_code name */
while (*fmt) {
if (state) {
@@ -1674,7 +1705,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BLI_strncpy(slot_name, fmt, sizeof(slot_name));
- state = 0;
+ state = false;
fmt += i;
}
else {
@@ -1695,13 +1726,13 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
else GOTO_ERROR("matrix size was not 3 or 4");
BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size);
- state = 1;
+ state = true;
break;
}
case 'v':
{
BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *));
- state = 1;
+ state = true;
break;
}
case 'e': /* single vert/edge/face */
@@ -1711,7 +1742,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_buffer_from_single(op, slot, ele);
- state = 1;
+ state = true;
break;
}
case 's':
@@ -1730,20 +1761,20 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_copy(op_other, slots_out, slot_name_other,
op, slots_in, slot_name);
}
- state = 1;
+ state = true;
break;
}
case 'i':
BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int));
- state = 1;
+ state = true;
break;
case 'b':
BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int));
- state = 1;
+ state = true;
break;
case 'p':
BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *));
- state = 1;
+ state = true;
break;
case 'f':
case 'F':
@@ -1756,15 +1787,16 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
}
else {
+ bool stop = false;
+
htype = 0;
- stop = 0;
while (1) {
switch (NEXT_CHAR(fmt)) {
case 'f': htype |= BM_FACE; break;
case 'e': htype |= BM_EDGE; break;
case 'v': htype |= BM_VERT; break;
default:
- stop = 1;
+ stop = true;
break;
}
if (stop) {
@@ -1791,11 +1823,11 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
}
}
- state = 1;
+ state = true;
break;
default:
fprintf(stderr,
- "%s: unrecognized bmop format char: %c, %d in '%s'\n",
+ "%s: unrecognized bmop format char: '%c', %d in '%s'\n",
__func__, *fmt, (int)(fmt - ofmt), ofmt);
break;
}
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
index 33c10411c0f..07d0ceb3aa3 100644
--- a/source/blender/bmesh/intern/bmesh_operators_private.h
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -35,6 +35,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op);
void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op);
void bmo_bevel_exec(BMesh *bm, BMOperator *op);
void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op);
+void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op);
void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op);
void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op);
void bmo_collapse_exec(BMesh *bm, BMOperator *op);
@@ -59,6 +60,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op);
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op);
void bmo_duplicate_exec(BMesh *bm, BMOperator *op);
void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op);
+void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op);
void bmo_holes_fill_exec(BMesh *bm, BMOperator *op);
void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op);
void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 43b261c118d..0978faee9e4 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -829,7 +829,9 @@ static bool bm_face_goodline(float const (*projectverts)[2], BMFace *f, int v1i,
continue;
}
- if (isect_point_tri_v2(pv1, v1, v2, v3) || isect_point_tri_v2(pv1, v3, v2, v1)) {
+ if (isect_point_tri_v2(pv1, v1, v2, v3) ||
+ isect_point_tri_v2(pv1, v3, v2, v1))
+ {
#if 0
if (isect_point_tri_v2(pv1, v1, v2, v3))
printf("%d in (%d, %d, %d)\n", v3i, i, v1i, v2i);
@@ -863,7 +865,10 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use
const float cos_threshold = 0.9f;
const float bias = 1.0f + 1e-6f;
- BLI_assert(len_squared_v3(f->no) > FLT_EPSILON);
+ /* just triangulate degenerate faces */
+ if (UNLIKELY(is_zero_v3(f->no))) {
+ return BM_FACE_FIRST_LOOP(f);
+ }
if (f->len == 4) {
BMLoop *larr[4];
@@ -875,10 +880,10 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use
i++;
} while ((l_iter = l_iter->next) != l_first);
- /* pick 0/1 based on best lenth */
+ /* pick 0/1 based on best length */
/* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */
i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) >
- len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty);
+ len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty);
i4 = (i + 3) % 4;
/* Check produced tris aren't too flat/narrow...
* Probably not the best test, but is quite efficient and should at least avoid null-area faces! */
@@ -891,6 +896,7 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use
#endif
if (cos1 < cos2)
cos1 = cos2;
+
if (cos1 > cos_threshold) {
if (cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i4]->v->co, larr[i + 2]->v->co)) &&
cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i + 1]->v->co, larr[i + 2]->v->co)))
@@ -901,8 +907,10 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use
/* Last check we do not get overlapping triangles
* (as much as possible, there are some cases with no good solution!) */
i4 = (i + 3) % 4;
- if (!bm_face_goodline((float const (*)[2])projectverts, f, BM_elem_index_get(larr[i4]->v),
- BM_elem_index_get(larr[i]->v), BM_elem_index_get(larr[i + 1]->v)))
+ if (!bm_face_goodline((float const (*)[2])projectverts, f,
+ BM_elem_index_get(larr[i4]->v),
+ BM_elem_index_get(larr[i]->v),
+ BM_elem_index_get(larr[i + 1]->v)))
{
i = !i;
}
@@ -912,13 +920,13 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use
}
else {
/* float angle, bestangle = 180.0f; */
- float cos, bestcos = 1.0f;
- int i, j, len;
+ const int len = f->len;
+ float cos, cos_best = 1.0f;
+ int i, j;
/* Compute cos of all corners! */
i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- len = l_iter->f->len;
do {
const BMVert *v1 = l_iter->prev->v;
const BMVert *v2 = l_iter->v;
@@ -936,39 +944,41 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use
const BMVert *v2 = l_iter->v;
const BMVert *v3 = l_iter->next->v;
- if (bm_face_goodline((float const (*)[2])projectverts, f,
- BM_elem_index_get(v1), BM_elem_index_get(v2), BM_elem_index_get(v3)))
- {
- /* Compute highest cos (i.e. narrowest angle) of this tri. */
- cos = max_fff(abscoss[i],
- fabsf(cos_v3v3v3(v2->co, v3->co, v1->co)),
- fabsf(cos_v3v3v3(v3->co, v1->co, v2->co)));
-
- /* Compare to prev best (i.e. lowest) cos. */
- if (cos < bestcos) {
+ /* Compute highest cos (i.e. narrowest angle) of this tri. */
+ cos = max_fff(abscoss[i],
+ fabsf(cos_v3v3v3(v2->co, v3->co, v1->co)),
+ fabsf(cos_v3v3v3(v3->co, v1->co, v2->co)));
+
+ /* Compare to prev best (i.e. lowest) cos. */
+ if (cos < cos_best) {
+ if (bm_face_goodline((float const (*)[2])projectverts, f,
+ BM_elem_index_get(v1),
+ BM_elem_index_get(v2),
+ BM_elem_index_get(v3)))
+ {
/* We must check this tri would not leave a (too much) degenerated remaining face! */
/* For now just assume if the average of cos of all
* "remaining face"'s corners is below a given threshold, it's OK. */
- float avgcos = fabsf(cos_v3v3v3(v1->co, v3->co, l_iter->next->next->v->co));
+ float cos_mean = fabsf(cos_v3v3v3(v1->co, v3->co, l_iter->next->next->v->co));
const int i_limit = (i - 1 + len) % len;
- avgcos += fabsf(cos_v3v3v3(l_iter->prev->prev->v->co, v1->co, v3->co));
+ cos_mean += fabsf(cos_v3v3v3(l_iter->prev->prev->v->co, v1->co, v3->co));
j = (i + 2) % len;
do {
- avgcos += abscoss[j];
+ cos_mean += abscoss[j];
} while ((j = (j + 1) % len) != i_limit);
- avgcos /= len - 1;
+ cos_mean /= len - 1;
/* We need a best ear in any case... */
- if (avgcos < cos_threshold || (!bestear && avgcos < 1.0f)) {
+ if (cos_mean < cos_threshold || (!bestear && cos_mean < 1.0f)) {
/* OKI, keep this ear (corner...) as a potential best one! */
bestear = l_iter;
- bestcos = cos;
+ cos_best = cos;
}
#if 0
else
- printf("Had a nice tri (higest cos of %f, current bestcos is %f), "
+ printf("Had a nice tri (higest cos of %f, current cos_best is %f), "
"but average cos of all \"remaining face\"'s corners is too high (%f)!\n",
- cos, bestcos, avgcos);
+ cos, cos_best, cos_mean);
#endif
}
}
@@ -1203,3 +1213,37 @@ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
r_verts[2] = l->v; l = l->next;
r_verts[3] = l->v;
}
+
+
+/**
+ * Small utility functions for fast access
+ *
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 3);
+ */
+void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3])
+{
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+
+ BLI_assert(f->len == 3);
+
+ r_loops[0] = l; l = l->next;
+ r_loops[1] = l; l = l->next;
+ r_loops[2] = l;
+}
+
+/**
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 4);
+ */
+void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4])
+{
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+
+ BLI_assert(f->len == 4);
+
+ r_loops[0] = l; l = l->next;
+ r_loops[1] = l; l = l->next;
+ r_loops[2] = l; l = l->next;
+ r_loops[3] = l;
+}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index e5dc5c081c3..14fe1e76360 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -27,40 +27,40 @@
* \ingroup bmesh
*/
-int BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, int (*r_index)[3])
-#ifdef __GNUC__
- __attribute__((warn_unused_result))
- __attribute__((nonnull))
-#endif
-;
-void BM_face_calc_normal(const BMFace *f, float r_no[3]);
+#include "BLI_compiler_attrs.h"
+
+int BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, int (*r_index)[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
void BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3],
- float const (*vertexCos)[3]);
-float BM_face_calc_area(BMFace *f);
-float BM_face_calc_perimeter(BMFace *f);
-void BM_face_calc_plane(BMFace *f, float r_plane[3]);
-void BM_face_calc_center_bounds(BMFace *f, float center[3]);
-void BM_face_calc_center_mean(BMFace *f, float center[3]);
+ float const (*vertexCos)[3]) ATTR_NONNULL();
+float BM_face_calc_area(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_face_calc_perimeter(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_face_calc_plane(BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_center_bounds(BMFace *f, float center[3]) ATTR_NONNULL();
+void BM_face_calc_center_mean(BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3],
- float const (*vertexCos)[3]);
-void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]);
+ float const (*vertexCos)[3]) ATTR_NONNULL();
+void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]) ATTR_NONNULL();
-void BM_face_normal_update(BMFace *f);
+void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
-void BM_edge_normals_update(BMEdge *e);
+void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL();
-void BM_vert_normal_update(BMVert *v);
-void BM_vert_normal_update_all(BMVert *v);
+void BM_vert_normal_update(BMVert *v) ATTR_NONNULL();
+void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL();
-void BM_face_normal_flip(BMesh *bm, BMFace *f);
-bool BM_face_point_inside_test(BMFace *f, const float co[3]);
+void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL();
+bool BM_face_point_inside_test(BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **newfaces,
- const bool use_beauty, const bool use_tag);
+ const bool use_beauty, const bool use_tag) ATTR_NONNULL(1, 2);
+
+void BM_face_legal_splits(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
-void BM_face_legal_splits(BMFace *f, BMLoop *(*loops)[2], int len);
+void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) ATTR_NONNULL();
+void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) ATTR_NONNULL();
-void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]);
-void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]);
+void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) ATTR_NONNULL();
+void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) ATTR_NONNULL();
#endif /* __BMESH_POLYGON_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 6eab3c625fa..9b4f34d18f2 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -35,6 +35,7 @@
#include "BLI_math.h"
#include "BLI_alloca.h"
+#include "BLI_linklist.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
@@ -991,6 +992,25 @@ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
}
/**
+ * \brief Return the Loop Shared by Edge and Vert
+ *
+ * Finds the loop used which uses \a in face loop \a l
+ *
+ * \note this function takes a loop rather then an edge
+ * so we can select the face that the loop should be from.
+ */
+BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v)
+{
+ BLI_assert(BM_vert_in_edge(l->e, v));
+ if (l->v == v) {
+ return l;
+ }
+ else {
+ return l->next;
+ }
+}
+
+/**
* \brief Return the Loop Shared by Face and Vertex
*
* Finds the loop used which uses \a v in face loop \a l
@@ -1453,8 +1473,7 @@ BMEdge *BM_edge_find_double(BMEdge *e)
* there is a face with exactly those vertices
* (and only those vertices).
*
- * \note there used to be a BM_face_exists_overlap function that checked for partial overlap,
- * however this is no longer used, simple to add back.
+ * \note there used to be a BM_face_exists_overlap function that checks for partial overlap.
*/
bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
{
@@ -1684,6 +1703,140 @@ bool BM_face_exists_multi_edge(BMEdge **earr, int len)
return ok;
}
+
+/**
+ * Given a set of vertices (varr), find out if
+ * all those vertices overlap an existing face.
+ *
+ * \note The face may contain other verts \b not in \a varr.
+ *
+ * \note Its possible there are more then one overlapping faces,
+ * in this case the first one found will be assigned to \a r_f_overlap.
+ *
+ * \param varr Array of unordered verts.
+ * \param len \a varr array length.
+ * \param r_f_overlap The overlapping face to return.
+ * \return Success
+ */
+
+bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap)
+{
+ BMIter viter;
+ BMFace *f;
+ int i;
+ bool is_overlap = false;
+ LinkNode *f_lnk = NULL;
+
+ if (r_f_overlap) {
+ *r_f_overlap = NULL;
+ }
+
+#ifdef DEBUG
+ /* check flag isn't already set */
+ for (i = 0; i < len; i++) {
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0);
+ }
+ }
+#endif
+
+ for (i = 0; i < len; i++) {
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) {
+ if (len <= BM_verts_in_face_count(f, varr, len)) {
+ if (r_f_overlap)
+ *r_f_overlap = f;
+
+ is_overlap = true;
+ break;
+ }
+
+ BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP);
+ BLI_linklist_prepend_alloca(&f_lnk, f);
+ }
+ }
+ }
+
+ for (; f_lnk; f_lnk = f_lnk->next) {
+ BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP);
+ }
+
+ return is_overlap;
+}
+
+/**
+ * Given a set of vertices (varr), find out if
+ * there is a face that uses vertices only from this list
+ * (that the face is a subset or made from the vertices given).
+ *
+ * \param varr Array of unordered verts.
+ * \param len varr array length.
+ */
+bool BM_face_exists_overlap_subset(BMVert **varr, const int len)
+{
+ BMIter viter;
+ BMFace *f;
+ int i;
+ bool is_init = false;
+ bool is_overlap = false;
+ LinkNode *f_lnk = NULL;
+
+#ifdef DEBUG
+ /* check flag isn't already set */
+ for (i = 0; i < len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP) == 0);
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0);
+ }
+ }
+#endif
+
+ for (i = 0; i < len; i++) {
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ if ((f->len <= len) && (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0)) {
+ /* check if all vers in this face are flagged*/
+ BMLoop *l_iter, *l_first;
+
+ if (is_init == false) {
+ is_init = true;
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
+ }
+ }
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ is_overlap = true;
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP) == 0) {
+ is_overlap = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (is_overlap) {
+ break;
+ }
+
+ BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP);
+ BLI_linklist_prepend_alloca(&f_lnk, f);
+ }
+ }
+ }
+
+ if (is_init == true) {
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
+ }
+
+ for (; f_lnk; f_lnk = f_lnk->next) {
+ BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP);
+ }
+
+ return is_overlap;
+}
+
+
/* convenience functions for checking flags */
bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag)
{
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 2c931de995e..a057d120be1 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -27,8 +27,6 @@
* \ingroup bmesh
*/
-typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
-
bool BM_vert_in_face(BMFace *f, BMVert *v);
int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len);
bool BM_verts_in_face(BMFace *f, BMVert **varr, int len);
@@ -95,6 +93,9 @@ bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface);
bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len);
bool BM_face_exists_multi_edge(BMEdge **earr, int len);
+bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap);
+bool BM_face_exists_overlap_subset(BMVert **varr, const int len);
+
int BM_face_share_face_count(BMFace *f_a, BMFace *f_b);
int BM_face_share_edge_count(BMFace *f1, BMFace *f2);
@@ -105,6 +106,7 @@ bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2);
bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2);
BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2);
+BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v);
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v);
BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e);
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index 80b85ab6edd..af901b3359c 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -87,8 +87,8 @@ void BMW_init(BMWalker *walker, BMesh *bm, int type,
walker->mask_edge = mask_edge;
walker->mask_face = mask_face;
- walker->visithash = BLI_ghash_ptr_new("bmesh walkers 1");
- walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers sec 1");
+ walker->visit_set = BLI_gset_ptr_new("bmesh walkers");
+ walker->visit_set_alt = BLI_gset_ptr_new("bmesh walkers sec");
if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) {
fprintf(stderr,
@@ -127,8 +127,8 @@ void BMW_init(BMWalker *walker, BMesh *bm, int type,
void BMW_end(BMWalker *walker)
{
BLI_mempool_destroy(walker->worklist);
- BLI_ghash_free(walker->visithash, NULL, NULL);
- BLI_ghash_free(walker->secvisithash, NULL, NULL);
+ BLI_gset_free(walker->visit_set, NULL);
+ BLI_gset_free(walker->visit_set_alt, NULL);
}
@@ -253,8 +253,6 @@ void BMW_reset(BMWalker *walker)
BMW_state_remove(walker);
}
walker->depth = 0;
- BLI_ghash_free(walker->visithash, NULL, NULL);
- BLI_ghash_free(walker->secvisithash, NULL, NULL);
- walker->visithash = BLI_ghash_ptr_new("bmesh walkers 1");
- walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers sec 1");
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_clear(walker->visit_set_alt, NULL);
}
diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h
index 8be362b5afa..ea1dbc61cc6 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.h
+++ b/source/blender/bmesh/intern/bmesh_walkers.h
@@ -67,8 +67,8 @@ typedef struct BMWalker {
BMWFlag flag;
- GHash *visithash;
- GHash *secvisithash;
+ GSet *visit_set;
+ GSet *visit_set_alt;
int depth;
} BMWalker;
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 6a8ce32991e..238b7b4aaaa 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -26,6 +26,8 @@
* BMesh Walker Code.
*/
+#include <string.h>
+
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
@@ -34,6 +36,12 @@
#include "intern/bmesh_private.h"
#include "intern/bmesh_walkers_private.h"
+/* pop into stack memory (common operation) */
+#define BMW_state_remove_r(walker, owalk) { \
+ memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \
+ BMW_state_remove(walker); \
+} (void)0
+
static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
{
if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
@@ -85,7 +93,7 @@ static void bmw_ShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
{
BMwShellWalker *shellWalk = NULL;
- if (BLI_ghash_haskey(walker->visithash, e)) {
+ if (BLI_gset_haskey(walker->visit_set, e)) {
return;
}
@@ -95,7 +103,7 @@ static void bmw_ShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
shellWalk = BMW_state_add(walker);
shellWalk->curedge = e;
- BLI_ghash_insert(walker->visithash, e, NULL);
+ BLI_gset_insert(walker->visit_set, e);
}
static void bmw_ShellWalker_begin(BMWalker *walker, void *data)
@@ -140,14 +148,16 @@ static void *bmw_ShellWalker_yield(BMWalker *walker)
static void *bmw_ShellWalker_step(BMWalker *walker)
{
- BMwShellWalker *swalk = BMW_current_state(walker);
+ BMwShellWalker *swalk, owalk;
BMEdge *e, *e2;
BMVert *v;
BMIter iter;
int i;
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
+
e = swalk->curedge;
- BMW_state_remove(walker);
for (i = 0; i < 2; i++) {
v = i ? e->v2 : e->v1;
@@ -167,8 +177,8 @@ static void *bmw_ShellWalker_step(BMWalker *walker)
bool restrictpass = true;
BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker));
- if (!BLI_ghash_haskey(walker->visithash, shellWalk.base)) {
- BLI_ghash_insert(walker->visithash, shellWalk.base, NULL);
+ if (!BLI_gset_haskey(walker->visit_set, shellWalk.base)) {
+ BLI_gset_insert(walker->visit_set, shellWalk.base);
}
BMW_state_remove(walker);
@@ -177,7 +187,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker)
/* find the next edge whose other vertex has not been visite */
curedge = shellWalk.curedge;
do {
- if (!BLI_ghash_haskey(walker->visithash, curedge)) {
+ if (!BLI_gset_haskey(walker->visit_set, curedge)) {
if (!walker->restrictflag ||
(walker->restrictflag && BMO_elem_flag_test(walker->bm, curedge, walker->restrictflag)))
{
@@ -187,7 +197,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker)
/* push a new state onto the stac */
newState = BMW_state_add(walker);
- BLI_ghash_insert(walker->visithash, curedge, NULL);
+ BLI_gset_insert(walker->visit_set, curedge);
/* populate the new stat */
@@ -211,7 +221,7 @@ static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v)
{
BMwConnectedVertexWalker *vwalk;
- if (BLI_ghash_haskey(walker->visithash, v)) {
+ if (BLI_gset_haskey(walker->visit_set, v)) {
/* already visited */
return;
}
@@ -223,7 +233,7 @@ static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v)
vwalk = BMW_state_add(walker);
vwalk->curvert = v;
- BLI_ghash_insert(walker->visithash, v, NULL);
+ BLI_gset_insert(walker->visit_set, v);
}
static void bmw_ConnectedVertexWalker_begin(BMWalker *walker, void *data)
@@ -240,18 +250,19 @@ static void *bmw_ConnectedVertexWalker_yield(BMWalker *walker)
static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
{
- BMwConnectedVertexWalker *vwalk = BMW_current_state(walker);
+ BMwConnectedVertexWalker *vwalk, owalk;
BMVert *v, *v2;
BMEdge *e;
BMIter iter;
- v = vwalk->curvert;
+ BMW_state_remove_r(walker, &owalk);
+ vwalk = &owalk;
- BMW_state_remove(walker);
+ v = vwalk->curvert;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
v2 = BM_edge_other_vert(e, v);
- if (!BLI_ghash_haskey(walker->visithash, v2)) {
+ if (!BLI_gset_haskey(walker->visit_set, v2)) {
bmw_ConnectedVertexWalker_visitVertex(walker, v2);
}
}
@@ -276,7 +287,7 @@ static void bmw_IslandboundWalker_begin(BMWalker *walker, void *data)
iwalk->base = iwalk->curloop = l;
iwalk->lastv = l->v;
- BLI_ghash_insert(walker->visithash, data, NULL);
+ BLI_gset_insert(walker->visit_set, data);
}
@@ -289,14 +300,19 @@ static void *bmw_IslandboundWalker_yield(BMWalker *walker)
static void *bmw_IslandboundWalker_step(BMWalker *walker)
{
- BMwIslandboundWalker *iwalk = BMW_current_state(walker), owalk;
+ BMwIslandboundWalker *iwalk, owalk;
BMVert *v;
- BMEdge *e = iwalk->curloop->e;
+ BMEdge *e;
BMFace *f;
- BMLoop *l = iwalk->curloop;
+ BMLoop *l;
/* int found = 0; */
- owalk = *iwalk;
+ memcpy(&owalk, BMW_current_state(walker), sizeof(owalk));
+ /* normally we'd remove here, but delay until after error checking */
+ iwalk = &owalk;
+
+ l = iwalk->curloop;
+ e = l->e;
v = BM_edge_other_vert(e, iwalk->lastv);
@@ -307,7 +323,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker)
return NULL;
}
- /* pop off current stat */
+ /* pop off current state */
BMW_state_remove(walker);
f = l->f;
@@ -334,11 +350,11 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker)
if (l == owalk.curloop) {
return NULL;
}
- else if (BLI_ghash_haskey(walker->visithash, l)) {
+ else if (BLI_gset_haskey(walker->visit_set, l)) {
return owalk.curloop;
}
- BLI_ghash_insert(walker->visithash, l, NULL);
+ BLI_gset_insert(walker->visit_set, l);
iwalk = BMW_state_add(walker);
iwalk->base = owalk.base;
@@ -367,7 +383,7 @@ static void bmw_IslandWalker_begin(BMWalker *walker, void *data)
}
iwalk = BMW_state_add(walker);
- BLI_ghash_insert(walker->visithash, data, NULL);
+ BLI_gset_insert(walker->visit_set, data);
iwalk->cur = data;
}
@@ -381,13 +397,13 @@ static void *bmw_IslandWalker_yield(BMWalker *walker)
static void *bmw_IslandWalker_step(BMWalker *walker)
{
- BMwIslandWalker *iwalk = BMW_current_state(walker);
- /* BMwIslandWalker *owalk = iwalk; */ /* UNUSED */
+ BMwIslandWalker *iwalk, owalk;
BMIter iter, liter;
- BMFace *f, *curf = iwalk->cur;
+ BMFace *f;
BMLoop *l;
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ iwalk = &owalk;
l = BM_iter_new(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur);
for ( ; l; l = BM_iter_step(&liter)) {
@@ -403,23 +419,23 @@ static void *bmw_IslandWalker_step(BMWalker *walker)
continue;
}
- /* saves checking BLI_ghash_haskey below (manifold edges theres a 50% chance) */
+ /* saves checking BLI_gset_haskey below (manifold edges theres a 50% chance) */
if (f == iwalk->cur) {
continue;
}
- if (BLI_ghash_haskey(walker->visithash, f)) {
+ if (BLI_gset_haskey(walker->visit_set, f)) {
continue;
}
iwalk = BMW_state_add(walker);
iwalk->cur = f;
- BLI_ghash_insert(walker->visithash, f, NULL);
+ BLI_gset_insert(walker->visit_set, f);
break;
}
}
- return curf;
+ return owalk.cur;
}
@@ -448,7 +464,7 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data)
v = e->v1;
lwalk = BMW_state_add(walker);
- BLI_ghash_insert(walker->visithash, e, NULL);
+ BLI_gset_insert(walker->visit_set, e);
lwalk->cur = lwalk->start = e;
lwalk->lastv = lwalk->startv = v;
@@ -494,9 +510,8 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data)
lwalk->lastv = lwalk->startv = BM_edge_other_vert(owalk.cur, lwalk->lastv);
- BLI_ghash_free(walker->visithash, NULL, NULL);
- walker->visithash = BLI_ghash_ptr_new("bmesh walkers 2");
- BLI_ghash_insert(walker->visithash, owalk.cur, NULL);
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_insert(walker->visit_set, owalk.cur);
}
static void *bmw_LoopWalker_yield(BMWalker *walker)
@@ -508,15 +523,16 @@ static void *bmw_LoopWalker_yield(BMWalker *walker)
static void *bmw_LoopWalker_step(BMWalker *walker)
{
- BMwLoopWalker *lwalk = BMW_current_state(walker), owalk;
- BMEdge *e = lwalk->cur, *nexte = NULL;
+ BMwLoopWalker *lwalk, owalk;
+ BMEdge *e, *nexte = NULL;
BMLoop *l;
BMVert *v;
int i = 0;
- owalk = *lwalk;
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
+ e = lwalk->cur;
l = e->l;
if (owalk.f_hub) { /* NGON EDGE */
@@ -531,7 +547,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
nexte = BM_edge_exists(v, l->v);
if (bmw_mask_check_edge(walker, nexte) &&
- !BLI_ghash_haskey(walker->visithash, nexte) &&
+ !BLI_gset_haskey(walker->visit_set, nexte) &&
/* never step onto a boundary edge, this gives odd-results */
(BM_edge_is_boundary(nexte) == false))
{
@@ -543,7 +559,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
lwalk->is_single = owalk.is_single;
lwalk->f_hub = owalk.f_hub;
- BLI_ghash_insert(walker->visithash, nexte, NULL);
+ BLI_gset_insert(walker->visit_set, nexte);
}
}
}
@@ -557,7 +573,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) {
if ((nexte->l == NULL) &&
bmw_mask_check_edge(walker, nexte) &&
- !BLI_ghash_haskey(walker->visithash, nexte))
+ !BLI_gset_haskey(walker->visit_set, nexte))
{
lwalk = BMW_state_add(walker);
lwalk->cur = nexte;
@@ -567,7 +583,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
lwalk->is_single = owalk.is_single;
lwalk->f_hub = owalk.f_hub;
- BLI_ghash_insert(walker->visithash, nexte, NULL);
+ BLI_gset_insert(walker->visit_set, nexte);
}
}
}
@@ -602,7 +618,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
if (l != NULL) {
if (l != e->l &&
bmw_mask_check_edge(walker, l->e) &&
- !BLI_ghash_haskey(walker->visithash, l->e))
+ !BLI_gset_haskey(walker->visit_set, l->e))
{
lwalk = BMW_state_add(walker);
lwalk->cur = l->e;
@@ -612,7 +628,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
lwalk->is_single = owalk.is_single;
lwalk->f_hub = owalk.f_hub;
- BLI_ghash_insert(walker->visithash, l->e, NULL);
+ BLI_gset_insert(walker->visit_set, l->e);
}
}
}
@@ -655,7 +671,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
if (l != NULL) {
if (l != e->l &&
bmw_mask_check_edge(walker, l->e) &&
- !BLI_ghash_haskey(walker->visithash, l->e))
+ !BLI_gset_haskey(walker->visit_set, l->e))
{
lwalk = BMW_state_add(walker);
lwalk->cur = l->e;
@@ -665,7 +681,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
lwalk->is_single = owalk.is_single;
lwalk->f_hub = owalk.f_hub;
- BLI_ghash_insert(walker->visithash, l->e, NULL);
+ BLI_gset_insert(walker->visit_set, l->e);
}
}
}
@@ -694,8 +710,8 @@ static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l)
return false;
}
- /* the face must not have been already visite */
- if (BLI_ghash_haskey(walker->visithash, l->f) && BLI_ghash_haskey(walker->secvisithash, l->e)) {
+ /* the face must not have been already visited */
+ if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) {
return false;
}
@@ -739,9 +755,9 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
lwalk = BMW_state_add(walker);
lwalk->l = e->l;
lwalk->no_calc = false;
- BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
+ BLI_gset_insert(walker->visit_set, lwalk->l->f);
- /* rewin */
+ /* rewind */
while ((owalk_pt = BMW_current_state(walker))) {
owalk = *((BMwFaceLoopWalker *)owalk_pt);
BMW_walk(walker);
@@ -751,13 +767,11 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
*lwalk = owalk;
lwalk->no_calc = false;
- BLI_ghash_free(walker->secvisithash, NULL, NULL);
- walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers 3");
- BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL);
+ BLI_gset_clear(walker->visit_set_alt, NULL);
+ BLI_gset_insert(walker->visit_set_alt, lwalk->l->e);
- BLI_ghash_free(walker->visithash, NULL, NULL);
- walker->visithash = BLI_ghash_ptr_new("bmesh walkers 3");
- BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_insert(walker->visit_set, lwalk->l->f);
}
static void *bmw_FaceLoopWalker_yield(BMWalker *walker)
@@ -773,13 +787,15 @@ static void *bmw_FaceLoopWalker_yield(BMWalker *walker)
static void *bmw_FaceLoopWalker_step(BMWalker *walker)
{
- BMwFaceLoopWalker *lwalk = BMW_current_state(walker);
- BMFace *f = lwalk->l->f;
- BMLoop *l = lwalk->l, *origl = lwalk->l;
+ BMwFaceLoopWalker *lwalk, owalk;
+ BMFace *f;
+ BMLoop *l;
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
- l = l->radial_next;
+ f = lwalk->l->f;
+ l = lwalk->l->radial_next;
if (lwalk->no_calc) {
return f;
@@ -800,14 +816,15 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
if (l->f->len != 4) {
lwalk->no_calc = true;
- lwalk->l = origl;
+ lwalk->l = owalk.l;
}
else {
lwalk->no_calc = false;
}
- BLI_ghash_insert(walker->secvisithash, l->e, NULL);
- BLI_ghash_insert(walker->visithash, l->f, NULL);
+ /* both may already exist */
+ BLI_gset_reinsert(walker->visit_set_alt, l->e, NULL);
+ BLI_gset_reinsert(walker->visit_set, l->f, NULL);
}
return f;
@@ -838,7 +855,7 @@ static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data)
lwalk->wireedge = NULL;
}
- BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL);
+ BLI_gset_insert(walker->visit_set, lwalk->l->e);
/* rewind */
while ((owalk_pt = BMW_current_state(walker))) {
@@ -858,9 +875,8 @@ static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data)
lwalk->l = lwalk->l->radial_next;
}
- BLI_ghash_free(walker->visithash, NULL, NULL);
- walker->visithash = BLI_ghash_ptr_new("bmesh walkers 4");
- BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL);
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_insert(walker->visit_set, lwalk->l->e);
}
static void *bmw_EdgeringWalker_yield(BMWalker *walker)
@@ -881,19 +897,21 @@ static void *bmw_EdgeringWalker_yield(BMWalker *walker)
static void *bmw_EdgeringWalker_step(BMWalker *walker)
{
- BMwEdgeringWalker *lwalk = BMW_current_state(walker);
- BMEdge *e, *wireedge = lwalk->wireedge;
- BMLoop *l = lwalk->l, *origl = lwalk->l;
+ BMwEdgeringWalker *lwalk, owalk;
+ BMEdge *e;
+ BMLoop *l;
#ifdef BMW_EDGERING_NGON
int i, len;
#endif
#define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e)))
- BMW_state_remove(walker);
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
+ l = lwalk->l;
if (!l)
- return wireedge;
+ return lwalk->wireedge;
e = l->e;
if (!EDGE_CHECK(e)) {
@@ -916,7 +934,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) ||
!bmw_mask_check_face(walker, l->f))
{
- l = origl;
+ l = owalk.l;
i = len;
while (i > 0) {
l = l->next;
@@ -925,7 +943,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
}
/* only walk to manifold edge */
if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) &&
- !BLI_ghash_haskey(walker->visithash, l->e))
+ !BLI_gset_haskey(walker->visit_set, l->e))
#else
@@ -933,18 +951,18 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
l = l->next->next;
if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
- l = origl->next->next;
+ l = owalk.l->next->next;
}
/* only walk to manifold edge */
if ((l->f->len == 4) && EDGE_CHECK(l->e) &&
- !BLI_ghash_haskey(walker->visithash, l->e))
+ !BLI_gset_haskey(walker->visit_set, l->e))
#endif
{
lwalk = BMW_state_add(walker);
lwalk->l = l;
lwalk->wireedge = NULL;
- BLI_ghash_insert(walker->visithash, l->e, NULL);
+ BLI_gset_insert(walker->visit_set, l->e);
}
return e;
@@ -957,12 +975,12 @@ static void bmw_UVEdgeWalker_begin(BMWalker *walker, void *data)
BMwUVEdgeWalker *lwalk;
BMLoop *l = data;
- if (BLI_ghash_haskey(walker->visithash, l))
+ if (BLI_gset_haskey(walker->visit_set, l))
return;
lwalk = BMW_state_add(walker);
lwalk->l = l;
- BLI_ghash_insert(walker->visithash, l, NULL);
+ BLI_gset_insert(walker->visit_set, l);
}
static void *bmw_UVEdgeWalker_yield(BMWalker *walker)
@@ -978,17 +996,18 @@ static void *bmw_UVEdgeWalker_yield(BMWalker *walker)
static void *bmw_UVEdgeWalker_step(BMWalker *walker)
{
- BMwUVEdgeWalker *lwalk = BMW_current_state(walker);
+ const int type = walker->bm->ldata.layers[walker->layer].type;
+ BMwUVEdgeWalker *lwalk, owalk;
BMLoop *l, *l2, *l3, *nl, *cl;
BMIter liter;
void *d1, *d2;
- int i, j, rlen, type;
+ int i, j, rlen;
+
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
l = lwalk->l;
nl = l->next;
- type = walker->bm->ldata.layers[walker->layer].type;
-
- BMW_state_remove(walker);
if (!bmw_mask_check_edge(walker, l->e)) {
return l;
@@ -1004,7 +1023,7 @@ static void *bmw_UVEdgeWalker_step(BMWalker *walker)
rlen = BM_edge_face_count(l2->e);
for (j = 0; j < rlen; j++) {
- if (BLI_ghash_haskey(walker->visithash, l2)) {
+ if (BLI_gset_haskey(walker->visit_set, l2)) {
continue;
}
@@ -1022,7 +1041,7 @@ static void *bmw_UVEdgeWalker_step(BMWalker *walker)
continue;
lwalk = BMW_state_add(walker);
- BLI_ghash_insert(walker->visithash, l2, NULL);
+ BLI_gset_insert(walker->visit_set, l2);
lwalk->l = l2;
diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c
index 22b686db64e..bd20e384234 100644
--- a/source/blender/bmesh/operators/bmo_beautify.c
+++ b/source/blender/bmesh/operators/bmo_beautify.c
@@ -28,7 +28,7 @@
*
* In principle this is very simple however there is the possibility of
* going into an eternal loop where edges keep rotating.
- * To avoid this - each edge stores a hash of it previous
+ * To avoid this - each edge stores a set of it previous
* states so as not to rotate back.
*
* TODO
@@ -43,10 +43,13 @@
#include "bmesh.h"
#include "intern/bmesh_operators_private.h"
+#include "BLI_strict_flags.h"
+
// #define DEBUG_TIME
#ifdef DEBUG_TIME
# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
#endif
enum {
@@ -54,14 +57,14 @@ enum {
};
/* -------------------------------------------------------------------- */
-/* GHash for edge rotation */
+/* GSet for edge rotation */
typedef struct EdRotState {
int v1, v2; /* edge vert, small -> large */
int f1, f2; /* face vert, small -> large */
} EdRotState;
-static unsigned int erot_ghashutil_hash(const void *ptr)
+static unsigned int erot_gsetutil_hash(const void *ptr)
{
const EdRotState *e_state = (const EdRotState *)ptr;
unsigned int
@@ -71,7 +74,7 @@ static unsigned int erot_ghashutil_hash(const void *ptr)
hash ^= BLI_ghashutil_inthash(SET_INT_IN_POINTER(e_state->f2));
return hash;
}
-static int erot_ghashutil_cmp(const void *a, const void *b)
+static int erot_gsetutil_cmp(const void *a, const void *b)
{
const EdRotState *e_state_a = (const EdRotState *)a;
const EdRotState *e_state_b = (const EdRotState *)b;
@@ -86,9 +89,9 @@ static int erot_ghashutil_cmp(const void *a, const void *b)
else return 0;
}
-static GHash *erot_ghash_new(void)
+static GSet *erot_gset_new(void)
{
- return BLI_ghash_new(erot_ghashutil_hash, erot_ghashutil_cmp, __func__);
+ return BLI_gset_new(erot_gsetutil_hash, erot_gsetutil_cmp, __func__);
}
/* ensure v0 is smaller */
@@ -133,7 +136,8 @@ static void erot_state_alternate(const BMEdge *e, EdRotState *e_state)
/**
* \return a negative value means the edge can be rotated.
*/
-static float bm_edge_calc_rotate_beauty(const BMEdge *e, const int flag)
+static float bm_edge_calc_rotate_beauty__area(
+ const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
/* not a loop (only to be able to break out) */
do {
@@ -141,28 +145,10 @@ static float bm_edge_calc_rotate_beauty(const BMEdge *e, const int flag)
/* first get the 2d values */
{
- const float *v1, *v2, *v3, *v4;
bool is_zero_a, is_zero_b;
float no[3];
float axis_mat[3][3];
- v1 = e->l->prev->v->co; /* first face co */
- v2 = e->l->v->co; /* e->v1 or e->v2*/
- v3 = e->l->radial_next->prev->v->co; /* second face co */
- v4 = e->l->next->v->co; /* e->v1 or e->v2*/
-
- if (flag & VERT_RESTRICT_TAG) {
- BMVert *v_a = e->l->prev->v, *v_b = e->l->radial_next->prev->v;
- if (BM_elem_flag_test(v_a, BM_ELEM_TAG) == BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
- break;
- }
- }
-
- if (UNLIKELY(v1 == v3)) {
- // printf("This should never happen, but does sometimes!\n");
- break;
- }
-
// printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
BLI_assert((ELEM3(v1, v2, v3, v4) == false) &&
(ELEM3(v2, v1, v3, v4) == false) &&
@@ -204,28 +190,101 @@ static float bm_edge_calc_rotate_beauty(const BMEdge *e, const int flag)
// printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
if (is_quad_convex_v2(v1_xy, v2_xy, v3_xy, v4_xy)) {
- float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
- /* testing rule:
- * the area divided by the total edge lengths
- */
- len1 = len_v2v2(v1_xy, v2_xy);
- len2 = len_v2v2(v2_xy, v3_xy);
- len3 = len_v2v2(v3_xy, v4_xy);
- len4 = len_v2v2(v4_xy, v1_xy);
- len5 = len_v2v2(v1_xy, v3_xy);
- len6 = len_v2v2(v2_xy, v4_xy);
-
- opp1 = area_tri_v2(v1_xy, v2_xy, v3_xy);
- opp2 = area_tri_v2(v1_xy, v3_xy, v4_xy);
-
- fac1 = opp1 / (len1 + len2 + len5) + opp2 / (len3 + len4 + len5);
-
- opp1 = area_tri_v2(v2_xy, v3_xy, v4_xy);
- opp2 = area_tri_v2(v2_xy, v4_xy, v1_xy);
-
- fac2 = opp1 / (len2 + len3 + len6) + opp2 / (len4 + len1 + len6);
- /* negative number if we're OK */
- return fac2 - fac1;
+ /* testing rule: the area divided by the perimeter,
+ * check if (1-3) beats the existing (2-4) edge rotation */
+ float area_a, area_b;
+ float prim_a, prim_b;
+ float fac_24, fac_13;
+
+ float len_12, len_23, len_34, len_41, len_24, len_13;
+
+ /* edges around the quad */
+ len_12 = len_v2v2(v1_xy, v2_xy);
+ len_23 = len_v2v2(v2_xy, v3_xy);
+ len_34 = len_v2v2(v3_xy, v4_xy);
+ len_41 = len_v2v2(v4_xy, v1_xy);
+ /* edges crossing the quad interior */
+ len_13 = len_v2v2(v1_xy, v3_xy);
+ len_24 = len_v2v2(v2_xy, v4_xy);
+
+ /* edge (2-4), current state */
+ area_a = area_tri_v2(v2_xy, v3_xy, v4_xy);
+ area_b = area_tri_v2(v2_xy, v4_xy, v1_xy);
+ prim_a = len_23 + len_34 + len_24;
+ prim_b = len_24 + len_41 + len_12;
+ fac_24 = (area_a / prim_a) + (area_b / prim_b);
+
+ /* edge (1-3), new state */
+ area_a = area_tri_v2(v1_xy, v2_xy, v3_xy);
+ area_b = area_tri_v2(v1_xy, v3_xy, v4_xy);
+ prim_a = len_12 + len_23 + len_13;
+ prim_b = len_34 + len_41 + len_13;
+ fac_13 = (area_a / prim_a) + (area_b / prim_b);
+
+ /* negative number if (1-3) is an improved state */
+ return fac_24 - fac_13;
+ }
+ } while (false);
+
+ return FLT_MAX;
+}
+
+static float bm_edge_calc_rotate_beauty__angle(
+ const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ /* not a loop (only to be able to break out) */
+ do {
+ float no_a[3], no_b[3];
+ float angle_24, angle_13;
+
+ /* edge (2-4), current state */
+ normal_tri_v3(no_a, v2, v3, v4);
+ normal_tri_v3(no_b, v2, v4, v1);
+ angle_24 = angle_normalized_v3v3(no_a, no_b);
+
+ /* edge (1-3), new state */
+ /* only check new state for degenerate outcome */
+ if ((normal_tri_v3(no_a, v1, v2, v3) == 0.0f) ||
+ (normal_tri_v3(no_b, v1, v3, v4) == 0.0f))
+ {
+ break;
+ }
+ angle_13 = angle_normalized_v3v3(no_a, no_b);
+
+ return angle_13 - angle_24;
+ } while (false);
+
+ return FLT_MAX;
+}
+
+static float bm_edge_calc_rotate_beauty(const BMEdge *e, const short flag, const short method)
+{
+ /* not a loop (only to be able to break out) */
+ do {
+ const float *v1, *v2, *v3, *v4;
+
+ v1 = e->l->prev->v->co; /* first face co */
+ v2 = e->l->v->co; /* e->v1 or e->v2*/
+ v3 = e->l->radial_next->prev->v->co; /* second face co */
+ v4 = e->l->next->v->co; /* e->v1 or e->v2*/
+
+ if (flag & VERT_RESTRICT_TAG) {
+ BMVert *v_a = e->l->prev->v, *v_b = e->l->radial_next->prev->v;
+ if (BM_elem_flag_test(v_a, BM_ELEM_TAG) == BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
+ break;
+ }
+ }
+
+ if (UNLIKELY(v1 == v3)) {
+ // printf("This should never happen, but does sometimes!\n");
+ break;
+ }
+
+ switch (method) {
+ case 0:
+ return bm_edge_calc_rotate_beauty__area(v1, v2, v3, v4);
+ default:
+ return bm_edge_calc_rotate_beauty__angle(v1, v2, v3, v4);
}
} while (false);
@@ -236,12 +295,12 @@ static float bm_edge_calc_rotate_beauty(const BMEdge *e, const int flag)
/* Update the edge cost of rotation in the heap */
/* recalc an edge in the heap (surrounding geometry has changed) */
-static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GHash **edge_state_arr,
- const int flag)
+static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
+ const short flag, const short method)
{
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
const int i = BM_elem_index_get(e);
- GHash *e_state_hash = edge_state_arr[i];
+ GSet *e_state_set = edge_state_arr[i];
if (eheap_table[i]) {
BLI_heap_remove(eheap, eheap_table[i]);
@@ -254,10 +313,10 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode *
// BMO_elem_flag_test(bm, e->l->radial_next->f, FACE_MARK));
/* check we're not moving back into a state we have been in before */
- if (e_state_hash != NULL) {
+ if (e_state_set != NULL) {
EdRotState e_state_alt;
erot_state_alternate(e, &e_state_alt);
- if (BLI_ghash_haskey(e_state_hash, (void *)&e_state_alt)) {
+ if (BLI_gset_haskey(e_state_set, (void *)&e_state_alt)) {
// printf(" skipping, we already have this state\n");
return;
}
@@ -265,7 +324,7 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode *
{
/* recalculate edge */
- const float cost = bm_edge_calc_rotate_beauty(e, flag);
+ const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
if (cost < 0.0f) {
eheap_table[i] = BLI_heap_insert(eheap, cost, e);
}
@@ -277,19 +336,19 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode *
}
/* we have rotated an edge, tag other edges and clear this one */
-static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GHash **edge_state_arr,
- const int flag)
+static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
+ const short flag, const short method)
{
BMLoop *l;
BLI_assert(e->l->f->len == 3 &&
e->l->radial_next->f->len == 3);
l = e->l;
- bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr, flag);
- bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr, flag);
+ bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr, flag, method);
+ bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr, flag, method);
l = l->radial_next;
- bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr, flag);
- bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr, flag);
+ bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr, flag, method);
+ bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr, flag, method);
}
/* -------------------------------------------------------------------- */
@@ -303,12 +362,12 @@ static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_
* have their index values set according to their position in the array.
*/
static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len,
- const int flag)
+ const short flag, const short method)
{
Heap *eheap; /* edge heap */
HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
- GHash **edge_state_arr = MEM_callocN(edge_array_len * sizeof(GHash *), __func__);
+ GSet **edge_state_arr = MEM_callocN((size_t)edge_array_len * sizeof(GSet *), __func__);
BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 512, 512, BLI_MEMPOOL_SYSMALLOC);
int i;
@@ -316,13 +375,13 @@ static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge
TIMEIT_START(beautify_fill);
#endif
- eheap = BLI_heap_new_ex(edge_array_len);
- eheap_table = MEM_mallocN(sizeof(HeapNode *) * edge_array_len, __func__);
+ eheap = BLI_heap_new_ex((unsigned int)edge_array_len);
+ eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__);
/* build heap */
for (i = 0; i < edge_array_len; i++) {
BMEdge *e = edge_array[i];
- const float cost = bm_edge_calc_rotate_beauty(e, flag);
+ const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
if (cost < 0.0f) {
eheap_table[i] = BLI_heap_insert(eheap, cost, e);
}
@@ -338,18 +397,18 @@ static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge
e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
if (LIKELY(e)) {
- GHash *e_state_hash = edge_state_arr[i];
+ GSet *e_state_set = edge_state_arr[i];
- /* add the new state into the hash so we don't move into this state again
+ /* add the new state into the set so we don't move into this state again
* note: we could add the previous state too but this isn't essential)
* for avoiding eternal loops */
EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
erot_state_current(e, e_state);
- if (UNLIKELY(e_state_hash == NULL)) {
- edge_state_arr[i] = e_state_hash = erot_ghash_new(); /* store previous state */
+ if (UNLIKELY(e_state_set == NULL)) {
+ edge_state_arr[i] = e_state_set = erot_gset_new(); /* store previous state */
}
- BLI_assert(BLI_ghash_haskey(e_state_hash, (void *)e_state) == false);
- BLI_ghash_insert(e_state_hash, e_state, NULL);
+ BLI_assert(BLI_gset_haskey(e_state_set, (void *)e_state) == false);
+ BLI_gset_insert(e_state_set, e_state);
// printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));
@@ -359,7 +418,7 @@ static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge
BM_elem_index_set(e, i);
/* recalculate faces connected on the heap */
- bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr, flag);
+ bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr, flag, method);
/* update flags */
BMO_elem_flag_enable(bm, e, ELE_NEW);
@@ -373,7 +432,7 @@ static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge
for (i = 0; i < edge_array_len; i++) {
if (edge_state_arr[i]) {
- BLI_ghash_free(edge_state_arr[i], NULL, NULL);
+ BLI_gset_free(edge_state_arr[i], NULL);
}
}
@@ -393,11 +452,11 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
BMFace *f;
BMEdge *e;
const bool use_restrict_tag = BMO_slot_bool_get(op->slots_in, "use_restrict_tag");
- const int flag = (use_restrict_tag ? VERT_RESTRICT_TAG : 0);
+ const short flag = (use_restrict_tag ? VERT_RESTRICT_TAG : 0);
+ const short method = (short)BMO_slot_int_get(op->slots_in, "method");
BMEdge **edge_array;
int edge_array_len = 0;
-
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
if (f->len == 3) {
BMO_elem_flag_enable(bm, f, FACE_MARK);
@@ -409,7 +468,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
}
/* will over alloc if some edges can't be rotated */
- edge_array = MEM_mallocN(sizeof(*edge_array) * BMO_slot_buffer_count(op->slots_in, "edges"), __func__);
+ edge_array = MEM_mallocN(sizeof(*edge_array) * (size_t)BMO_slot_buffer_count(op->slots_in, "edges"), __func__);
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
@@ -427,7 +486,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
}
bm->elem_index_dirty |= BM_EDGE;
- bm_mesh_beautify_fill(bm, edge_array, edge_array_len, flag);
+ bm_mesh_beautify_fill(bm, edge_array, edge_array_len, flag, method);
MEM_freeN(edge_array);
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index dc06b0b4f13..eef470e0d85 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -29,6 +29,7 @@
#include "BLI_utildefines.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h" /* own include */
diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c
new file mode 100644
index 00000000000..74cb9d67e88
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_bisect_plane.c
@@ -0,0 +1,112 @@
+/*
+ * ***** 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):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_bisect_plane.c
+ * \ingroup bmesh
+ *
+ * Wrapper around #BM_mesh_bisect_plane
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define ELE_NEW 1
+#define ELE_INPUT 2
+
+void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
+{
+ const float dist = BMO_slot_float_get(op->slots_in, "dist");
+ const bool use_snap_center = BMO_slot_bool_get(op->slots_in, "use_snap_center");
+ const bool clear_outer = BMO_slot_bool_get(op->slots_in, "clear_outer");
+ const bool clear_inner = BMO_slot_bool_get(op->slots_in, "clear_inner");
+
+ float plane_co[3];
+ float plane_no[3];
+ float plane[4];
+
+ BMO_slot_vec_get(op->slots_in, "plane_co", plane_co);
+ BMO_slot_vec_get(op->slots_in, "plane_no", plane_no);
+
+ if (is_zero_v3(plane_no)) {
+ BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Zero normal given");
+ return;
+ }
+
+ plane_from_point_normal_v3(plane, plane_co, plane_no);
+
+ /* tag geometry to bisect */
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, ELE_INPUT);
+
+
+ BM_mesh_bisect_plane(bm, plane, use_snap_center, true,
+ ELE_NEW, dist);
+
+
+ if (clear_outer || clear_inner) {
+ /* Use an array of vertices because 'geom' contains both vers and edges that may use them.
+ * Removing a vert may remove and edge which is later checked by BMO_ITER.
+ * over-alloc the total possible vert count */
+ const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_count(op->slots_in, "geom"));
+ BMVert **vert_arr = MEM_mallocN(sizeof(*vert_arr) * (size_t)vert_arr_max, __func__);
+ BMOIter siter;
+ BMVert *v;
+ float plane_inner[4];
+ float plane_outer[4];
+
+ STACK_DECLARE(vert_arr);
+
+ copy_v3_v3(plane_outer, plane);
+ copy_v3_v3(plane_inner, plane);
+ plane_outer[3] = plane[3] - dist;
+ plane_inner[3] = plane[3] + dist;
+
+ STACK_INIT(vert_arr);
+
+ BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
+ if ((clear_outer && plane_point_side_v3(plane_outer, v->co) > 0.0f) ||
+ (clear_inner && plane_point_side_v3(plane_inner, v->co) < 0.0f))
+ {
+ STACK_PUSH(vert_arr, v);
+ }
+ }
+
+ while ((v = STACK_POP(vert_arr))) {
+ BM_vert_kill(bm, v);
+ }
+
+ STACK_FREE(vert_arr);
+ MEM_freeN(vert_arr);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_NEW);
+}
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index f63e742d8ba..9dfbf951fc0 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -121,7 +121,7 @@ static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct B
}
if (el_b_best) {
- BLI_rotatelist(lb_b, el_b_best);
+ BLI_rotatelist_first(lb_b, el_b_best);
}
}
@@ -273,9 +273,8 @@ static void bridge_loop_pair(BMesh *bm,
if (twist_offset != 0) {
const int len_b = BM_edgeloop_length_get(el_store_b);
ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
- const int offset = twist_offset % len_b;
- LinkData *el_b = BLI_rfindlink(lb_b, (offset < 0) ? (offset + len_b) : offset);
- BLI_rotatelist(lb_b, el_b);
+ LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b));
+ BLI_rotatelist_first(lb_b, el_b);
}
}
@@ -343,7 +342,7 @@ static void bridge_loop_pair(BMesh *bm,
BMVert *v_arr[4] = {v_a, v_b, v_b_next, v_a_next};
if (BM_face_exists(v_arr, 4, &f) == false) {
/* copy if loop data if its is missing on one ring */
- f = BM_face_create_ngon_verts(bm, v_arr, 4, 0, false, true);
+ f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true);
l_iter = BM_FACE_FIRST_LOOP(f);
if (l_b) BM_elem_attrs_copy(bm, bm, l_b, l_iter); l_iter = l_iter->next;
@@ -356,7 +355,7 @@ static void bridge_loop_pair(BMesh *bm,
BMVert *v_arr[3] = {v_a, v_b, v_a_next};
if (BM_face_exists(v_arr, 3, &f) == false) {
/* fan-fill a triangle */
- f = BM_face_create_ngon_verts(bm, v_arr, 3, 0, false, true);
+ f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true);
l_iter = BM_FACE_FIRST_LOOP(f);
if (l_b) BM_elem_attrs_copy(bm, bm, l_b, l_iter); l_iter = l_iter->next;
@@ -422,8 +421,8 @@ static void bridge_loop_pair(BMesh *bm,
BMO_op_initf(bm, &op_sub, 0,
- "beautify_fill faces=%hf edges=ae use_restrict_tag=%b",
- BM_ELEM_TAG, true);
+ "beautify_fill faces=%hf edges=ae use_restrict_tag=%b method=%i",
+ BM_ELEM_TAG, true, 1);
if (use_edgeout) {
BMOIter siter;
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index c718cac4bd6..b3a42ba533e 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -31,6 +31,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
+#include "BLI_linklist_stack.h"
#include "bmesh.h"
@@ -117,10 +118,9 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
BMIter iter;
BMVert *v;
BMFace *f;
- BMFace **faces = MEM_mallocN(sizeof(BMFace *) * bm->totface, __func__);
- STACK_DECLARE(faces);
+ BLI_LINKSTACK_DECLARE(faces, BMFace *);
- STACK_INIT(faces);
+ BLI_LINKSTACK_INIT(faces);
/* add all faces connected to verts */
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
@@ -129,20 +129,20 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
if (!BMO_elem_flag_test(bm, f, FACE_TAG)) {
BMO_elem_flag_enable(bm, f, FACE_TAG);
if (f->len > 3) {
- STACK_PUSH(faces, f);
+ BLI_LINKSTACK_PUSH(faces, f);
}
}
}
}
/* connect faces */
- while ((f = STACK_POP(faces))) {
+ while ((f = BLI_LINKSTACK_POP(faces))) {
if (bm_face_connect_verts(bm, f) == -1) {
BMO_error_raise(bm, op, BMERR_CONNECTVERT_FAILED, NULL);
}
}
- MEM_freeN(faces);
+ BLI_LINKSTACK_FREE(faces);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
}
diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
index 6d30b327a6c..61085596acc 100644
--- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c
+++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
@@ -31,6 +31,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
+#include "BLI_linklist_stack.h"
#include "bmesh.h"
@@ -179,9 +180,7 @@ void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op)
BMOIter siter;
BMFace *f;
int totface = 0, totloop = 0;
- int tottris;
- BMFace **fstack;
- STACK_DECLARE(fstack);
+ BLI_LINKSTACK_DECLARE(fstack, BMFace *);
const float angle_limit = BMO_slot_float_get(op->slots_in, "angle_limit");
@@ -197,32 +196,28 @@ void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op)
return;
}
- /* over alloc, if we split every face */
- tottris = poly_to_tri_count(totface, totloop);
- fstack = MEM_mallocN(sizeof(BMFace *) * tottris, __func__);
-
- STACK_INIT(fstack);
+ BLI_LINKSTACK_INIT(fstack);
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
if (f->len > 3) {
- STACK_PUSH(fstack, f);
+ BLI_LINKSTACK_PUSH(fstack, f);
}
}
- while ((f = STACK_POP(fstack))) {
+ while ((f = BLI_LINKSTACK_POP(fstack))) {
BMFace *f_pair[2];
if (bm_face_split_by_angle(bm, f, f_pair, angle_limit)) {
int j;
for (j = 0; j < 2; j++) {
BM_face_normal_update(f_pair[j]);
if (f_pair[j]->len > 3) {
- STACK_PUSH(fstack, f_pair[j]);
+ BLI_LINKSTACK_PUSH(fstack, f_pair[j]);
}
}
}
}
- MEM_freeN(fstack);
+ BLI_LINKSTACK_FREE(fstack);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index 64d0ec6ac27..dd814fa8bfb 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -145,6 +145,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* EdgeNet Create */
if (tote != 0) {
/* call edgenet prepare op so additional face creation cases work */
+
BMOperator op_sub;
BMO_op_initf(bm, &op_sub, op->flag, "edgenet_prepare edges=%fe", ELE_NEW);
BMO_op_exec(bm, &op_sub);
@@ -152,8 +153,8 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMO_op_finish(bm, &op_sub);
BMO_op_initf(bm, &op_sub, op->flag,
- "edgenet_fill edges=%fe use_fill_check=%b mat_nr=%i use_smooth=%b",
- ELE_NEW, true, mat_nr, use_smooth);
+ "edgenet_fill edges=%fe mat_nr=%i use_smooth=%b sides=%i",
+ ELE_NEW, mat_nr, use_smooth, 10000);
BMO_op_exec(bm, &op_sub);
@@ -181,7 +182,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* if we dissolved anything, then return */
if (BMO_slot_buffer_count(op_sub.slots_out, "region.out")) {
BMO_slot_copy(&op_sub, slots_out, "region.out",
- op, slots_out, "faces.out");
+ op, slots_out, "faces.out");
BMO_op_finish(bm, &op_sub);
return;
}
@@ -282,7 +283,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMFace *f;
BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv);
- f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, BM_CREATE_NO_DOUBLE);
+ f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, NULL, BM_CREATE_NO_DOUBLE);
if (f) {
BMO_elem_flag_enable(bm, f, ELE_OUT);
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index d633182de42..cf36e88ea98 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -32,17 +32,26 @@
#include "BLI_math.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
+
#include "intern/bmesh_operators_private.h"
+/* ***_ISGC: mark for garbage-collection */
+
#define FACE_MARK 1
#define FACE_ORIG 2
#define FACE_NEW 4
+
#define EDGE_MARK 1
#define EDGE_TAG 2
+#define EDGE_ISGC 8
#define VERT_MARK 1
#define VERT_TAG 2
+#define VERT_ISGC 8
+
+
static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
{
@@ -230,14 +239,12 @@ cleanup:
void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
{
- /* might want to make this an option or mode - campbell */
-
/* BMOperator fop; */
BMFace *act_face = bm->act_face;
BMOIter eiter;
- BMEdge *e;
- BMIter viter;
- BMVert *v;
+ BMIter iter;
+ BMEdge *e, *e_next;
+ BMVert *v, *v_next;
const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
@@ -245,10 +252,10 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
if (use_face_split) {
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_TAG);
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- BMIter iter;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMIter itersub;
int untag_count = 0;
- BM_ITER_ELEM(e, &iter, v, BM_EDGES_OF_VERT) {
+ BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
if (!BMO_elem_flag_test(bm, e, EDGE_TAG)) {
untag_count++;
}
@@ -264,22 +271,34 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
}
if (use_verts) {
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
BMO_elem_flag_set(bm, v, VERT_MARK, (BM_vert_edge_count(v) != 2));
}
}
+ /* tag all verts/edges connected to faces */
BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
- BMFace *fa, *fb;
+ BMFace *f_pair[2];
+ if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
+ unsigned int j;
+ for (j = 0; j < 2; j++) {
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]);
+ do {
+ BMO_elem_flag_enable(bm, l_iter->v, VERT_ISGC);
+ BMO_elem_flag_enable(bm, l_iter->e, EDGE_ISGC);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+ BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
+ BMFace *fa, *fb;
if (BM_edge_face_pair(e, &fa, &fb)) {
BMFace *f_new;
/* join faces */
-
- /* BMESH_TODO - check on delaying edge removal since we may end up removing more than
- * one edge, and later reference a removed edge */
- f_new = BM_faces_join_pair(bm, fa, fb, e, true);
+ f_new = BM_faces_join_pair(bm, fa, fb, e, false);
if (f_new) {
/* maintain active face */
@@ -290,8 +309,23 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
}
}
+ /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on)
+ * so do this in a separate pass instead. */
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ if ((e->l == NULL) && BMO_elem_flag_test(bm, e, EDGE_ISGC)) {
+ BM_edge_kill(bm, e);
+ }
+ }
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if ((v->e == NULL) && BMO_elem_flag_test(bm, v, VERT_ISGC)) {
+ BM_vert_kill(bm, v);
+ }
+ }
+ /* done with cleanup */
+
+
if (use_verts) {
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (BM_vert_edge_count(v) == 2) {
BM_vert_collapse_edge(bm, v->e, v, true);
@@ -310,21 +344,21 @@ static bool test_extra_verts(BMesh *bm, BMVert *v)
/* test faces around verts for verts that would be wrongly killed
* by dissolve faces. */
- BM_ITER_ELEM(f, &fiter, v, BM_FACES_OF_VERT) {
- BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
/* if an edge around a vert is a boundary edge,
* then dissolve faces won't destroy it.
* also if it forms a boundary with one
* of the face region */
bool found = false;
- BM_ITER_ELEM(e, &eiter, l->v, BM_EDGES_OF_VERT) {
+ BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) {
BMFace *f_iter;
if (BM_edge_is_boundary(e)) {
found = true;
}
else {
- BM_ITER_ELEM(f_iter, &fiter_sub, e, BM_FACES_OF_EDGE) {
+ BM_ITER_ELEM (f_iter, &fiter_sub, e, BM_FACES_OF_EDGE) {
if (!BMO_elem_flag_test(bm, f_iter, FACE_MARK)) {
found = true;
break;
@@ -347,7 +381,7 @@ static bool test_extra_verts(BMesh *bm, BMVert *v)
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
{
BMIter iter, fiter;
- BMVert *v;
+ BMVert *v, *v_next;
BMFace *f;
const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
@@ -359,7 +393,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
bm_face_split(bm, VERT_MARK);
}
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
/* check if it's a two-valence ver */
if (BM_vert_edge_count(v) == 2) {
@@ -407,7 +441,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
}
/* clean up any remainin */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (!BM_vert_dissolve(bm, v)) {
BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL);
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 1dc7b0a414d..bd2485b92fb 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -46,23 +46,27 @@
*
* Copy an existing vertex from one bmesh to another.
*/
-static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *target_mesh, GHash *vhash)
+static BMVert *bmo_vert_copy(BMOperator *op,
+ BMOpSlot *slot_vertmap_out,
+ BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash)
{
- BMVert *target_vertex = NULL;
+ BMVert *v_dst;
/* Create a new vertex */
- target_vertex = BM_vert_create(target_mesh, source_vertex->co, NULL, BM_CREATE_SKIP_CD);
-
+ v_dst = BM_vert_create(bm_dst, v_src->co, NULL, BM_CREATE_SKIP_CD);
+ BMO_slot_map_elem_insert(op, slot_vertmap_out, v_src, v_dst);
+ BMO_slot_map_elem_insert(op, slot_vertmap_out, v_dst, v_src);
+
/* Insert new vertex into the vert hash */
- BLI_ghash_insert(vhash, source_vertex, target_vertex);
-
+ BLI_ghash_insert(vhash, v_src, v_dst);
+
/* Copy attributes */
- BM_elem_attrs_copy(source_mesh, target_mesh, source_vertex, target_vertex);
-
- /* Set internal op flags */
- BMO_elem_flag_enable(target_mesh, target_vertex, DUPE_NEW);
+ BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
+
+ /* Mark the vert for output */
+ BMO_elem_flag_enable(bm_dst, v_dst, DUPE_NEW);
- return target_vertex;
+ return v_dst;
}
/**
@@ -70,55 +74,58 @@ static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *tar
*
* Copy an existing edge from one bmesh to another.
*/
-static BMEdge *copy_edge(BMOperator *op,
- BMOpSlot *slot_boundarymap_out,
- BMesh *source_mesh,
- BMEdge *source_edge, BMesh *target_mesh,
- GHash *vhash, GHash *ehash)
+static BMEdge *bmo_edge_copy(BMOperator *op,
+ BMOpSlot *slot_edgemap_out,
+ BMOpSlot *slot_boundarymap_out,
+ BMesh *bm_dst, BMesh *bm_src,
+ BMEdge *e_src,
+ GHash *vhash, GHash *ehash)
{
- BMEdge *target_edge = NULL;
- BMVert *target_vert1, *target_vert2;
- BMFace *face;
- BMIter fiter;
- int rlen;
+ BMEdge *e_dst;
+ BMVert *e_dst_v1, *e_dst_v2;
+ unsigned int rlen;
/* see if any of the neighboring faces are
* not being duplicated. in that case,
* add it to the new/old map. */
+ /* lookup edge */
rlen = 0;
- for (face = BM_iter_new(&fiter, source_mesh, BM_FACES_OF_EDGE, source_edge);
- face;
- face = BM_iter_step(&fiter))
- {
- if (BMO_elem_flag_test(source_mesh, face, DUPE_INPUT)) {
- rlen++;
- }
+ if (e_src->l) {
+ BMLoop *l_iter_src, *l_first_src;
+ l_iter_src = l_first_src = e_src->l;
+ do {
+ if (BMO_elem_flag_test(bm_src, l_iter_src->f, DUPE_INPUT)) {
+ rlen++;
+ }
+ } while ((l_iter_src = l_iter_src->radial_next) != l_first_src);
}
/* Lookup v1 and v2 */
- target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
- target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
+ e_dst_v1 = BLI_ghash_lookup(vhash, e_src->v1);
+ e_dst_v2 = BLI_ghash_lookup(vhash, e_src->v2);
/* Create a new edge */
- target_edge = BM_edge_create(target_mesh, target_vert1, target_vert2, NULL, BM_CREATE_SKIP_CD);
-
+ e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, NULL, BM_CREATE_SKIP_CD);
+ BMO_slot_map_elem_insert(op, slot_edgemap_out, e_src, e_dst);
+ BMO_slot_map_elem_insert(op, slot_edgemap_out, e_dst, e_src);
+
/* add to new/old edge map if necassary */
if (rlen < 2) {
/* not sure what non-manifold cases of greater then three
* radial should do. */
- BMO_slot_map_elem_insert(op, slot_boundarymap_out, source_edge, target_edge);
+ BMO_slot_map_elem_insert(op, slot_boundarymap_out, e_src, e_dst);
}
/* Insert new edge into the edge hash */
- BLI_ghash_insert(ehash, source_edge, target_edge);
-
+ BLI_ghash_insert(ehash, e_src, e_dst);
+
/* Copy attributes */
- BM_elem_attrs_copy(source_mesh, target_mesh, source_edge, target_edge);
-
- /* Set internal op flags */
- BMO_elem_flag_enable(target_mesh, target_edge, DUPE_NEW);
+ BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst);
+
+ /* Mark the edge for output */
+ BMO_elem_flag_enable(bm_dst, e_dst, DUPE_NEW);
- return target_edge;
+ return e_dst;
}
/**
@@ -126,56 +133,49 @@ static BMEdge *copy_edge(BMOperator *op,
*
* Copy an existing face from one bmesh to another.
*/
-static BMFace *copy_face(BMOperator *op,
- BMOpSlot *slot_facemap_out,
- BMesh *source_mesh,
- BMFace *source_face, BMesh *target_mesh,
- GHash *vhash, GHash *ehash)
+static BMFace *bmo_face_copy(BMOperator *op,
+ BMOpSlot *slot_facemap_out,
+ BMesh *bm_dst, BMesh *bm_src,
+ BMFace *f_src,
+ GHash *vhash, GHash *ehash)
{
- /* BMVert *target_vert1, *target_vert2; */ /* UNUSED */
- BMVert **vtar = BLI_array_alloca(vtar, source_face->len);
- BMEdge **edar = BLI_array_alloca(edar, source_face->len);
- BMLoop *source_loop, *target_loop;
- BMFace *target_face = NULL;
- BMIter iter, iter2;
+ BMFace *f_dst;
+ BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
+ BMEdge **edar = BLI_array_alloca(edar, f_src->len);
+ BMLoop *l_iter_src, *l_iter_dst, *l_first_src;
int i;
-
- /* lookup the first and second vert */
-#if 0 /* UNUSED */
- target_vert1 = BLI_ghash_lookup(vhash, BM_iter_new(&iter, source_mesh, BM_VERTS_OF_FACE, source_face));
- target_vert2 = BLI_ghash_lookup(vhash, BM_iter_step(&iter));
-#else
- BM_iter_new(&iter, source_mesh, BM_VERTS_OF_FACE, source_face);
- BM_iter_step(&iter);
-#endif
+
+ l_first_src = BM_FACE_FIRST_LOOP(f_src);
/* lookup edge */
- BM_ITER_ELEM_INDEX (source_loop, &iter, source_face, BM_LOOPS_OF_FACE, i) {
- vtar[i] = BLI_ghash_lookup(vhash, source_loop->v);
- edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
- }
+ l_iter_src = l_first_src;
+ i = 0;
+ do {
+ vtar[i] = BLI_ghash_lookup(vhash, l_iter_src->v);
+ edar[i] = BLI_ghash_lookup(ehash, l_iter_src->e);
+ i++;
+ } while ((l_iter_src = l_iter_src->next) != l_first_src);
/* create new face */
- target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, BM_CREATE_SKIP_CD);
- BMO_slot_map_elem_insert(op, slot_facemap_out, source_face, target_face);
- BMO_slot_map_elem_insert(op, slot_facemap_out, target_face, source_face);
-
- BM_elem_attrs_copy(source_mesh, target_mesh, source_face, target_face);
+ f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, NULL, BM_CREATE_SKIP_CD);
+ BMO_slot_map_elem_insert(op, slot_facemap_out, f_src, f_dst);
+ BMO_slot_map_elem_insert(op, slot_facemap_out, f_dst, f_src);
- /* mark the face for output */
- BMO_elem_flag_enable(target_mesh, target_face, DUPE_NEW);
+ /* Copy attributes */
+ BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
/* copy per-loop custom data */
- BM_ITER_ELEM (source_loop, &iter, source_face, BM_LOOPS_OF_FACE) {
- BM_ITER_ELEM (target_loop, &iter2, target_face, BM_LOOPS_OF_FACE) {
- if (BLI_ghash_lookup(vhash, source_loop->v) == target_loop->v) {
- BM_elem_attrs_copy(source_mesh, target_mesh, source_loop, target_loop);
- break;
- }
- }
- }
+ l_iter_src = l_first_src;
+ l_iter_dst = BM_FACE_FIRST_LOOP(f_dst);
+ do {
+ BM_elem_attrs_copy(bm_src, bm_dst, l_iter_src, l_iter_dst);
+ } while ((l_iter_dst = l_iter_dst->next),
+ (l_iter_src = l_iter_src->next) != l_first_src);
+
+ /* Mark the face for output */
+ BMO_elem_flag_enable(bm_dst, f_dst, DUPE_NEW);
- return target_face;
+ return f_dst;
}
/**
@@ -183,7 +183,7 @@ static BMFace *copy_face(BMOperator *op,
*
* Internal Copy function.
*/
-static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
+static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
{
BMVert *v = NULL, *v2;
@@ -194,9 +194,12 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
GHash *vhash, *ehash;
BMOpSlot *slot_boundary_map_out = BMO_slot_get(op->slots_out, "boundary_map.out");
- BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out");
BMOpSlot *slot_isovert_map_out = BMO_slot_get(op->slots_out, "isovert_map.out");
+ BMOpSlot *slot_vert_map_out = BMO_slot_get(op->slots_out, "vert_map.out");
+ BMOpSlot *slot_edge_map_out = BMO_slot_get(op->slots_out, "edge_map.out");
+ BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out");
+
/* initialize pointer hashes */
vhash = BLI_ghash_ptr_new("bmesh dupeops v");
ehash = BLI_ghash_ptr_new("bmesh dupeops e");
@@ -209,7 +212,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
BMIter iter;
bool isolated = true;
- v2 = copy_vertex(bm_src, v, bm_dst, vhash);
+ v2 = bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) {
@@ -242,15 +245,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
{
/* make sure that verts are copied */
if (!BMO_elem_flag_test(bm_src, e->v1, DUPE_DONE)) {
- copy_vertex(bm_src, e->v1, bm_dst, vhash);
+ bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v1, vhash);
BMO_elem_flag_enable(bm_src, e->v1, DUPE_DONE);
}
if (!BMO_elem_flag_test(bm_src, e->v2, DUPE_DONE)) {
- copy_vertex(bm_src, e->v2, bm_dst, vhash);
+ bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v2, vhash);
BMO_elem_flag_enable(bm_src, e->v2, DUPE_DONE);
}
/* now copy the actual edge */
- copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash);
+ bmo_edge_copy(op, slot_edge_map_out, slot_boundary_map_out,
+ bm_dst, bm_src, e, vhash, ehash);
BMO_elem_flag_enable(bm_src, e, DUPE_DONE);
}
}
@@ -261,7 +265,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
/* vertex pass */
BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
if (!BMO_elem_flag_test(bm_src, v, DUPE_DONE)) {
- copy_vertex(bm_src, v, bm_dst, vhash);
+ bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
BMO_elem_flag_enable(bm_src, v, DUPE_DONE);
}
}
@@ -269,12 +273,13 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
/* edge pass */
BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {
if (!BMO_elem_flag_test(bm_src, e, DUPE_DONE)) {
- copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash);
+ bmo_edge_copy(op, slot_edge_map_out, slot_boundary_map_out,
+ bm_dst, bm_src, e, vhash, ehash);
BMO_elem_flag_enable(bm_src, e, DUPE_DONE);
}
}
- copy_face(op, slot_face_map_out, bm_src, f, bm_dst, vhash, ehash);
+ bmo_face_copy(op, slot_face_map_out, bm_dst, bm_src, f, vhash, ehash);
BMO_elem_flag_enable(bm_src, f, DUPE_DONE);
}
}
@@ -307,16 +312,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
void bmo_duplicate_exec(BMesh *bm, BMOperator *op)
{
BMOperator *dupeop = op;
- BMesh *bm2 = BMO_slot_ptr_get(op->slots_in, "dest");
+ BMesh *bm_dst = BMO_slot_ptr_get(op->slots_in, "dest");
- if (!bm2)
- bm2 = bm;
+ if (!bm_dst)
+ bm_dst = bm;
/* flag input */
BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "geom", BM_ALL_NOLOOP, DUPE_INPUT);
/* use the internal copy function */
- bmo_mesh_copy(dupeop, bm, bm2);
+ bmo_mesh_copy(dupeop, bm_dst, bm);
/* Output */
/* First copy the input buffers to output buffers - original data */
@@ -466,13 +471,14 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
float axis[3];
float rmat[3][3];
float phi;
- int steps, do_dupli, a, usedvec;
+ int steps, do_dupli, a;
+ bool use_dvec;
BMO_slot_vec_get(op->slots_in, "cent", cent);
BMO_slot_vec_get(op->slots_in, "axis", axis);
normalize_v3(axis);
BMO_slot_vec_get(op->slots_in, "dvec", dvec);
- usedvec = !is_zero_v3(dvec);
+ use_dvec = !is_zero_v3(dvec);
steps = BMO_slot_int_get(op->slots_in, "steps");
phi = BMO_slot_float_get(op->slots_in, "angle") / steps;
do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate");
@@ -504,7 +510,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
BMO_op_finish(bm, &extop);
}
- if (usedvec) {
+ if (use_dvec) {
mul_m3_v3(rmat, dvec);
BMO_op_callf(bm, op->flag,
"translate vec=%v space=%s verts=%S",
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 923b877b822..fdee80b9505 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -37,1028 +37,58 @@
#include "BLI_heap.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h" /* own include */
#define EDGE_MARK 1
#define EDGE_VIS 2
-#define FACE_NEW 1
-
#define ELE_NEW 1
-#define ELE_ORIG 4
-
-#define FACE_IGNORE 16
-
-typedef struct EPathNode {
- struct EPathNode *next, *prev;
- BMVert *v;
- BMEdge *e;
- BMEdge *cure;
-} EPathNode;
-
-typedef struct EPath {
- ListBase nodes;
- float weight;
- int group;
-} EPath;
-
-typedef struct PathBase {
- BLI_mempool *nodepool, *pathpool;
-} PathBase;
-
-typedef struct EdgeData {
- int tag;
- int ftag;
- BMDiskLink v1_disk_link, v2_disk_link;
-} EdgeData;
-
-typedef struct VertData {
- BMEdge *e;
- float no[3], offco[3], sco[3]; /* offco is vertex coordinate slightly offset randomly */
- int tag;
-} VertData;
-
-static int count_edge_faces(BMesh *bm, BMEdge *e);
-
-/**** rotation system code * */
-
-BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data)
-{
- return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) :
- &(((EdgeData *)e_data)->v2_disk_link);
-}
-
-static bool rotsys_append_edge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *vdata)
-{
- EdgeData *ed = &edata[BM_elem_index_get(e)];
- VertData *vd = &vdata[BM_elem_index_get(v)];
-
- if (!vd->e) {
- Link *e1 = (Link *)rs_edge_link_get(e, v, ed);
-
- vd->e = e;
- e1->next = e1->prev = (Link *)e;
- }
- else {
- BMDiskLink *dl1, *dl2, *dl3;
- EdgeData *ved = &edata[BM_elem_index_get(vd->e)];
-
- dl1 = rs_edge_link_get(e, v, ed);
- dl2 = rs_edge_link_get(vd->e, v, ved);
- dl3 = dl2->prev ? rs_edge_link_get(dl2->prev, v, &edata[BM_elem_index_get(dl2->prev)]) : NULL;
-
- dl1->next = vd->e;
- dl1->prev = dl2->prev;
-
- dl2->prev = e;
- if (dl3) {
- dl3->next = e;
- }
- }
-
- return true;
-}
-
-static void UNUSED_FUNCTION(rotsys_remove_edge)(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *vdata)
-{
- EdgeData *ed = edata + BM_elem_index_get(e);
- VertData *vd = vdata + BM_elem_index_get(v);
- BMDiskLink *e1, *e2;
-
- e1 = rs_edge_link_get(e, v, ed);
- if (e1->prev) {
- e2 = rs_edge_link_get(e1->prev, v, ed);
- e2->next = e1->next;
- }
-
- if (e1->next) {
- e2 = rs_edge_link_get(e1->next, v, ed);
- e2->prev = e1->prev;
- }
-
- if (vd->e == e)
- vd->e = (e != e1->next) ? e1->next : NULL;
-
- e1->next = e1->prev = NULL;
-}
-
-static BMEdge *rotsys_nextedge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *UNUSED(vdata))
-{
- if (v == e->v1)
- return edata[BM_elem_index_get(e)].v1_disk_link.next;
- if (v == e->v2)
- return edata[BM_elem_index_get(e)].v2_disk_link.next;
- return NULL;
-}
-
-static BMEdge *rotsys_prevedge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *UNUSED(vdata))
-{
- if (v == e->v1)
- return edata[BM_elem_index_get(e)].v1_disk_link.prev;
- if (v == e->v2)
- return edata[BM_elem_index_get(e)].v2_disk_link.prev;
- return NULL;
-}
-
-static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertData *vdata)
-{
- BMEdge **edges = NULL;
- BMEdge *e_first;
- BMEdge *e;
- BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
- int i, totedge;
-
- e = e_first = vdata[BM_elem_index_get(v)].e;
- do {
- BLI_array_append(edges, e);
- e = rotsys_nextedge(e, v, edata, vdata);
- } while (e != e_first);
-
- totedge = BLI_array_count(edges);
- for (i = 0; i < totedge / 2; i++) {
- SWAP(BMEdge *, edges[i], edges[totedge - 1 - i]);
- }
-
- vdata[BM_elem_index_get(v)].e = NULL;
- for (i = 0; i < totedge; i++) {
- rotsys_append_edge(edges[i], v, edata, vdata);
- }
-
- BLI_array_free(edges);
-}
-
-static int UNUSED_FUNCTION(rotsys_count)(BMVert *v, EdgeData *edata, VertData *vdata)
-{
- BMEdge *e = vdata[BM_elem_index_get(v)].e;
- int i = 0;
-
- if (!e)
- return 0;
-
- do {
- if (!e)
- return 0;
- e = rotsys_nextedge(e, v, edata, vdata);
-
- if (i >= (1 << 20)) {
- printf("bmesh error: infinite loop in disk cycle!\n");
- return 0;
- }
-
- i += 1;
- } while (e != vdata[BM_elem_index_get(v)].e);
-
- return i;
-}
-
-static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e, **edges = NULL;
- BLI_array_declare(edges);
- BMVert *v, **verts = NULL;
- BMFace *f;
- BLI_array_declare(verts);
- SmallHash visithash, *hash = &visithash;
- int i;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMEdge *e2, *starte;
- BMVert *startv;
- int rad, ok;
-
- rad = count_edge_faces(bm, e);
-
- if (rad < 2) {
- starte = e;
- }
- else {
- continue;
- }
-
- /* do two passes, going forward then backward */
- for (i = 0; i < 2; i++) {
- BLI_smallhash_init(hash);
-
- BLI_array_empty(verts);
- BLI_array_empty(edges);
-
- startv = v = starte->v1;
- e2 = starte;
- ok = 1;
- if (!v || !e2)
- continue;
-
- do {
- if (BLI_smallhash_haskey(hash, (uintptr_t)e2) ||
- BLI_smallhash_haskey(hash, (uintptr_t)v))
- {
- ok = 0;
- break;
- }
-
- BLI_array_append(verts, v);
- BLI_array_append(edges, e2);
-
- BLI_smallhash_insert(hash, (uintptr_t)e2, NULL);
-
- v = BM_edge_other_vert(e2, v);
- e2 = i ? rotsys_prevedge(e2, v, edata, vdata) : rotsys_nextedge(e2, v, edata, vdata);
- } while (e2 != starte && v != startv);
-
- BLI_smallhash_release(hash);
-
- if (!ok || BLI_array_count(edges) < 3)
- continue;
-
- f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), BM_CREATE_NO_DOUBLE);
- if (UNLIKELY(f == NULL)) {
- continue;
- }
- }
- }
-
- return 0;
-}
-
-static void rotsys_make_consistent(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e;
- BMVert *v, **stack = NULL;
- BLI_array_declare(stack);
- int i;
-
- for (i = 0; i < bm->totvert; i++) {
- vdata[i].tag = 0;
- }
-
- while (1) {
- VertData *vd;
- BMVert *startv = NULL;
- float dis;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- vd = vdata + BM_elem_index_get(v);
-
- if (vd->tag)
- continue;
-
- if (!startv || dot_v3v3(vd->offco, vd->offco) > dis) {
- dis = dot_v3v3(vd->offco, vd->offco);
- startv = v;
- }
- }
-
- if (!startv)
- break;
-
- vd = vdata + BM_elem_index_get(startv);
-
- BLI_array_empty(stack);
- BLI_array_append(stack, startv);
-
- vd->tag = 1;
-
- while (BLI_array_count(stack)) {
- v = BLI_array_pop(stack);
- vd = vdata + BM_elem_index_get(v);
-
- if (!vd->e)
- continue;
-
- e = vd->e;
- do {
- BMVert *v2 = BM_edge_other_vert(e, v);
- VertData *vd2 = vdata + BM_elem_index_get(v2);
-
- if (dot_v3v3(vd->no, vd2->no) < 0.0f + FLT_EPSILON * 2) {
- rotsys_reverse(e, v2, edata, vdata);
- mul_v3_fl(vd2->no, -1.0f);
- }
-
- if (!vd2->tag) {
- BLI_array_append(stack, v2);
- vd2->tag = 1;
- }
-
- e = rotsys_nextedge(e, v, edata, vdata);
- } while (e != vd->e);
- }
- }
-
- BLI_array_free(stack);
-}
-
-static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
-{
- BMIter iter;
- BMEdge *e;
- BMEdge **edges = NULL;
- BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
- BMVert *v;
- RNG *rng;
- /* BMVert **verts = NULL; */
- /* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */
- int i;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMIter eiter;
- float no[3], cent[3];
- int j, k = 0, totedge = 0;
-
- if (BM_elem_index_get(v) == -1)
- continue;
-
- BLI_array_empty(edges);
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- BLI_array_append(edges, e);
- totedge++;
- }
- }
-
- copy_v3_v3(cent, v->co);
-
- zero_v3(no);
- for (i = 0; i < totedge; i++) {
- BMEdge *e1, *e2;
- float cno[3], vec1[3], vec2[3];
-
- e1 = edges[i];
- e2 = edges[(i + 1) % totedge];
-
- sub_v3_v3v3(vec1, (BM_edge_other_vert(e1, v))->co, v->co);
- sub_v3_v3v3(vec2, (BM_edge_other_vert(e2, v))->co, v->co);
-
- cross_v3_v3v3(cno, vec1, vec2);
- normalize_v3(cno);
-
- if (i && dot_v3v3(cno, no) < 0.0f + FLT_EPSILON * 10)
- mul_v3_fl(cno, -1.0f);
-
- add_v3_v3(no, cno);
- normalize_v3(no);
- }
-
- /* generate plane-flattened coordinates */
- for (i = 0; i < totedge; i++) {
- BMEdge *e1;
- BMVert *v2;
- float cvec[3], vec1[3];
-
- e1 = edges[i];
- v2 = BM_edge_other_vert(e1, v);
-
- sub_v3_v3v3(vec1, v2->co, v->co);
-
- cross_v3_v3v3(cvec, vec1, no);
- cross_v3_v3v3(vec1, cvec, no);
- normalize_v3(vec1);
-
- mul_v3_fl(vec1, len_v3v3(v2->co, v->co));
- add_v3_v3(vec1, v->co);
-
- copy_v3_v3(vdata[BM_elem_index_get(v2)].sco, vec1);
- }
-
- rng = BLI_rng_new_srandom(0);
-
- /* first, ensure no 0 or 180 angles between adjacent
- * (and that adjacent's adjacent) edges */
- for (i = 0, k = 0; i < totedge; i++) {
- BMEdge *e1, *e2, *e3 = NULL;
- BMVert *v1, *v2, *v3;
- VertData *vd1, *vd2, *vd3;
- float vec1[3], vec2[3], vec3[3], size;
- int s1, s2, s3;
-
- if (totedge < 3)
- continue;
-
- e1 = edges[(i + totedge - 1) % totedge];
- e2 = edges[i];
- e3 = edges[(i + 1) % totedge];
-
- v1 = BM_edge_other_vert(e1, v);
- v2 = BM_edge_other_vert(e2, v);
- v3 = BM_edge_other_vert(e3, v);
-
- vd1 = vdata + BM_elem_index_get(v1);
- vd2 = vdata + BM_elem_index_get(v2);
- vd3 = vdata + BM_elem_index_get(v3);
-
- sub_v3_v3v3(vec1, vd1->sco, cent);
- sub_v3_v3v3(vec2, vd2->sco, cent);
- sub_v3_v3v3(vec3, vd3->sco, cent);
-
- size = (len_v3(vec1) + len_v3(vec3)) * 0.01f;
- normalize_v3(vec1); normalize_v3(vec2); normalize_v3(vec3);
-
-#ifdef STRAIGHT
-#undef STRAIGHT
-#endif
-#define STRAIGHT(vec11, vec22) (fabsf(dot_v3v3((vec11), (vec22))) > 1.0f - ((float)FLT_EPSILON * 1000.0f))
-
- s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
-
- if (s1 || s2 || s3) {
- copy_v3_v3(cent, v->co);
-
- for (j = 0; j < 3; j++) {
- float fac = (BLI_rng_get_float(rng) - 0.5f) * size;
- cent[j] += fac;
- }
-
- if (k < 2000) {
- i = 0;
- k++;
- continue;
- }
- else {
- k++;
- continue;
- }
-
- }
- }
-
- BLI_rng_free(rng);
-
- copy_v3_v3(vdata[BM_elem_index_get(v)].offco, cent);
- //copy_v3_v3(v->co, cent);
-
- /* now, sort edges so the triangle fan of all edges
- * has a consistent normal. this is the same as
- * sorting by polar coordinates along a group normal */
- for (j = 0; j < totedge; j++) {
- for (i = 0; i < totedge; i++) {
- BMEdge *e1, *e2, *e3 = NULL;
- BMVert *v1, *v2, *v3;
- VertData *vd1, *vd2, *vd3;
- float vec1[3], vec2[3], vec3[3], n1[3], n2[3], n3[3];
-
- e1 = edges[(i + totedge - 1) % totedge];
- e2 = edges[i];
- e3 = edges[(i + 1) % totedge];
-
- v1 = BM_edge_other_vert(e1, v);
- v2 = BM_edge_other_vert(e2, v);
- v3 = BM_edge_other_vert(e3, v);
-
- vd1 = vdata + BM_elem_index_get(v1);
- vd2 = vdata + BM_elem_index_get(v2);
- vd3 = vdata + BM_elem_index_get(v3);
-
- sub_v3_v3v3(vec1, vd1->sco, cent);
- sub_v3_v3v3(vec2, vd2->sco, cent);
- sub_v3_v3v3(vec3, vd3->sco, cent);
-
- cross_v3_v3v3(n1, vec1, vec2);
- cross_v3_v3v3(n2, vec2, vec3);
- cross_v3_v3v3(n3, vec1, vec3);
-
- /* this case happens often enough and probably not worth bothering users with,
- * maybe enable for debugging code but not for everyday use - campbell */
-#if 0
- /* Other way to determine if two vectors approach are (nearly) parallel: the
- * cross product of the two vectors will approach zero */
- {
- int s1, s2, s3;
- s1 = (dot_v3v3(n1, n1) < (0.0f + FLT_EPSILON * 10));
- s2 = (dot_v3v3(n2, n2) < (0.0f + FLT_EPSILON * 10));
- s3 = (totedge < 3) ? 0 : (dot_v3v3(n3, n3) < (0.0f + FLT_EPSILON * 10));
-
- if (s1 || s2 || s3) {
- fprintf(stderr, "%s: s1: %d, s2: %d, s3: %dx (bmesh internal error)\n", __func__, s1, s2, s3);
- }
- }
-#endif
-
- normalize_v3(n1); normalize_v3(n2); normalize_v3(n3);
-
-
- if (dot_v3v3(n1, n2) < 0.0f) {
- if (dot_v3v3(n1, n3) >= 0.0f + FLT_EPSILON * 10) {
- SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
- }
- else {
- SWAP(BMEdge *, edges[(i + totedge - 1) % totedge], edges[(i + 1) % totedge]);
- SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
- }
- }
- }
- }
-
-#undef STRAIGHT
-
- zero_v3(no);
-
- /* yay, edges are sorted */
- for (i = 0; i < totedge; i++) {
- BMEdge *e1 = edges[i], *e2 = edges[(i + 1) % totedge];
- float eno[3];
-
- normal_tri_v3(eno, BM_edge_other_vert(e1, v)->co, v->co, BM_edge_other_vert(e2, v)->co);
- add_v3_v3(no, eno);
-
- rotsys_append_edge(edges[i], v, edata, vdata);
- }
-
- normalize_v3(no);
- copy_v3_v3(vdata[BM_elem_index_get(v)].no, no);
- }
-
- /* now, make sure rotation system is topologically consistent
- * (e.g. vert normals consistently point either inside or outside) */
- rotsys_make_consistent(bm, edata, vdata);
-
- //rotsys_fill_faces(bm, edata, vdata);
-
-#if 0
- /* create visualizing geometry */
- BMVert *lastv;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMVert *v2;
- BMFace *f;
- int totedge = BM_vert_edge_count(v);
-
- if (BM_elem_index_get(v) == -1)
- continue;
-
- //cv = BM_vert_create(bm, cent, v);
- //BM_elem_index_set(cv, -1); /* set_dirty! */
- i = 0;
- e = vdata[BM_elem_index_get(v)].e;
- lastv = NULL;
- do {
- BMEdge *e2;
- BMVert *v2;
- float f = ((float)i / (float)totedge) * 0.35 + 0.05;
- float co[3];
-
- if (!e)
- break;
-
- if (!BM_edge_other_vert(e, v))
- continue;
-
- sub_v3_v3v3(co, (BM_edge_other_vert(e, v))->co, vdata[BM_elem_index_get(v)].offco);
- mul_v3_fl(co, f);
- add_v3_v3(co, vdata[BM_elem_index_get(v)].offco);
-
- v2 = BM_vert_create(bm, co, NULL);
- BM_elem_index_set(v2, -1); /* set_dirty! */
- //BM_edge_create(bm, cv, v2, NULL, 0);
-
- BM_vert_select_set(bm, v2, true);
- if (lastv) {
- e2 = BM_edge_create(bm, lastv, v2, NULL, 0);
- BM_edge_select_set(bm, e2, true);
- }
-
- lastv = v2;
-
- e = rotsys_nextedge(e, v, edata, vdata);
- i++;
- } while (e != vdata[BM_elem_index_get(v)].e);
- }
-#endif
-
- BLI_array_free(edges);
-}
-
-static PathBase *edge_pathbase_new(void)
-{
- PathBase *pb = MEM_callocN(sizeof(PathBase), "PathBase");
-
- pb->nodepool = BLI_mempool_create(sizeof(EPathNode), 1, 512, BLI_MEMPOOL_SYSMALLOC);
- pb->pathpool = BLI_mempool_create(sizeof(EPath), 1, 512, BLI_MEMPOOL_SYSMALLOC);
-
- return pb;
-}
-
-static void edge_pathbase_free(PathBase *pathbase)
-{
- BLI_mempool_destroy(pathbase->nodepool);
- BLI_mempool_destroy(pathbase->pathpool);
- MEM_freeN(pathbase);
-}
-
-static EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
-{
- EPath *path2;
- EPathNode *node, *node2;
-
- path2 = BLI_mempool_alloc(pb->pathpool);
- path2->nodes.first = path2->nodes.last = NULL;
- path2->weight = 0.0f;
- path2->group = path->group;
-
- for (node = path->nodes.first; node; node = node->next) {
- node2 = BLI_mempool_alloc(pb->nodepool);
- *node2 = *node;
- BLI_addtail(&path2->nodes, node2);
- }
-
- node2 = BLI_mempool_alloc(pb->nodepool);
- node2->v = appendv;
- node2->e = e;
- node2->cure = NULL;
-
- BLI_addtail(&path2->nodes, node2);
-
- return path2;
-}
-
-static EPath *edge_path_new(PathBase *pb, BMVert *start, BMEdge *starte)
-{
- EPath *path;
- EPathNode *node;
-
- path = BLI_mempool_alloc(pb->pathpool);
- node = BLI_mempool_alloc(pb->nodepool);
-
- path->nodes.first = path->nodes.last = NULL;
-
- node->v = start;
- node->e = starte;
- node->cure = NULL;
-
- BLI_addtail(&path->nodes, node);
- path->weight = 0.0f;
-
- return path;
-}
-
-static float edge_weight_path(EPath *path, EdgeData *edata, VertData *UNUSED(vdata))
-{
- EPathNode *node, *first = path->nodes.first;
- float w = 0.0;
-
- for (node = path->nodes.first; node; node = node->next) {
- if (node->e && node != path->nodes.first) {
- w += edata[BM_elem_index_get(node->e)].ftag;
- if (node->prev) {
- /* BMESH_TOD */
- (void)first;
- //w += len_v3v3(node->v->co, first->e->v1->co) * 0.0001f;
- //w += len_v3v3(node->v->co, first->e->v2->co) * 0.0001f;
- }
- }
-
- w += 1.0f;
- }
-
- return w;
-}
-
-
-static void edge_free_path(PathBase *pathbase, EPath *path)
-{
- EPathNode *node, *next;
-
- for (node = path->nodes.first; node; node = next) {
- next = node->next;
- BLI_mempool_free(pathbase->nodepool, node);
- }
-
- BLI_mempool_free(pathbase->pathpool, path);
-}
-
-static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, EdgeData *edata,
- VertData *vdata, PathBase *pathbase, int group)
-{
- BMEdge *e;
- GHash *gh = BLI_ghash_ptr_new("createops find shortest path");
- BMVert *v1, *v2;
- BMVert **verts = NULL;
- BLI_array_staticdeclare(verts, 1024);
- Heap *heap = BLI_heap_new();
- EPath *path = NULL, *path2;
- BMVert *startv;
- BMVert *endv;
- EPathNode *node;
- int i;
- const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
- BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
-
-
- startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1;
- endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2;
-
- path = edge_path_new(pathbase, startv, edge);
- BLI_ghash_insert(gh, startv, NULL);
- BLI_heap_insert(heap, path->weight, path);
- path->group = group;
-
- while (BLI_heap_size(heap)) {
- VertData *vd;
- EPathNode *last;
- BMFace *f = NULL;
-
- path = BLI_heap_popmin(heap);
- last = path->nodes.last;
- v1 = last->v;
-
- if (v1 == endv) {
- /* make sure this path loop doesn't already exists */
- i = 0;
- BLI_array_empty(verts);
- for (i = 0, node = path->nodes.first; node; node = node->next, i++) {
- BLI_array_grow_one(verts);
- verts[i] = node->v;
- }
-
- if (BM_face_exists(verts, i, &f)) {
- if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) {
- BLI_ghash_remove(gh, endv, NULL, NULL);
- continue;
- }
- }
- break;
- }
-
- vd = vdata + BM_elem_index_get(v1);
- if (!vd->e)
- continue;
-
- v2 = NULL;
- while (1) {
- if (!last->cure) {
- last->cure = e = vdata[BM_elem_index_get(last->v)].e;
- }
- else {
- last->cure = e = rotsys_nextedge(last->cure, last->v, edata, vdata);
- if (last->cure == vdata[BM_elem_index_get(last->v)].e) {
- v2 = NULL;
- break;
- }
- }
-
- if (e == edge || !BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- continue;
- }
-
- v2 = BM_edge_other_vert(e, last->v);
-
- if (BLI_ghash_haskey(gh, v2)) {
- v2 = NULL;
- continue;
- }
-
- if (use_restrict) {
- int *group_flag = (int *)BMO_slot_map_data_get(slot_restrict, e);
- if (group_flag) {
- if (!(*group_flag & path->group)) {
- v2 = NULL;
- continue;
- }
- }
- }
-
- break;
- }
-
- if (!v2) {
- edge_free_path(pathbase, path);
- path = NULL;
- continue;
- }
-
- /* add path back into heap */
- BLI_heap_insert(heap, path->weight, path);
-
- /* put v2 in gh ma */
- BLI_ghash_insert(gh, v2, NULL);
-
- path2 = edge_copy_add_path(pathbase, path, v2, e);
- path2->weight = edge_weight_path(path2, edata, vdata);
-
- BLI_heap_insert(heap, path2->weight, path2);
- }
-
- if (path && ((EPathNode *)path->nodes.last)->v != endv) {
- edge_free_path(pathbase, path);
- path = NULL;
- }
-
- BLI_array_free(verts);
- BLI_heap_free(heap, NULL);
- BLI_ghash_free(gh, NULL, NULL);
-
- return path;
-}
-
-static int count_edge_faces(BMesh *bm, BMEdge *e)
-{
- int i = 0;
- BMLoop *l = e->l;
-
- if (!l) {
- return 0;
- }
-
- do {
- if (!BMO_elem_flag_test(bm, l->f, FACE_IGNORE)) {
- i++;
- }
-
- l = l->radial_next;
- } while (l != e->l);
-
- return i;
-}
-
-BLI_INLINE void vote_on_winding(BMEdge *edge, EPathNode *node, unsigned int winding[2])
-{
- BMVert *test_v1, *test_v2;
- /* we want to use the reverse winding to the existing order */
- BM_edge_ordered_verts(edge, &test_v2, &test_v1);
-
- /* edges vote on which winding wins out */
- winding[(test_v1 == node->v)]++;
-}
-
-static BMFace *bm_face_from_path(BMesh *bm, EPath *path,
- EdgeData *edata,
- const bool use_fill_check)
-{
- /* accumulte winding directions for each edge which has a face */
- const unsigned int path_len = BLI_countlist(&path->nodes);
- unsigned int winding[2] = {0, 0};
- unsigned int i;
-
- EPathNode *node;
-
- BMVert **verts = BLI_array_alloca(verts, path_len);
- BMEdge **edges = BLI_array_alloca(edges, path_len);
- BMEdge *e;
- BMVert *v;
-
- for (node = path->nodes.first, i = 0; node; node = node->next, i++) {
-
- v = node->v;
- e = BM_edge_exists(v, node->next ?
- node->next->v :
- ((EPathNode *)path->nodes.first)->v);
-
- /* check on the winding */
- if (e->l) {
- if (UNLIKELY(count_edge_faces(bm, e) >= 2)) {
- return NULL;
- }
-
- vote_on_winding(e, node, winding);
- }
-
- verts[i] = v;
- edges[i] = e;
- }
-
- /* do after incase we bail early, above */
- for (i = 0; i < path_len; i++) {
- edata[BM_elem_index_get(edges[i])].ftag++;
- }
-
-
- /* if these are even it doesn't really matter what to do,
- * with consistent geometry one will be zero, the choice is clear */
- if (winding[0] > winding[1]) {
- BLI_array_wrap(verts, path_len, -1);
- BLI_array_reverse(verts, path_len);
- BLI_array_reverse(edges, path_len);
- }
-
- if ((use_fill_check == false) ||
- /* fairly expensive check - see if there are already faces filling this area */
- (BM_face_exists_multi(verts, edges, path_len) == false))
- {
- return BM_face_create(bm, verts, edges, path_len, BM_CREATE_NO_DOUBLE);
- }
- else {
- return NULL;
- }
-}
void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
{
- BMIter iter;
+ BMOperator op_attr;
BMOIter siter;
BMFace *f;
- BMEdge *e;
- EPath *path;
- EdgeData *edata;
- VertData *vdata;
- PathBase *pathbase;
- const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
- const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
- int i;
- BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
- BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out");
+// const int sides = BMO_slot_int_get(op->slots_in, "sides");
if (!bm->totvert || !bm->totedge)
return;
- pathbase = edge_pathbase_new();
-
- edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData");
- vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData");
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMO_elem_flag_enable(bm, f, ELE_ORIG);
- }
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BM_mesh_edgenet(bm, true, true); // TODO, sides
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- BM_elem_index_set(e, i); /* set_inline */
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
- if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- edata[i].tag = 2;
+ BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) {
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
}
+ /* normals are zero'd */
+ BM_face_normal_update(f);
}
- bm->elem_index_dirty &= ~BM_EDGE;
- init_rotsys(bm, edata, vdata);
+ /* --- Attribute Fill --- */
+ /* may as well since we have the faces already in a buffer */
+ BMO_op_initf(bm, &op_attr, op->flag,
+ "face_attribute_fill faces=%S use_normals=%b",
+ op, "faces.out", true);
- while (1) {
- BMEdge *edge = NULL;
- int group = 0;
+ BMO_op_exec(bm, &op_attr);
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- /* if restrict is on, only start on faces in the restrict map */
- if (use_restrict && !BMO_slot_map_contains(slot_restrict, e))
- continue;
-
- if (edata[BM_elem_index_get(e)].tag < 2) {
- edge = e;
-
- if (use_restrict) {
- int gi_iter = 0, gi_count = 0, gi = 0;
-
- group = BMO_slot_map_int_get(slot_restrict, e);
-
- for (gi_iter = 0; gi_iter < 30; gi_iter++) {
- if (group & (1 << gi_iter)) {
- gi_count++;
- gi = gi_iter;
-
- if (gi_count - 1 == edata[BM_elem_index_get(e)].tag) {
- break;
- }
- }
- }
-
- group = (1 << gi);
- }
-
- break;
- }
- }
-
- if (!edge)
- break;
-
- edata[BM_elem_index_get(edge)].tag += 1;
-
- path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
- if (path && path->nodes.first) {
- BMFace *f = bm_face_from_path(bm, path, edata,
- use_fill_check);
-
- if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
- BMO_elem_flag_enable(bm, f, FACE_NEW);
- f->mat_nr = mat_nr;
- if (use_smooth) {
- BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
- }
- }
-
- if (use_restrict) {
- BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group);
- }
-
- edge_free_path(pathbase, path);
- }
+ /* check if some faces couldn't be touched */
+ if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
+ BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out");
}
+ BMO_op_finish(bm, &op_attr);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
-
- edge_pathbase_free(pathbase);
- MEM_freeN(edata);
- MEM_freeN(vdata);
}
static BMEdge *edge_next(BMesh *bm, BMEdge *e)
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 070cc187045..90c514bfd02 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -77,7 +77,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
f_side = BM_face_create_quad_tri(bm,
l_org->next->v, l_new->next->v, l_new->v, l_org->v,
- f_org, false);
+ f_org, BM_CREATE_NOP);
l_side_iter = BM_FACE_FIRST_LOOP(f_side);
@@ -163,14 +163,14 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
/* disable root flag on all new skin nodes */
if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
BMVert *v;
- BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
+ BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
bm_extrude_disable_skin_root(bm, v);
}
}
for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) {
BMVert *f_verts[4];
- e_new = *(BMEdge **)BMO_iter_map_value(&siter);
+ e_new = BMO_iter_map_value_ptr(&siter);
if (e->l && e->v1 != e->l->v) {
f_verts[0] = e->v1;
@@ -185,7 +185,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
f_verts[3] = e_new->v2;
}
/* not sure what to do about example face, pass NULL for now */
- f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false);
+ f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
bm_extrude_copy_face_loop_attributes(bm, f);
if (BMO_elem_flag_test(bm, e, EXT_INPUT))
@@ -211,11 +211,11 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) {
- dupev = BM_vert_create(bm, v->co, v, 0);
+ dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
if (has_vskin)
bm_extrude_disable_skin_root(bm, v);
- e = BM_edge_create(bm, v, dupev, NULL, 0);
+ e = BM_edge_create(bm, v, dupev, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, e, EXT_KEEP);
BMO_elem_flag_enable(bm, dupev, EXT_KEEP);
@@ -319,7 +319,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
/* disable root flag on all new skin nodes */
if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
- BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
+ BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
bm_extrude_disable_skin_root(bm, v);
}
}
@@ -372,7 +372,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
continue;
}
- e_new = *(BMEdge **)BMO_iter_map_value(&siter);
+ e_new = BMO_iter_map_value_ptr(&siter);
if (!e_new) {
continue;
@@ -401,13 +401,13 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
}
/* not sure what to do about example face, pass NULL for now */
- f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false);
+ f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
bm_extrude_copy_face_loop_attributes(bm, f);
}
/* link isolated vert */
for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) {
- BMVert *v2 = *((void **)BMO_iter_map_value(&siter));
+ BMVert *v2 = BMO_iter_map_value_ptr(&siter);
BM_edge_create(bm, v, v2, v->e, BM_CREATE_NO_DOUBLE);
}
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
new file mode 100644
index 00000000000..f53b4536e44
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -0,0 +1,176 @@
+
+/*
+ * ***** 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): Campbell Barton.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_fill_attribute.c
+ * \ingroup bmesh
+ *
+ * Fill in geometry with the attributes of their adjacent data.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_linklist_stack.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+/**
+ * Check if all other loops are tagged.
+ */
+static bool bm_loop_is_all_radial_tag(BMLoop *l)
+{
+ BMLoop *l_iter;
+ l_iter = l->radial_next;
+ do {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG) == 0) {
+ return false;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return true;
+}
+
+/**
+ * Callback to run on source-loops for #BM_face_copy_shared
+ */
+static bool bm_loop_is_face_untag(BMElem *ele, void *UNUSED(user_data))
+{
+ return (BM_elem_flag_test(((BMLoop *)ele)->f, BM_ELEM_TAG) == 0);
+}
+
+/**
+ * Copy all attributes from adjacent untagged faces.
+ */
+static void bm_face_copy_shared_all(BMesh *bm, BMLoop *l,
+ const bool use_normals, const bool use_data)
+{
+ BMLoop *l_other = l->radial_next;
+ BMFace *f = l->f, *f_other;
+ while (BM_elem_flag_test(l_other->f, BM_ELEM_TAG)) {
+ l_other = l_other->radial_next;
+ }
+ f_other = l_other->f;
+
+ if (use_data) {
+ /* copy face-attrs */
+ BM_elem_attrs_copy(bm, bm, f_other, f);
+
+ /* copy loop-attrs */
+ BM_face_copy_shared(bm, f, bm_loop_is_face_untag, NULL);
+ }
+
+ if (use_normals) {
+ /* copy winding (flipping) */
+ if (l->v == l_other->v) {
+ BM_face_normal_flip(bm, f);
+ }
+ }
+}
+
+/**
+ * Flood fill attributes.
+ */
+static unsigned int bmesh_face_attribute_fill(BMesh *bm,
+ const bool use_normals, const bool use_data)
+{
+ BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *);
+ BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *);
+
+ BMFace *f;
+ BMIter iter;
+ BMLoop *l;
+
+ unsigned int face_tot = 0;
+
+
+ BLI_LINKSTACK_INIT(loop_queue_prev);
+ BLI_LINKSTACK_INIT(loop_queue_next);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (bm_loop_is_all_radial_tag(l_iter) == false) {
+ BLI_LINKSTACK_PUSH(loop_queue_prev, l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ while (BLI_LINKSTACK_SIZE(loop_queue_prev)) {
+ while ((l = BLI_LINKSTACK_POP(loop_queue_prev))) {
+ /* check we're still un-assigned */
+ if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
+ BMLoop *l_iter;
+
+ BM_elem_flag_disable(l->f, BM_ELEM_TAG);
+
+ l_iter = l->next;
+ do {
+ BMLoop *l_radial_iter = l_iter->radial_next;
+ if (l_radial_iter != l_iter) {
+ do {
+ if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
+ BLI_LINKSTACK_PUSH(loop_queue_next, l_radial_iter);
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l);
+
+ /* do last because of face flipping */
+ bm_face_copy_shared_all(bm, l,
+ use_normals, use_data);
+ face_tot += 1;
+ }
+ }
+
+ BLI_LINKSTACK_SWAP(loop_queue_prev, loop_queue_next);
+ }
+
+ BLI_LINKSTACK_FREE(loop_queue_prev);
+ BLI_LINKSTACK_FREE(loop_queue_next);
+
+ return face_tot;
+}
+
+void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
+{
+ const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
+ const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
+
+ int face_tot;
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); /* do inline */
+
+ /* now we can copy adjacent data */
+ face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data);
+
+ if (face_tot != BMO_slot_buffer_count(op->slots_in, "faces")) {
+ /* any remaining tags will be skipped */
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG);
+ }
+}
diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
index bd0466ff499..0fbaf5ff11a 100644
--- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c
+++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
@@ -140,7 +140,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
BMFace *f;
/* don't use calc_edges option because we already have the edges */
- f = BM_face_create_ngon_verts(bm, f_verts, i, 0, true, false);
+ f = BM_face_create_ngon_verts(bm, f_verts, i, NULL, BM_CREATE_NOP, true, false);
BMO_elem_flag_enable(bm, f, ELE_OUT);
f->mat_nr = mat_nr;
if (use_smooth) {
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 7d4b780baf5..a4b1237bc5d 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -37,6 +37,8 @@
#include "intern/bmesh_operators_private.h" /* own include */
+#include "BLI_strict_flags.h"
+
#define EDGE_MARK 4
#define FACE_OUT 16
@@ -103,17 +105,130 @@ static void quad_verts_to_barycentric_tri(
#endif
+/* -------------------------------------------------------------------- */
+/* Handle Loop Pairs */
+
+/** \name Loop Pairs
+ * \{ */
+
+/**
+ * Assign a loop pair from 2 verts (which _must_ share an edge)
+ */
+static void bm_loop_pair_from_verts(BMVert *v_a, BMVert *v_b,
+ BMLoop *l_pair[2])
+{
+ BMEdge *e = BM_edge_exists(v_a, v_b);
+ if (e->l) {
+ if (e->l->v == v_a) {
+ l_pair[0] = e->l;
+ l_pair[1] = e->l->next;
+ }
+ else {
+ l_pair[0] = e->l->next;
+ l_pair[1] = e->l;
+ }
+ }
+ else {
+ l_pair[0] = NULL;
+ l_pair[1] = NULL;
+ }
+}
+
+/**
+ * Copy loop pair from one side to the other if either is missing,
+ * this simplifies interpolation code so we only need to check if x/y are missing,
+ * rather then checking each loop.
+ */
+static void bm_loop_pair_test_copy(BMLoop *l_pair_a[2], BMLoop *l_pair_b[2])
+{
+ /* if the first one is set, we know the second is too */
+ if (l_pair_a[0] && l_pair_b[0] == NULL) {
+ l_pair_b[0] = l_pair_a[1];
+ l_pair_b[1] = l_pair_a[0];
+ }
+ else if (l_pair_b[0] && l_pair_a[0] == NULL) {
+ l_pair_a[0] = l_pair_b[1];
+ l_pair_a[1] = l_pair_b[0];
+ }
+}
+
+/**
+ * Interpolate from boundary loops.
+ *
+ * \note These weights will be calculated multiple times per vertex.
+ */
+static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_bound[4], const float w[4])
+{
+ void *l_cdata[4] = {
+ l_bound[0]->head.data,
+ l_bound[1]->head.data,
+ l_bound[2]->head.data,
+ l_bound[3]->head.data};
+
+ CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 4, l->head.data);
+}
+
+static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_bound[2], const float t)
+{
+
+ void *l_cdata[2] = {
+ l_bound[0]->head.data,
+ l_bound[1]->head.data};
+
+ const float w[2] = {1.0f - t, t};
+
+ CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 2, l->head.data);
+}
+
+/** \} */
+
+
+/**
+ * Avoids calling #barycentric_weights_v2_quad often by caching weights into an array.
+ */
+static void barycentric_weights_v2_grid_cache(const unsigned int xtot, const unsigned int ytot,
+ float (*weight_table)[4])
+{
+ float x_step = 1.0f / (float)(xtot - 1);
+ float y_step = 1.0f / (float)(ytot - 1);
+ unsigned int i = 0;
+ float xy_fl[2];
+
+ unsigned int x, y;
+ for (y = 0; y < ytot; y++) {
+ xy_fl[1] = y_step * (float)y;
+ for (x = 0; x < xtot; x++) {
+ xy_fl[0] = x_step * (float)x;
+ {
+ const float cos[4][2] = {
+ {xy_fl[0], 0.0f},
+ {0.0f, xy_fl[1]},
+ {xy_fl[0], 1.0f},
+ {1.0f, xy_fl[1]}};
+ barycentric_weights_v2_quad(UNPACK4(cos), xy_fl, weight_table[i++]);
+ }
+ }
+ }
+}
+
+
/**
* This may be useful outside the bmesh operator.
*
* \param v_grid 2d array of verts, all boundary verts must be set, we fill in the middle.
*/
-static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const int ytot,
+static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const unsigned int xtot, unsigned const int ytot,
const short mat_nr, const bool use_smooth,
- const bool use_flip)
+ const bool use_flip, const bool use_interp_simple)
{
const bool use_vert_interp = CustomData_has_interp(&bm->vdata);
- int x, y;
+ const bool use_loop_interp = CustomData_has_interp(&bm->ldata);
+ unsigned int x, y;
+
+ /* for use_loop_interp */
+ BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]);
+
+ float (*weight_table)[4];
#define XY(_x, _y) ((_x) + ((_y) * (xtot)))
@@ -141,6 +256,39 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
true);
#endif
+ if (use_interp_simple || use_vert_interp || use_loop_interp) {
+ weight_table = MEM_mallocN(sizeof(*weight_table) * (size_t)(xtot * ytot), __func__);
+ barycentric_weights_v2_grid_cache(xtot, ytot, weight_table);
+ }
+ else {
+ weight_table = NULL;
+ }
+
+
+ /* Store loops */
+ if (use_loop_interp) {
+ /* x2 because each edge connects 2 loops */
+ larr_x_a = MEM_mallocN(sizeof(*larr_x_a) * (xtot - 1), __func__);
+ larr_x_b = MEM_mallocN(sizeof(*larr_x_b) * (xtot - 1), __func__);
+
+ larr_y_a = MEM_mallocN(sizeof(*larr_y_a) * (ytot - 1), __func__);
+ larr_y_b = MEM_mallocN(sizeof(*larr_y_b) * (ytot - 1), __func__);
+
+ /* fill in the loops */
+ for (x = 0; x < xtot - 1; x++) {
+ bm_loop_pair_from_verts(v_grid[XY(x, 0)], v_grid[XY(x + 1, 0)], larr_x_a[x]);
+ bm_loop_pair_from_verts(v_grid[XY(x, ytot - 1)], v_grid[XY(x + 1, ytot - 1)], larr_x_b[x]);
+ bm_loop_pair_test_copy(larr_x_a[x], larr_x_b[x]);
+ }
+
+ for (y = 0; y < ytot - 1; y++) {
+ bm_loop_pair_from_verts(v_grid[XY(0, y)], v_grid[XY(0, y + 1)], larr_y_a[y]);
+ bm_loop_pair_from_verts(v_grid[XY(xtot - 1, y)], v_grid[XY(xtot - 1, y + 1)], larr_y_b[y]);
+ bm_loop_pair_test_copy(larr_y_a[y], larr_y_b[y]);
+ }
+ }
+
+
/* Build Verts */
for (y = 1; y < ytot - 1; y++) {
#ifdef BARYCENTRIC_INTERP
@@ -162,7 +310,7 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
/* place the vertex */
#ifdef BARYCENTRIC_INTERP
- {
+ if (use_interp_simple == false) {
float co_a[3], co_b[3];
barycentric_transform(
@@ -178,28 +326,34 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
interp_v3_v3v3(co, co_a, co_b, (float)y / ((float)ytot - 1));
}
-
-#else
- interp_v3_v3v3(
- co,
- v_grid[x]->co,
- v_grid[(xtot * ytot) + (x - xtot)]->co,
- (float)y / ((float)ytot - 1));
+ else
#endif
+ {
+ const float *w = weight_table[XY(x, y)];
+
+ zero_v3(co);
+ madd_v3_v3fl(co, v_grid[XY(x, 0)]->co, w[0]);
+ madd_v3_v3fl(co, v_grid[XY(0, y)]->co, w[1]);
+ madd_v3_v3fl(co, v_grid[XY(x, ytot - 1)]->co, w[2]);
+ madd_v3_v3fl(co, v_grid[XY(xtot - 1, y)]->co, w[3]);
+ }
- v = BM_vert_create(bm, co, NULL, 0);
+ v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
v_grid[(y * xtot) + x] = v;
/* interpolate only along one axis, this could be changed
* but from user pov gives predictable results since these are selected loop */
if (use_vert_interp) {
- void *v_cdata[2] = {
- v_grid[XY(x, 0)]->head.data,
- v_grid[XY(x, (ytot - 1))]->head.data,
+ const float *w = weight_table[XY(x, y)];
+
+ void *v_cdata[4] = {
+ v_grid[XY(x, 0)]->head.data,
+ v_grid[XY(0, y)]->head.data,
+ v_grid[XY(x, ytot - 1)]->head.data,
+ v_grid[XY(xtot - 1, y)]->head.data,
};
- const float t = (float)y / ((float)ytot - 1);
- const float w[2] = {1.0f - t, t};
- CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 2, v->head.data);
+
+ CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 4, v->head.data);
}
}
@@ -218,7 +372,7 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
v_grid[XY(x + 1, y + 1)], /* TR */
v_grid[XY(x + 1, y + 0)], /* BR */
NULL,
- false);
+ BM_CREATE_NOP);
}
else {
f = BM_face_create_quad_tri(
@@ -228,8 +382,88 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
v_grid[XY(x, y + 1)], /* TL */
v_grid[XY(x, y + 0)], /* BL */
NULL,
- false);
+ BM_CREATE_NOP);
+ }
+
+
+ if (use_loop_interp && (larr_x_a[x][0] || larr_y_a[y][0])) {
+ /* bottom/left/top/right */
+ BMLoop *l_quad[4];
+ BMLoop *l_bound[4];
+ BMLoop *l_tmp;
+ unsigned int x_side, y_side, i;
+ char interp_from;
+
+
+ if (larr_x_a[x][0] && larr_y_a[y][0]) {
+ interp_from = 'B'; /* B == both */
+ l_tmp = larr_x_a[x][0];
+ }
+ else if (larr_x_a[x][0]) {
+ interp_from = 'X';
+ l_tmp = larr_x_a[x][0];
+ }
+ else {
+ interp_from = 'Y';
+ l_tmp = larr_y_a[y][0];
+ }
+
+ BM_elem_attrs_copy(bm, bm, l_tmp->f, f);
+
+
+ BM_face_as_array_loop_quad(f, l_quad);
+
+ l_tmp = BM_FACE_FIRST_LOOP(f);
+
+ if (use_flip) {
+ l_quad[0] = l_tmp; l_tmp = l_tmp->next;
+ l_quad[1] = l_tmp; l_tmp = l_tmp->next;
+ l_quad[3] = l_tmp; l_tmp = l_tmp->next;
+ l_quad[2] = l_tmp;
+ }
+ else {
+ l_quad[2] = l_tmp; l_tmp = l_tmp->next;
+ l_quad[3] = l_tmp; l_tmp = l_tmp->next;
+ l_quad[1] = l_tmp; l_tmp = l_tmp->next;
+ l_quad[0] = l_tmp;
+ }
+
+ i = 0;
+
+ for (x_side = 0; x_side < 2; x_side++) {
+ for (y_side = 0; y_side < 2; y_side++) {
+ if (interp_from == 'B') {
+ const float *w = weight_table[XY(x + x_side, y + y_side)];
+ l_bound[0] = larr_x_a[x][x_side]; /* B */
+ l_bound[1] = larr_y_a[y][y_side]; /* L */
+ l_bound[2] = larr_x_b[x][x_side]; /* T */
+ l_bound[3] = larr_y_b[y][y_side]; /* R */
+
+ bm_loop_interp_from_grid_boundary_4(bm, l_quad[i++], l_bound, w);
+ }
+ else if (interp_from == 'X') {
+ const float t = (float)(y + y_side) / (float)(ytot - 1);
+ l_bound[0] = larr_x_a[x][x_side]; /* B */
+ l_bound[1] = larr_x_b[x][x_side]; /* T */
+
+ bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
+ }
+ else if (interp_from == 'Y') {
+ const float t = (float)(x + x_side) / (float)(xtot - 1);
+ l_bound[0] = larr_y_a[y][y_side]; /* L */
+ l_bound[1] = larr_y_b[y][y_side]; /* R */
+
+ bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
}
+ /* end interp */
+
+
BMO_elem_flag_enable(bm, f, FACE_OUT);
f->mat_nr = mat_nr;
if (use_smooth) {
@@ -237,22 +471,34 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
}
}
}
+
+ if (use_loop_interp) {
+ MEM_freeN(larr_x_a);
+ MEM_freeN(larr_y_a);
+ MEM_freeN(larr_x_b);
+ MEM_freeN(larr_y_b);
+ }
+
+ if (weight_table) {
+ MEM_freeN(weight_table);
+ }
+
#undef XY
}
static void bm_grid_fill(BMesh *bm,
struct BMEdgeLoopStore *estore_a, struct BMEdgeLoopStore *estore_b,
struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b,
- const short mat_nr, const bool use_smooth)
+ const short mat_nr, const bool use_smooth, const bool use_interp_simple)
{
#define USE_FLIP_DETECT
- const int xtot = BM_edgeloop_length_get(estore_a);
- const int ytot = BM_edgeloop_length_get(estore_rail_a);
+ const unsigned int xtot = (unsigned int)BM_edgeloop_length_get(estore_a);
+ const unsigned int ytot = (unsigned int)BM_edgeloop_length_get(estore_rail_a);
//BMVert *v;
- int i;
+ unsigned int i;
#ifdef DEBUG
- int x, y;
+ unsigned int x, y;
#endif
LinkData *el;
bool use_flip = false;
@@ -263,7 +509,7 @@ static void bm_grid_fill(BMesh *bm,
ListBase *lb_rail_a = BM_edgeloop_verts_get(estore_rail_a);
ListBase *lb_rail_b = BM_edgeloop_verts_get(estore_rail_b);
- BMVert **v_grid = MEM_callocN(sizeof(BMVert *) * xtot * ytot, __func__);
+ BMVert **v_grid = MEM_callocN(sizeof(BMVert *) * (size_t)(xtot * ytot), __func__);
/**
* <pre>
* estore_b
@@ -314,7 +560,7 @@ static void bm_grid_fill(BMesh *bm,
#endif
- bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip);
+ bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip, use_interp_simple);
MEM_freeN(v_grid);
#undef USE_FLIP_DETECT
@@ -322,7 +568,7 @@ static void bm_grid_fill(BMesh *bm,
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
{
- return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK);
+ return BMO_elem_flag_test_bool((BMesh *)bm_v, e, EDGE_MARK);
}
static bool bm_edge_test_rail_cb(BMEdge *e, void *UNUSED(bm_v))
@@ -343,8 +589,9 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
struct BMEdgeLoopStore *estore_rail_a, *estore_rail_b;
BMVert *v_a_first, *v_a_last;
BMVert *v_b_first, *v_b_last;
- const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
- const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+ const short mat_nr = (short)BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+ const bool use_interp_simple = BMO_slot_bool_get(op->slots_in, "use_interp_simple");
int count;
bool change = false;
@@ -436,9 +683,11 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
/* finally we have all edge loops needed */
bm_grid_fill(bm, estore_a, estore_b, estore_rail_a, estore_rail_b,
- mat_nr, use_smooth);
+ mat_nr, use_smooth, use_interp_simple);
change = true;
+
+
cleanup:
BM_mesh_edgeloops_free(&eloops);
BM_mesh_edgeloops_free(&eloops_rail);
diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c
index 40a682e790d..8160d28d7a7 100644
--- a/source/blender/bmesh/operators/bmo_fill_holes.c
+++ b/source/blender/bmesh/operators/bmo_fill_holes.c
@@ -28,110 +28,58 @@
#include "MEM_guardedalloc.h"
-#include "BLI_listbase.h"
-#include "BLI_alloca.h"
-#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_MARK 2
-#define ELE_OUT 4
-
-/**
- * Clone of BM_face_find_longest_loop that ensures the loop has an adjacent face
- */
-static BMLoop *bm_face_find_longest_loop_manifold(BMFace *f)
-{
- BMLoop *longest_loop = NULL;
- float longest_len = 0.0f;
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
-
- do {
- if (BM_edge_is_wire(l_iter->e) == false) {
- const float len = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
- if (len >= longest_len) {
- longest_loop = l_iter;
- longest_len = len;
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- return longest_loop;
-}
-
-static BMFace *bm_face_from_eloop(BMesh *bm, struct BMEdgeLoopStore *el_store)
-{
- LinkData *node = BM_edgeloop_verts_get(el_store)->first;
- const int len = BM_edgeloop_length_get(el_store);
- BMVert **f_verts = BLI_array_alloca(f_verts, len);
- BMFace *f;
- BMLoop *l;
- unsigned int i = 0;
-
- do {
- f_verts[i++] = node->data;
- } while ((node = node->next));
-
- f = BM_face_create_ngon_verts(bm, f_verts, len, 0, true, false);
- BM_face_copy_shared(bm, f);
-
- l = bm_face_find_longest_loop_manifold(f);
- if (l) {
- BMFace *f_other = l->radial_next->f;
- BLI_assert(l->radial_next != l);
- BM_elem_attrs_copy(bm, bm, f_other, f);
- }
-
- return f;
-}
-
-static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
-{
- return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK);
-}
-
void bmo_holes_fill_exec(BMesh *bm, BMOperator *op)
{
- ListBase eloops = {NULL, NULL};
- LinkData *el_store;
+ BMOperator op_attr;
+ const unsigned int sides = BMO_slot_int_get(op->slots_in, "sides");
- BMEdge *e;
- int count;
- BMOIter siter;
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
- const int sides = BMO_slot_int_get(op->slots_in, "sides");
+ BM_mesh_edgenet(bm, true, true); // TODO, sides
- /* clear tags */
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ /* bad - remove faces after as a workaround */
+ if (sides != 0) {
+ BMOIter siter;
+ BMFace *f;
- /* tag edges that may be apart of loops */
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- BMO_elem_flag_set(bm, e, EDGE_MARK, BM_edge_is_boundary(e));
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+ BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) {
+ if (f->len > sides) {
+ BM_face_kill(bm, f);
+ }
+ }
}
- count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, (void *)bm);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
- for (el_store = eloops.first; el_store; el_store = el_store->next) {
- if (BM_edgeloop_is_closed((struct BMEdgeLoopStore *)el_store)) {
- const int len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store);
- if ((sides == 0) || (len <= sides)) {
- BMFace *f;
+ /* --- Attribute Fill --- */
+ /* may as well since we have the faces already in a buffer */
+ BMO_op_initf(bm, &op_attr, op->flag,
+ "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+ op, "faces.out", true, true);
- f = bm_face_from_eloop(bm, (struct BMEdgeLoopStore *)el_store);
- BMO_elem_flag_enable(bm, f, ELE_OUT);
- }
- }
- }
+ BMO_op_exec(bm, &op_attr);
- (void)count;
+ /* check if some faces couldn't be touched */
+ if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
+ BMOIter siter;
+ BMFace *f;
- BM_mesh_edgeloops_free(&eloops);
+ BMO_ITER (f, &siter, op_attr.slots_out, "faces_fail.out", BM_FACE) {
+ BM_face_normal_update(f); /* normals are zero'd */
+ }
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
+ BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out");
+ }
+ BMO_op_finish(bm, &op_attr);
}
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 500e984f4c9..1737e27c84a 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -67,7 +67,7 @@ typedef struct HullTriangle {
/*************************** Hull Triangles ***************************/
-static void hull_add_triangle(BMesh *bm, GHash *hull_triangles, BLI_mempool *pool,
+static void hull_add_triangle(BMesh *bm, GSet *hull_triangles, BLI_mempool *pool,
BMVert *v1, BMVert *v2, BMVert *v3)
{
HullTriangle *t;
@@ -82,7 +82,7 @@ static void hull_add_triangle(BMesh *bm, GHash *hull_triangles, BLI_mempool *poo
for (i = 0; i < 3; i++)
BMO_elem_flag_disable(bm, t->v[i], HULL_FLAG_INTERIOR_ELE);
- BLI_ghash_insert(hull_triangles, t, NULL);
+ BLI_gset_insert(hull_triangles, t);
normal_tri_v3(t->no, v1->co, v2->co, v3->co);
}
@@ -102,12 +102,12 @@ static BMFace *hull_find_example_face(BMesh *bm, BMEdge *e)
return NULL;
}
-static void hull_output_triangles(BMesh *bm, GHash *hull_triangles)
+static void hull_output_triangles(BMesh *bm, GSet *hull_triangles)
{
- GHashIterator iter;
+ GSetIterator iter;
- GHASH_ITER (iter, hull_triangles) {
- HullTriangle *t = BLI_ghashIterator_getKey(&iter);
+ GSET_ITER (iter, hull_triangles) {
+ HullTriangle *t = BLI_gsetIterator_getKey(&iter);
int i;
if (!t->skip) {
@@ -135,8 +135,8 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles)
}
/* Create new hull face */
- f = BM_face_create_quad_tri_v(bm, t->v, 3, example, true);
- BM_face_copy_shared(bm, f);
+ f = BM_face_create_verts(bm, t->v, 3, example, BM_CREATE_NO_DOUBLE, true);
+ BM_face_copy_shared(bm, f, NULL, NULL);
}
/* Mark face for 'geom.out' slot and select */
BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
@@ -206,22 +206,22 @@ static int hull_final_edges_lookup(HullFinalEdges *final_edges,
}
/* Used for checking whether a pre-existing edge lies on the hull */
-static HullFinalEdges *hull_final_edges(GHash *hull_triangles)
+static HullFinalEdges *hull_final_edges(GSet *hull_triangles)
{
HullFinalEdges *final_edges;
- GHashIterator iter;
+ GSetIterator iter;
final_edges = MEM_callocN(sizeof(HullFinalEdges), "HullFinalEdges");
final_edges->edges = BLI_ghash_ptr_new("final edges ghash");
final_edges->base_pool = BLI_mempool_create(sizeof(ListBase), 128, 128, 0);
final_edges->link_pool = BLI_mempool_create(sizeof(LinkData), 128, 128, 0);
- GHASH_ITER (iter, hull_triangles) {
+ GSET_ITER (iter, hull_triangles) {
LinkData *link;
int i;
for (i = 0; i < 3; i++) {
- HullTriangle *t = BLI_ghashIterator_getKey(&iter);
+ HullTriangle *t = BLI_gsetIterator_getKey(&iter);
BMVert *v1 = t->v[i];
BMVert *v2 = t->v[(i + 1) % 3];
ListBase *adj;
@@ -259,13 +259,13 @@ static void hull_final_edges_free(HullFinalEdges *final_edges)
/**************************** Final Output ****************************/
-static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles,
+static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles,
HullFinalEdges *final_edges)
{
- GHashIterator hull_iter;
+ GSetIterator hull_iter;
- GHASH_ITER (hull_iter, hull_triangles) {
- HullTriangle *t = BLI_ghashIterator_getKey(&hull_iter);
+ GSET_ITER (hull_iter, hull_triangles) {
+ HullTriangle *t = BLI_gsetIterator_getKey(&hull_iter);
BMIter bm_iter1, bm_iter2;
BMFace *f;
bool f_on_hull;
@@ -444,7 +444,7 @@ static BMVert **hull_input_verts_copy(BMOperator *op,
static float (*hull_verts_for_bullet(BMVert **input_verts,
const int num_input_verts))[3]
{
- float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, AT);
+ float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, __func__);
int i;
for (i = 0; i < num_input_verts; i++) {
@@ -479,7 +479,7 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull,
}
static void hull_from_bullet(BMesh *bm, BMOperator *op,
- GHash *hull_triangles,
+ GSet *hull_triangles,
BLI_mempool *pool)
{
int *fvi = NULL;
@@ -556,7 +556,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op)
BLI_mempool *hull_pool;
BMElemF *ele;
BMOIter oiter;
- GHash *hull_triangles;
+ GSet *hull_triangles;
/* Verify that at least three verts in the input */
if (!hull_num_input_verts_is_ok(op)) {
@@ -575,7 +575,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op)
}
hull_pool = BLI_mempool_create(sizeof(HullTriangle), 128, 128, 0);
- hull_triangles = BLI_ghash_ptr_new("hull_triangles");
+ hull_triangles = BLI_gset_ptr_new("hull_triangles");
hull_from_bullet(bm, op, hull_triangles, hull_pool);
@@ -597,7 +597,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op)
hull_output_triangles(bm, hull_triangles);
BLI_mempool_destroy(hull_pool);
- BLI_ghash_free(hull_triangles, NULL, NULL);
+ BLI_gset_free(hull_triangles, NULL);
hull_tag_unused(bm, op);
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index a7b98cda2b3..20cd828af1e 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -32,6 +32,7 @@
#include "BLI_math.h"
#include "BLI_array.h"
+#include "BLI_alloca.h"
#include "BLI_memarena.h"
#include "BKE_customdata.h"
@@ -42,199 +43,263 @@
#define ELE_NEW 1
-
/* -------------------------------------------------------------------- */
-/* Inset Individual */
-
-
-/* Holds Per-Face Inset Edge Data */
-typedef struct EdgeInsetInfo {
- float no[3];
- BMEdge *e_old;
- BMEdge *e_new;
-} EdgeInsetInfo;
+/* Generic Interp Face (use for both types of inset) */
/**
- * Individual Face Inset.
- * Find all tagged faces (f), duplicate edges around faces, inset verts of
- * created edges, create new faces between old and new edges, fill face
- * between connected new edges, kill old face (f).
- */
-void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
-{
- BMEdge **f_edges = NULL;
- BMVert **f_verts = NULL;
+ * Interpolation, this is more complex for regions since we're not creating new faces
+ * and throwing away old ones, so instead, store face data needed for interpolation.
+ *
+ * \note This uses CustomData functions in quite a low-level way which should be
+ * avoided, but in this case its hard to do without storing a duplicate mesh. */
+
+/* just enough of a face to store interpolation data we can use once the inset is done */
+typedef struct InterpFace {
BMFace *f;
+ void **blocks_l;
+ void **blocks_v;
+ float (*cos_2d)[2];
+ float axis_mat[3][3];
+} InterpFace;
- BMOIter oiter;
- EdgeInsetInfo *eiinfo_arr = NULL;
+/* basically a clone of #BM_vert_interp_from_face */
+static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena)
+{
+ BMLoop *l_iter, *l_first;
+ void **blocks_l = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len);
+ void **blocks_v = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len);
+ float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len);
+ void *axis_mat = iface->axis_mat;
+ int i;
- BLI_array_declare(eiinfo_arr);
- BLI_array_declare(f_edges);
- BLI_array_declare(f_verts);
+ BLI_assert(BM_face_is_normal_valid(f));
- const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
- const float depth = BMO_slot_float_get(op->slots_in, "depth");
- const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
+ axis_dominant_v3_to_m3(axis_mat, f->no);
- /* Only tag faces in slot */
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ iface->f = f;
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks_l[i] = NULL;
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]);
+ /* if we were not modifying the loops later we would do... */
+ // blocks[i] = l_iter->head.data;
- BMO_ITER(f, &oiter, op->slots_in, "faces", BM_FACE) {
- BMFace *f_new_inner;
- BMLoop *l_iter, *l_first;
- BMLoop *l_iter_inner = NULL;
- int i;
-
- BLI_array_empty(f_verts);
- BLI_array_empty(f_edges);
- BLI_array_empty(eiinfo_arr);
- BLI_array_grow_items(f_verts, f->len);
- BLI_array_grow_items(f_edges, f->len);
- BLI_array_grow_items(eiinfo_arr, f->len);
-
- /* create verts */
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- f_verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0);
- i++;
- } while ((l_iter = l_iter->next) != l_first);
+ blocks_v[i] = NULL;
+ CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]);
- /* make edges */
- i = 0;
- l_iter = l_first;
- do {
- f_edges[i] = BM_edge_create(bm, f_verts[i], f_verts[(i + 1) % f->len], l_iter->e, 0);
+ /* use later for index lookups */
+ BM_elem_index_set(l_iter, i); /* set_ok */
+ } while (i++, (l_iter = l_iter->next) != l_first);
+}
+static void bm_interp_face_free(InterpFace *iface, BMesh *bm)
+{
+ void **blocks_l = iface->blocks_l;
+ void **blocks_v = iface->blocks_v;
+ int i;
- eiinfo_arr[i].e_new = f_edges[i];
- eiinfo_arr[i].e_old = l_iter->e;
- BM_edge_calc_face_tangent(l_iter->e, l_iter, eiinfo_arr[i].no);
+ for (i = 0; i < iface->f->len; i++) {
+ CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]);
+ CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]);
+ }
+}
- /* Tagging (old elements) required when iterating over edges
- * connected to verts for translation vector calculation */
- BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG);
- BM_elem_index_set(l_iter->e, i); /* set_dirty! */
- i++;
- } while ((l_iter = l_iter->next) != l_first);
- /* done with edges */
- bm->elem_index_dirty |= BM_EDGE;
+/* -------------------------------------------------------------------- */
+/* Inset Individual */
- /* Calculate translation vector for new */
- l_iter = l_first;
- do {
- EdgeInsetInfo *ei_prev = &eiinfo_arr[BM_elem_index_get(l_iter->prev->e)];
- EdgeInsetInfo *ei_next = &eiinfo_arr[BM_elem_index_get(l_iter->e)];
- float tvec[3];
- float v_new_co[3];
- int index = 0;
+static void bmo_face_inset_individual(
+ BMesh *bm, BMFace *f, MemArena *interp_arena,
+ const float thickness, const float depth,
+ const bool use_even_offset, const bool use_relative_offset, const bool use_interpolate)
+{
+ InterpFace *iface = NULL;
- add_v3_v3v3(tvec, ei_prev->no, ei_next->no);
- normalize_v3(tvec);
+ /* stores verts split away from the face (aligned with face verts) */
+ BMVert **verts = BLI_array_alloca(verts, f->len);
+ /* store edge normals (aligned with face-loop-edges) */
+ float (*edge_nors)[3] = BLI_array_alloca(edge_nors, f->len);
+ float (*coords)[3] = BLI_array_alloca(coords, f->len);
- /* l->e is traversed in order */
- index = BM_elem_index_get(l_iter->e);
+ BMLoop *l_iter, *l_first;
+ BMLoop *l_other;
+ unsigned int i;
+ float e_length_prev;
- copy_v3_v3(v_new_co, eiinfo_arr[index].e_new->v1->co);
+ l_first = BM_FACE_FIRST_LOOP(f);
- if (use_even_offset) {
- mul_v3_fl(tvec, shell_angle_to_dist(angle_normalized_v3v3(ei_prev->no, ei_next->no) / 2.0f));
- }
+ /* split off all loops */
+ l_iter = l_first;
+ i = 0;
+ do {
+ BMVert *v_other = l_iter->v;
+ BMVert *v_sep = BM_face_loop_separate(bm, l_iter);
+ if (v_sep == v_other) {
+ v_other = BM_vert_create(bm, l_iter->v->co, l_iter->v, BM_CREATE_NOP);
+ }
+ verts[i] = v_other;
- /* Modify vertices and their normals */
- if (use_relative_offset) {
- mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f);
- }
+ /* unrelated to splitting, but calc here */
+ BM_edge_calc_face_tangent(l_iter->e, l_iter, edge_nors[i]);
+ } while (i++, ((l_iter = l_iter->next) != l_first));
- madd_v3_v3fl(v_new_co, tvec, thickness);
- /* Set normal, add depth and write new vertex position*/
- copy_v3_v3(eiinfo_arr[index].e_new->v1->no, f->no);
+ /* build rim faces */
+ l_iter = l_first;
+ i = 0;
+ do {
+ BMFace *f_new_outer;
+ BMVert *v_other = verts[i];
+ BMVert *v_other_next = verts[(i + 1) % f->len];
+
+ BMEdge *e_other = BM_edge_create(bm, v_other, v_other_next, l_iter->e, BM_CREATE_NO_DOUBLE);
+ (void)e_other;
+
+ f_new_outer = BM_face_create_quad_tri(bm,
+ v_other,
+ v_other_next,
+ l_iter->next->v,
+ l_iter->v,
+ f, BM_CREATE_NOP);
+ BMO_elem_flag_enable(bm, f_new_outer, ELE_NEW);
+
+ /* copy loop data */
+ l_other = l_iter->radial_next;
+ BM_elem_attrs_copy(bm, bm, l_iter->next, l_other->prev);
+ BM_elem_attrs_copy(bm, bm, l_iter, l_other->next->next);
+
+ if (use_interpolate == false) {
+ BM_elem_attrs_copy(bm, bm, l_iter->next, l_other);
+ BM_elem_attrs_copy(bm, bm, l_iter, l_other->next);
+ }
+ } while (i++, ((l_iter = l_iter->next) != l_first));
- madd_v3_v3fl(v_new_co, f->no, depth);
+ /* hold interpolation values */
+ if (use_interpolate) {
+ iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
+ bm_interp_face_store(iface, bm, f, interp_arena);
+ }
- copy_v3_v3(eiinfo_arr[index].e_new->v1->co, v_new_co);
- } while ((l_iter = l_iter->next) != l_first);
+ /* Calculate translation vector for new */
+ l_iter = l_first;
+ i = 0;
+ if (depth != 0.0f) {
+ e_length_prev = BM_edge_calc_length(l_iter->prev->e);
+ }
- /* Create New Inset Faces */
- f_new_inner = BM_face_create(bm, f_verts, f_edges, f->len, 0);
- BLI_assert(f_new_inner != NULL); /* no reason it should fail */
+ do {
+ const float *eno_prev = edge_nors[(i ? i : f->len) - 1];
+ const float *eno_next = edge_nors[i];
+ float tvec[3];
+ float v_new_co[3];
+ add_v3_v3v3(tvec, eno_prev, eno_next);
+ normalize_v3(tvec);
- // Don't tag, gives more useful inner/outer select option
- // BMO_elem_flag_enable(bm, f_new_inner, ELE_NEW);
+ copy_v3_v3(v_new_co, l_iter->v->co);
+ if (use_even_offset) {
+ mul_v3_fl(tvec, shell_angle_to_dist(angle_normalized_v3v3(eno_prev, eno_next) / 2.0f));
+ }
- /* Copy Face Data */
- /* interpolate loop data or just stretch */
- if (use_interpolate) {
- BM_face_interp_from_face(bm, f_new_inner, f, true);
+ /* Modify vertices and their normals */
+ if (use_relative_offset) {
+ mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f);
}
- else {
- BM_elem_attrs_copy(bm, bm, f, f_new_inner);
+
+ madd_v3_v3fl(v_new_co, tvec, thickness);
+
+ /* Set normal, add depth and write new vertex position*/
+ copy_v3_v3(l_iter->v->no, f->no);
+
+ if (depth != 0.0f) {
+ const float e_length = BM_edge_calc_length(l_iter->e);
+ const float fac = depth * (use_relative_offset ? ((e_length_prev + e_length) * 0.5f) : 1.0f);
+ e_length_prev = e_length;
+
+ madd_v3_v3fl(v_new_co, f->no, fac);
}
- l_iter_inner = BM_FACE_FIRST_LOOP(f_new_inner);
+
+
+ copy_v3_v3(coords[i], v_new_co);
+ } while (i++, ((l_iter = l_iter->next) != l_first));
+
+ /* update the coords */
+ l_iter = l_first;
+ i = 0;
+ do {
+ copy_v3_v3(l_iter->v->co, coords[i]);
+ } while (i++, ((l_iter = l_iter->next) != l_first));
+
+
+ if (use_interpolate) {
+ BM_face_interp_from_face_ex(bm, iface->f, iface->f, true,
+ iface->blocks_l, iface->blocks_v, iface->cos_2d, iface->axis_mat);
+
+ /* build rim faces */
l_iter = l_first;
do {
- BMFace *f_new_outer;
+ /* copy loop data */
+ l_other = l_iter->radial_next;
- BMLoop *l_a;
- BMLoop *l_b;
-
- if (use_interpolate == false) {
- BM_elem_attrs_copy(bm, bm, l_iter, l_iter_inner);
- }
+ BM_elem_attrs_copy(bm, bm, l_iter->next, l_other);
+ BM_elem_attrs_copy(bm, bm, l_iter, l_other->next);
+ } while ((l_iter = l_iter->next) != l_first);
- f_new_outer = BM_face_create_quad_tri(bm,
- l_iter->v,
- l_iter->next->v,
- l_iter_inner->next->v,
- l_iter_inner->v,
- f, false);
+ bm_interp_face_free(iface, bm);
+ }
+}
- BLI_assert(f_new_outer != NULL); /* no reason it should fail */
- BM_elem_attrs_copy(bm, bm, f, f_new_outer);
- BMO_elem_flag_enable(bm, f_new_outer, ELE_NEW);
- BM_elem_flag_enable(f_new_outer, BM_ELEM_TAG);
+/**
+ * Individual Face Inset.
+ * Find all tagged faces (f), duplicate edges around faces, inset verts of
+ * created edges, create new faces between old and new edges, fill face
+ * between connected new edges, kill old face (f).
+ */
+void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
+{
+ BMFace *f;
- /* Copy Loop Data */
- l_a = BM_FACE_FIRST_LOOP(f_new_outer);
- l_b = l_a->next;
+ BMOIter oiter;
+ MemArena *interp_arena = NULL;
- /* first pair */
- BM_elem_attrs_copy(bm, bm, l_iter, l_a);
- BM_elem_attrs_copy(bm, bm, l_iter->next, l_b);
+ const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
+ const float depth = BMO_slot_float_get(op->slots_in, "depth");
+ const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
+ const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
+ const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
+ /* Only tag faces in slot */
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- /* Move to the last two loops in new face */
- l_a = l_b->next;
- l_b = l_a->next;
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
- /* This loop should always have >1 radials
- * (associated edge connects new and old face) */
- BM_elem_attrs_copy(bm, bm, l_iter_inner, l_b);
- BM_elem_attrs_copy(bm, bm, use_interpolate ? l_iter_inner->next : l_iter->next, l_a);
+ if (use_interpolate) {
+ interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
- } while ((l_iter_inner = l_iter_inner->next),
- (l_iter = l_iter->next) != l_first);
+ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
+ bmo_face_inset_individual(
+ bm, f, interp_arena,
+ thickness, depth,
+ use_even_offset, use_relative_offset, use_interpolate);
- BM_face_kill(bm, f);
+ if (use_interpolate) {
+ BLI_memarena_clear(interp_arena);
+ }
}
/* we could flag new edges/verts too, is it useful? */
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
- BLI_array_free(f_verts);
- BLI_array_free(f_edges);
- BLI_array_free(eiinfo_arr);
+ if (use_interpolate) {
+ BLI_memarena_free(interp_arena);
+ }
}
@@ -250,68 +315,6 @@ typedef struct SplitEdgeInfo {
BMLoop *l;
} SplitEdgeInfo;
-
-/**
- * Interpolation, this is more complex for regions since we're not creating new faces
- * and throwing away old ones, so instead, store face data needed for interpolation.
- *
- * \note This uses CustomData functions in quite a low-level way which should be
- * avoided, but in this case its hard to do without storing a duplicate mesh. */
-
-/* just enough of a face to store interpolation data we can use once the inset is done */
-typedef struct InterpFace {
- BMFace *f;
- void **blocks_l;
- void **blocks_v;
- float (*cos_2d)[2];
- float axis_mat[3][3];
-} InterpFace;
-
-/* basically a clone of #BM_vert_interp_from_face */
-static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena)
-{
- BMLoop *l_iter, *l_first;
- void **blocks_l = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len);
- void **blocks_v = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len);
- float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len);
- void *axis_mat = iface->axis_mat;
- int i;
-
- BLI_assert(BM_face_is_normal_valid(f));
-
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
- iface->f = f;
-
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
- blocks_l[i] = NULL;
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]);
- /* if we were not modifying the loops later we would do... */
- // blocks[i] = l_iter->head.data;
-
- blocks_v[i] = NULL;
- CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]);
-
- /* use later for index lookups */
- BM_elem_index_set(l_iter, i); /* set_ok */
- } while (i++, (l_iter = l_iter->next) != l_first);
-}
-static void bm_interp_face_free(InterpFace *iface, BMesh *bm)
-{
- void **blocks_l = iface->blocks_l;
- void **blocks_v = iface->blocks_v;
- int i;
-
- for (i = 0; i < iface->f->len; i++) {
- CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]);
- CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]);
- }
-}
-
-
/**
* return the tag loop where there is...
* - only 1 tagged face attached to this edge.
@@ -350,6 +353,27 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l)
}
}
+static float bm_edge_info_average_length(BMVert *v, SplitEdgeInfo *edge_info)
+{
+ BMIter iter;
+ BMEdge *e;
+
+ float len = 0.0f;
+ int tot = 0;
+
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ const int i = BM_elem_index_get(e);
+ if (i != -1) {
+ len += edge_info[i].length;
+ tot++;
+ }
+ }
+
+ BLI_assert(tot != 0);
+ return len / (float)tot;
+}
+
/**
* implementation is as follows...
*
@@ -465,7 +489,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
if (es->e_new == es->e_old) { /* happens on boundary edges */
/* take care here, we're creating this double edge which _must_ have its verts replaced later on */
- es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, 0);
+ es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, BM_CREATE_NOP);
}
/* store index back to original in 'edge_info' */
@@ -508,8 +532,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
mid_v3_v3v3(tvec, es->e_new->v1->co, es->e_new->v2->co);
- v1 = BM_vert_create(bm, tvec, NULL);
- v2 = BM_vert_create(bm, tvec, NULL);
+ v1 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
+ v2 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
madd_v3_v3fl(v2->co, es->no, 0.1f);
BM_edge_create(bm, v1, v2, NULL, 0);
}
@@ -787,7 +811,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
#endif
/* no need to check doubles, we KNOW there won't be any */
/* yes - reverse face is correct in this case */
- f = BM_face_create_quad_tri_v(bm, varr, j, es->l->f, false);
+ f = BM_face_create_verts(bm, varr, j, es->l->f, BM_CREATE_NOP, true);
BMO_elem_flag_enable(bm, f, ELE_NEW);
/* copy for loop data, otherwise UV's and vcols are no good.
@@ -796,7 +820,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
#if 0
/* don't use this because face boundaries have no adjacent loops and won't be filled in.
* instead copy from the opposite side with the code below */
- BM_face_copy_shared(bm, f);
+ BM_face_copy_shared(bm, f, NULL, NULL);
#else
{
/* 2 inner loops on the edge between the new face and the original */
@@ -894,7 +918,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
const float fac = (depth *
- (use_relative_offset ? BM_vert_calc_mean_tagged_edge_length(v) : 1.0f) *
+ (use_relative_offset ? bm_edge_info_average_length(v, edge_info) : 1.0f) *
(use_even_boundry ? BM_vert_calc_shell_factor(v) : 1.0f));
madd_v3_v3v3fl(varr_co[i], v->co, v->no, fac);
}
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 12065743136..6562f26062f 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -34,6 +34,7 @@
#include "DNA_meshdata_types.h"
#include "BLI_math.h"
+#include "BLI_sort_utils.h"
#include "BKE_customdata.h"
@@ -181,10 +182,6 @@ static bool bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const bool do_uv, const bool
return true;
}
-typedef struct JoinEdge {
- float weight;
- BMEdge *e;
-} JoinEdge;
#define EDGE_MARK 1
#define EDGE_CHOSEN 2
@@ -192,14 +189,7 @@ typedef struct JoinEdge {
#define FACE_MARK 1
#define FACE_INPUT 2
-static int fplcmp(const void *v1, const void *v2)
-{
- const JoinEdge *e1 = (JoinEdge *)v1, *e2 = (JoinEdge *)v2;
- if (e1->weight > e2->weight) return 1;
- else if (e1->weight < e2->weight) return -1;
- else return 0;
-}
void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
{
@@ -213,8 +203,9 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BMIter iter;
BMOIter siter;
BMFace *f;
- BMEdge *e;
- JoinEdge *jedges = NULL;
+ BMEdge *e, *e_next;
+ /* data: edge-to-join, sort_value: error weight */
+ struct SortPointerByFloat *jedges;
unsigned i, totedge;
unsigned int totedge_tag = 0;
@@ -271,19 +262,19 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
measure = measure_facepair(v1->co, v2->co, v3->co, v4->co, limit);
if (measure < limit) {
- jedges[i].e = e;
- jedges[i].weight = measure;
+ jedges[i].data = e;
+ jedges[i].sort_value = measure;
i++;
}
}
totedge = i;
- qsort(jedges, totedge, sizeof(JoinEdge), fplcmp);
+ qsort(jedges, totedge, sizeof(*jedges), BLI_sortutil_cmp_float);
for (i = 0; i < totedge; i++) {
BMFace *f_a, *f_b;
- e = jedges[i].e;
+ e = jedges[i].data;
f_a = e->l->f;
f_b = e->l->radial_next->f;
@@ -300,7 +291,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
MEM_freeN(jedges);
/* join best weighted */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
BMFace *f_new;
BMFace *f_a, *f_b;
@@ -317,7 +308,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
}
/* join 2-tri islands */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
BMLoop *l_a, *l_b;
BMFace *f_a, *f_b;
@@ -335,7 +326,11 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
(BMO_elem_flag_test(bm, l_a->next->e, EDGE_MARK) == false) &&
(BMO_elem_flag_test(bm, l_a->prev->e, EDGE_MARK) == false) &&
(BMO_elem_flag_test(bm, l_b->next->e, EDGE_MARK) == false) &&
- (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false))
+ (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false) &&
+ /* check for faces that use same verts, this is supported but raises an error
+ * and cancels the operation when performed from editmode, since this is only
+ * two triangles we only need to compare a single vertex */
+ (LIKELY(l_a->prev->v != l_b->prev->v)))
{
BMFace *f_new;
f_new = BM_faces_join_pair(bm, f_a, f_b, e, true);
diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c
index 025b8557331..1eaa0695ad2 100644
--- a/source/blender/bmesh/operators/bmo_normals.c
+++ b/source/blender/bmesh/operators/bmo_normals.c
@@ -29,6 +29,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_linklist_stack.h"
#include "bmesh.h"
@@ -46,7 +47,7 @@ static bool bmo_recalc_normal_edge_filter_cb(BMElem *ele, void *UNUSED(user_data
}
/**
- * Given an array of faces, recalcualte their normals.
+ * Given an array of faces, recalculate their normals.
* this functions assumes all faces in the array are connected by edges.
*
* \param bm
@@ -65,8 +66,7 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f
float f_len_best;
BMFace *f;
- BMFace **fstack = MEM_mallocN(sizeof(*fstack) * faces_len, __func__);
- STACK_DECLARE(fstack);
+ BLI_LINKSTACK_DECLARE(fstack, BMFace *);
zero_v3(cent);
@@ -77,6 +77,7 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f
madd_v3_v3fl(cent, f_cent, cent_fac);
BLI_assert(BMO_elem_flag_test(bm, faces[i], FACE_TEMP) == 0);
+ BLI_assert(BM_face_is_normal_valid(faces[i]));
}
f_len_best = -FLT_MAX;
@@ -102,12 +103,12 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f
* have the same winding. this is done recursively, using a manual
* stack (if we use simple function recursion, we'd end up overloading
* the stack on large meshes). */
- STACK_INIT(fstack);
+ BLI_LINKSTACK_INIT(fstack);
- STACK_PUSH(fstack, faces[f_start_index]);
+ BLI_LINKSTACK_PUSH(fstack, faces[f_start_index]);
BMO_elem_flag_enable(bm, faces[f_start_index], FACE_TEMP);
- while ((f = STACK_POP(fstack))) {
+ while ((f = BLI_LINKSTACK_POP(fstack))) {
const bool flip_state = BMO_elem_flag_test_bool(bm, f, FACE_FLIP);
BMLoop *l_iter, *l_first;
@@ -119,13 +120,13 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f
if (!BMO_elem_flag_test(bm, l_other->f, FACE_TEMP)) {
BMO_elem_flag_enable(bm, l_other->f, FACE_TEMP);
BMO_elem_flag_set(bm, l_other->f, FACE_FLIP, (l_other->v == l_iter->v) != flip_state);
- STACK_PUSH(fstack, l_other->f);
+ BLI_LINKSTACK_PUSH(fstack, l_other->f);
}
}
} while ((l_iter = l_iter->next) != l_first);
}
- MEM_freeN(fstack);
+ BLI_LINKSTACK_FREE(fstack);
/* apply flipping to oflag'd faces */
for (i = 0; i < faces_len; i++) {
diff --git a/source/blender/bmesh/operators/bmo_poke.c b/source/blender/bmesh/operators/bmo_poke.c
index 03084ebb1b6..26f20656478 100644
--- a/source/blender/bmesh/operators/bmo_poke.c
+++ b/source/blender/bmesh/operators/bmo_poke.c
@@ -65,10 +65,10 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op)
break;
default:
BLI_assert(0);
- break;
+ return;
}
- BMO_ITER(f, &oiter, op->slots_in, "faces", BM_FACE) {
+ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
BMFace *f_new;
float f_center[3];
BMVert *v_center = NULL;
@@ -83,7 +83,7 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op)
int i;
bm_face_calc_center_fn(f, f_center);
- v_center = BM_vert_create(bm, f_center, NULL, 0);
+ v_center = BM_vert_create(bm, f_center, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v_center, ELE_NEW);
/* handled by BM_loop_interp_from_face */
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 9f17c1dd8e3..45653f3411f 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -249,7 +249,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
vec[2] = 0.0f;
mul_m4_v3(mat, vec);
- eve = BM_vert_create(bm, vec, NULL, 0);
+ eve = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, eve, VERT_MARK);
if (a != 0) {
@@ -318,11 +318,11 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
vec[0] = -dia * sinf(phi);
vec[1] = 0.0;
vec[2] = dia * cosf(phi);
- eve = BM_vert_create(bm, vec, NULL, 0);
+ eve = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, eve, VERT_MARK);
if (a != 0) {
- e = BM_edge_create(bm, preveve, eve, NULL, 0);
+ e = BM_edge_create(bm, preveve, eve, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, e, EDGE_ORIG);
}
@@ -408,7 +408,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
vec[0] = dia_div * icovert[a][0];
vec[1] = dia_div * icovert[a][1];
vec[2] = dia_div * icovert[a][2];
- eva[a] = BM_vert_create(bm, vec, NULL, 0);
+ eva[a] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, eva[a], VERT_MARK);
}
@@ -471,12 +471,12 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
v[0] = (monkeyv[i][0] + 127) / 128.0, v[1] = monkeyv[i][1] / 128.0, v[2] = monkeyv[i][2] / 128.0;
- tv[i] = BM_vert_create(bm, v, NULL, 0);
+ tv[i] = BM_vert_create(bm, v, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, tv[i], VERT_MARK);
tv[monkeynv + i] = (fabsf(v[0] = -v[0]) < 0.001f) ?
tv[i] :
- (eve = BM_vert_create(bm, v, NULL, 0), mul_m4_v3(mat, eve->co), eve);
+ (eve = BM_vert_create(bm, v, NULL, BM_CREATE_NOP), mul_m4_v3(mat, eve->co), eve);
BMO_elem_flag_enable(bm, tv[monkeynv + i], VERT_MARK);
@@ -528,7 +528,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
zero_v3(vec);
mul_m4_v3(mat, vec);
- cent1 = BM_vert_create(bm, vec, NULL, 0);
+ cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, cent1, VERT_MARK);
}
@@ -538,12 +538,12 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
vec[1] = dia * cosf(phi);
vec[2] = 0.0f;
mul_m4_v3(mat, vec);
- v1 = BM_vert_create(bm, vec, NULL, 0);
+ v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v1, VERT_MARK);
if (lastv1)
- BM_edge_create(bm, v1, lastv1, NULL, 0);
+ BM_edge_create(bm, v1, lastv1, NULL, BM_CREATE_NOP);
if (a && cap_ends) {
BMFace *f;
@@ -603,13 +603,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
vec[2] = -depth;
mul_m4_v3(mat, vec);
- cent1 = BM_vert_create(bm, vec, NULL, 0);
+ cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
vec[0] = vec[1] = 0.0f;
vec[2] = depth;
mul_m4_v3(mat, vec);
- cent2 = BM_vert_create(bm, vec, NULL, 0);
+ cent2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, cent1, VERT_MARK);
BMO_elem_flag_enable(bm, cent2, VERT_MARK);
@@ -620,13 +620,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
vec[1] = dia1 * cosf(phi);
vec[2] = -depth;
mul_m4_v3(mat, vec);
- v1 = BM_vert_create(bm, vec, NULL, 0);
+ v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
vec[0] = dia2 * sinf(phi);
vec[1] = dia2 * cosf(phi);
vec[2] = depth;
mul_m4_v3(mat, vec);
- v2 = BM_vert_create(bm, vec, NULL, 0);
+ v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v1, VERT_MARK);
BMO_elem_flag_enable(bm, v2, VERT_MARK);
@@ -686,56 +686,56 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
vec[1] = -off;
vec[2] = -off;
mul_m4_v3(mat, vec);
- v1 = BM_vert_create(bm, vec, NULL, 0);
+ v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v1, VERT_MARK);
vec[0] = -off;
vec[1] = off;
vec[2] = -off;
mul_m4_v3(mat, vec);
- v2 = BM_vert_create(bm, vec, NULL, 0);
+ v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v2, VERT_MARK);
vec[0] = off;
vec[1] = off;
vec[2] = -off;
mul_m4_v3(mat, vec);
- v3 = BM_vert_create(bm, vec, NULL, 0);
+ v3 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v3, VERT_MARK);
vec[0] = off;
vec[1] = -off;
vec[2] = -off;
mul_m4_v3(mat, vec);
- v4 = BM_vert_create(bm, vec, NULL, 0);
+ v4 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v4, VERT_MARK);
vec[0] = -off;
vec[1] = -off;
vec[2] = off;
mul_m4_v3(mat, vec);
- v5 = BM_vert_create(bm, vec, NULL, 0);
+ v5 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v5, VERT_MARK);
vec[0] = -off;
vec[1] = off;
vec[2] = off;
mul_m4_v3(mat, vec);
- v6 = BM_vert_create(bm, vec, NULL, 0);
+ v6 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v6, VERT_MARK);
vec[0] = off;
vec[1] = off;
vec[2] = off;
mul_m4_v3(mat, vec);
- v7 = BM_vert_create(bm, vec, NULL, 0);
+ v7 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v7, VERT_MARK);
vec[0] = off;
vec[1] = -off;
vec[2] = off;
mul_m4_v3(mat, vec);
- v8 = BM_vert_create(bm, vec, NULL, 0);
+ v8 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
BMO_elem_flag_enable(bm, v8, VERT_MARK);
/* the four sides */
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index da70e201976..cc5a635092a 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -71,32 +71,11 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot
#define EDGE_COL 2
#define FACE_MARK 2
-#if 0
-int remdoubles_face_overlaps(BMesh *bm, BMVert **varr,
- int len, BMFace *exclude,
- BMFace **overlapface)
-{
- BMIter vertfaces;
- BMFace *f;
- int i, amount;
-
- if (overlapface) *overlapface = NULL;
-
- for (i = 0; i < len; i++) {
- f = BM_iter_new(&vertfaces, bm, BM_FACES_OF_VERT, varr[i]);
- while (f) {
- amount = BM_verts_in_face(bm, f, varr, len);
- if (amount >= len) {
- if (overlapface) *overlapface = f;
- return true;
- }
- f = BM_iter_step(&vertfaces);
- }
- }
- return false;
-}
-#endif
-
+/**
+ * \note with 'targetmap', multiple 'keys' are currently supported, though no callers should be using.
+ * (because slot maps currently use GHash without the GHASH_FLAG_ALLOW_DUPES flag set)
+ *
+ */
void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
{
BMIter iter, liter;
@@ -215,10 +194,8 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
v2 = BMO_slot_map_elem_get(slot_targetmap, v2);
}
- f_new = BM_face_create_ngon(bm, v, v2, edges, a, BM_CREATE_NO_DOUBLE);
+ f_new = BM_face_create_ngon(bm, v, v2, edges, a, f, BM_CREATE_NO_DOUBLE);
if (f_new && (f_new != f)) {
- BM_elem_attrs_copy(bm, bm, f, f_new);
-
a = 0;
BM_ITER_ELEM (l, &liter, f_new, BM_LOOPS_OF_FACE) {
l_new = loops[a];
@@ -377,7 +354,7 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BMEdge *e, **edges = NULL;
BLI_array_declare(edges);
float min[3], max[3], center[3];
- int i, tot;
+ unsigned int i, tot;
BMOpSlot *slot_targetmap;
BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
@@ -392,6 +369,8 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
BMW_NIL_LAY);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BMVert *v_tar;
+
if (!BMO_elem_flag_test(bm, e, EDGE_MARK))
continue;
@@ -404,19 +383,29 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
minmax_v3v3_v3(min, max, e->v1->co);
minmax_v3v3_v3(min, max, e->v2->co);
+
+ /* prevent adding to slot_targetmap multiple times */
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
}
mid_v3_v3v3(center, min, max);
/* snap edges to a point. for initial testing purposes anyway */
+ v_tar = edges[0]->v1;
+
for (i = 0; i < tot; i++) {
- copy_v3_v3(edges[i]->v1->co, center);
- copy_v3_v3(edges[i]->v2->co, center);
-
- if (edges[i]->v1 != edges[0]->v1)
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v1, edges[0]->v1);
- if (edges[i]->v2 != edges[0]->v1)
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1);
+ unsigned int j;
+
+ for (j = 0; j < 2; j++) {
+ BMVert *v_src = *((&edges[i]->v1) + j);
+
+ copy_v3_v3(v_src->co, center);
+ if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v_src, BM_ELEM_TAG);
+ BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
+ }
+ }
}
}
@@ -521,13 +510,18 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op,
for (i = 0; i < verts_len; i++) {
BMVert *v_check = verts[i];
- if (BMO_elem_flag_test(bm, v_check, VERT_DOUBLE)) {
+ if (BMO_elem_flag_test(bm, v_check, VERT_DOUBLE | VERT_TARGET)) {
continue;
}
for (j = i + 1; j < verts_len; j++) {
BMVert *v_other = verts[j];
+ /* a match has already been found, (we could check which is best, for now don't) */
+ if (BMO_elem_flag_test(bm, v_other, VERT_DOUBLE | VERT_TARGET)) {
+ continue;
+ }
+
/* Compare sort values of the verts using 3x tolerance (allowing for the tolerance
* on each of the three axes). This avoids the more expensive length comparison
* for most vertex pairs. */
diff --git a/source/blender/bmesh/operators/bmo_split_edges.c b/source/blender/bmesh/operators/bmo_split_edges.c
index 7eea4c4878d..eb7946caff0 100644
--- a/source/blender/bmesh/operators/bmo_split_edges.c
+++ b/source/blender/bmesh/operators/bmo_split_edges.c
@@ -29,6 +29,7 @@
#include "BLI_utildefines.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h" /* own include */
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index e669585a857..b3b9cecf389 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -921,7 +921,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
if (BMO_elem_flag_test(bm, face, FACE_CUSTOMFILL)) {
- pat = BMO_slot_map_data_get(params.slot_custom_patterns, face);
+ pat = *BMO_slot_map_data_get(params.slot_custom_patterns, face);
for (i = 0; i < pat->len; i++) {
matched = 1;
for (j = 0; j < pat->len; j++) {
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index fa39ae68cdf..13a7aa09335 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -203,7 +203,7 @@ finally:
/* -------------------------------------------------------------------- */
/* Edge Loop Pairs */
/* key (ordered loop pointers) */
-static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
+static GSet *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
{
/**
* Method for for finding pairs:
@@ -219,7 +219,7 @@ static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
* could sort and optimize this but not really so important.
*/
- GHash *eloop_pair_gh = BLI_ghash_pair_new(__func__);
+ GSet *eloop_pair_gs = BLI_gset_pair_new(__func__);
GHash *vert_eloop_gh = BLI_ghash_ptr_new(__func__);
struct BMEdgeLoopStore *el_store;
@@ -256,9 +256,9 @@ static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
if (pair_test.first > pair_test.second)
SWAP(const void *, pair_test.first, pair_test.second);
- if (!BLI_ghash_haskey(eloop_pair_gh, &pair_test)) {
+ if (!BLI_gset_haskey(eloop_pair_gs, &pair_test)) {
GHashPair *pair = BLI_ghashutil_pairalloc(pair_test.first, pair_test.second);
- BLI_ghash_insert(eloop_pair_gh, pair, NULL);
+ BLI_gset_insert(eloop_pair_gs, pair);
}
}
@@ -268,12 +268,12 @@ static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
BLI_ghash_free(vert_eloop_gh, NULL, NULL);
- if (BLI_ghash_size(eloop_pair_gh) == 0) {
- BLI_ghash_free(eloop_pair_gh, NULL, NULL);
- eloop_pair_gh = NULL;
+ if (BLI_gset_size(eloop_pair_gs) == 0) {
+ BLI_gset_free(eloop_pair_gs, NULL);
+ eloop_pair_gs = NULL;
}
- return eloop_pair_gh;
+ return eloop_pair_gs;
}
@@ -919,13 +919,13 @@ static void bm_edgering_pair_order(BMesh *bm,
}
BLI_assert(node != NULL);
- BLI_rotatelist(lb_b, node);
+ BLI_rotatelist_first(lb_b, node);
/* now check we are winding the same way */
if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) {
BM_edgeloop_flip(bm, el_store_b);
/* re-ensure the first node */
- BLI_rotatelist(lb_b, node);
+ BLI_rotatelist_first(lb_b, node);
}
/* sanity checks that we are aligned & winding now */
@@ -1175,23 +1175,23 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
}
}
else {
- GHashIterator gh_iter;
+ GSetIterator gs_iter;
int i;
- GHash *eloop_pairs_gh = bm_edgering_pair_calc(bm, &eloops_rim);
+ GSet *eloop_pairs_gs = bm_edgering_pair_calc(bm, &eloops_rim);
LoopPairStore **lpair_arr;
- if (eloop_pairs_gh == NULL) {
+ if (eloop_pairs_gs == NULL) {
BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
"Edge-rings are not connected");
goto cleanup;
}
- lpair_arr = BLI_array_alloca(lpair_arr, BLI_ghash_size(eloop_pairs_gh));
+ lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_size(eloop_pairs_gs));
/* first cache pairs */
- GHASH_ITER_INDEX (gh_iter, eloop_pairs_gh, i) {
- GHashPair *eloop_pair = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) {
+ GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
LoopPairStore *lpair;
@@ -1207,8 +1207,8 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
BLI_assert(bm_verts_tag_count(bm) == 0);
}
- GHASH_ITER_INDEX (gh_iter, eloop_pairs_gh, i) {
- GHashPair *eloop_pair = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) {
+ GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
LoopPairStore *lpair = lpair_arr[i];
@@ -1222,7 +1222,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
BLI_assert(bm_verts_tag_count(bm) == 0);
}
- BLI_ghash_free(eloop_pairs_gh, MEM_freeN, NULL);
+ BLI_gset_free(eloop_pairs_gs, MEM_freeN);
}
cleanup:
diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index b684240dc76..4b538dccb4e 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor(s): Nicholas Bishop
+ * Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -29,656 +29,81 @@
#include "MEM_guardedalloc.h"
-#include "BLI_array.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "bmesh.h"
#include "intern/bmesh_operators_private.h"
-enum {
- SYMM_OUTPUT_GEOM = (1 << 0)
-};
-
-/* Note: don't think there's much need to make these user-adjustable? */
-#define SYMM_AXIS_THRESHOLD 0.00002f
-#define SYMM_VERT_THRESHOLD 0.00002f
-
-typedef enum {
- /* Coordinate lies on the side being copied from */
- SYMM_SIDE_KEEP,
- /* Coordinate lies on the side being copied from and within the
- * axis threshold */
- SYMM_SIDE_AXIS,
- /* Coordinate lies on the side being copied to */
- SYMM_SIDE_KILL
-} SymmSide;
-
-typedef struct {
- BMesh *bm;
- BMOperator *op;
-
- int axis;
- BMO_SymmDirection direction;
-
- /* Maps from input vertices to their mirrors. If the vertex
- * doesn't have a mirror, it's not in this map. If the vertex is
- * within the axis threshold, it's mapped to itself. */
- GHash *vert_symm_map;
-
- /* Edges that cross the symmetry plane and are asymmetric get
- * split. This map goes from input edges to output vertices. If an
- * edge is not split, it's not in this map. */
- GHash *edge_split_map;
-} Symm;
-
-/* Return which side the coordinate lies on */
-static SymmSide symm_co_side(const Symm *symm,
- const float *co)
-{
- float comp = co[symm->axis];
- if (ELEM3(symm->direction,
- BMO_SYMMETRIZE_NEGATIVE_X,
- BMO_SYMMETRIZE_NEGATIVE_Y,
- BMO_SYMMETRIZE_NEGATIVE_Z))
- {
- comp = -comp;
- }
-
- if (comp >= 0) {
- if (comp < SYMM_AXIS_THRESHOLD)
- return SYMM_SIDE_AXIS;
- else
- return SYMM_SIDE_KEEP;
- }
- else
- return SYMM_SIDE_KILL;
-}
-
-/* Output vertices and the vert_map array */
-static void symm_verts_mirror(Symm *symm)
-{
- BMOIter oiter;
- BMVert *src_v, *dst_v;
-
- symm->vert_symm_map = BLI_ghash_ptr_new(AT);
-
- BMO_ITER (src_v, &oiter, symm->op->slots_in, "input", BM_VERT) {
- SymmSide side = symm_co_side(symm, src_v->co);
- float co[3];
-
- switch (side) {
- case SYMM_SIDE_KEEP:
- /* The vertex is outside the axis area; output its mirror */
- copy_v3_v3(co, src_v->co);
- co[symm->axis] = -co[symm->axis];
-
- dst_v = BM_vert_create(symm->bm, co, src_v, 0);
- BMO_elem_flag_enable(symm->bm, dst_v, SYMM_OUTPUT_GEOM);
- BLI_ghash_insert(symm->vert_symm_map, src_v, dst_v);
- break;
-
- case SYMM_SIDE_AXIS:
- /* The vertex is within the axis area, snap to center */
- src_v->co[symm->axis] = 0;
- /* Vertex isn't copied, map to itself */
- BLI_ghash_insert(symm->vert_symm_map, src_v, src_v);
- break;
-
- case SYMM_SIDE_KILL:
- /* The vertex does not lie in the half-space being
- * copied from, nothing to do */
- break;
- }
- }
-}
-
-static int symm_edge_crosses_axis(const Symm *symm, const BMEdge *e)
-{
- const int sides[2] = {symm_co_side(symm, e->v1->co),
- symm_co_side(symm, e->v2->co)};
-
- return ((sides[0] != SYMM_SIDE_AXIS) &&
- (sides[1] != SYMM_SIDE_AXIS) &&
- (sides[0] != sides[1]));
-}
-
-/* Output edge split vertices for asymmetric edges and the edge_splits
- * mapping array */
-static void symm_split_asymmetric_edges(Symm *symm)
-{
- BMOIter oiter;
- BMEdge *e;
-
- symm->edge_split_map = BLI_ghash_ptr_new(AT);
-
- BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
- float flipped[3];
-
- copy_v3_v3(flipped, e->v1->co);
- flipped[symm->axis] = -flipped[symm->axis];
-
- if (symm_edge_crosses_axis(symm, e) &&
- (!compare_v3v3(e->v2->co, flipped, SYMM_VERT_THRESHOLD)))
- {
- /* Endpoints lie on opposite sides and are asymmetric */
-
- BMVert *v;
- float lambda = 0, edge_dir[3], co[3];
- float plane_co[3][3][3] = {
- /* axis == 0 */
- {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}},
- /* axis == 1 */
- {{0, 0, 0}, {1, 0, 0}, {0, 0, 1}},
- /* axis == 2 */
- {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}},
- };
- int r;
-
- /* Find intersection of edge with symmetry plane */
- sub_v3_v3v3(edge_dir, e->v2->co, e->v1->co);
- normalize_v3(edge_dir);
- r = isect_ray_plane_v3(e->v1->co,
- edge_dir,
- plane_co[symm->axis][0],
- plane_co[symm->axis][1],
- plane_co[symm->axis][2],
- &lambda, true);
- BLI_assert(r);
-
- madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda);
- co[symm->axis] = 0;
-
- /* Edge is asymmetric, split it with a new vertex */
- v = BM_vert_create(symm->bm, co, e->v1, 0);
- BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM);
- BLI_ghash_insert(symm->edge_split_map, e, v);
- }
- }
-}
-
-static void symm_mirror_edges(Symm *symm)
-{
- BMOIter oiter;
- BMEdge *e;
-
- BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
- BMVert *v1 = NULL, *v2 = NULL;
- BMEdge *e_new;
-
- v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1);
- v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2);
-
- if (v1 && v2) {
- e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- }
- else if (v1 || v2) {
- if (BLI_ghash_haskey(symm->edge_split_map, e)) {
- BMVert *v_split = BLI_ghash_lookup(symm->edge_split_map, e);
-
- /* Output the keep side of the split edge */
- if (!v1) {
- e_new = BM_edge_create(symm->bm, v_split, e->v2, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- v1 = v_split;
- }
- else {
- e_new = BM_edge_create(symm->bm, e->v1, v_split, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- v2 = v_split;
- }
-
- /* Output the kill side of the split edge */
- e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- }
- }
- }
-}
-
-/****************************** SymmPoly ******************************/
-
-typedef struct {
- /* Indices into the source mvert array (or -1 if not in that array) */
- BMVert **src_verts;
- /* Indices into the destination mvert array, these are vertices
- * created by an edge split (-1 for vertices not created by edge
- * split) */
- BMVert **edge_verts;
-
- /* Number of vertices in the polygon */
- int len;
-
- /* True only if none of the polygon's edges were split */
- bool already_symmetric;
-
- BMFace *src_face;
-} SymmPoly;
-
-static void symm_poly_with_splits(const Symm *symm,
- BMFace *f,
- SymmPoly *out)
-{
- BMIter iter;
- BMLoop *l;
- int i;
-
- out->src_face = f;
-
- /* Count vertices and check for edge splits */
- out->len = f->len;
- out->already_symmetric = true;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- if (BLI_ghash_haskey(symm->edge_split_map, l->e)) {
- out->len++;
- out->already_symmetric = false;
- }
- }
-
- i = 0;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- BMVert *split = BLI_ghash_lookup(symm->edge_split_map, l->e);
-
- out->src_verts[i] = l->v;
- out->edge_verts[i] = NULL;
- i++;
-
- if (split) {
- out->src_verts[i] = NULL;
- out->edge_verts[i] = split;
- i++;
- }
- }
-}
-
-static const float *symm_poly_co(const SymmPoly *sp, int v)
-{
- if (sp->src_verts[v])
- return sp->src_verts[v]->co;
- else if (sp->edge_verts[v])
- return sp->edge_verts[v]->co;
- else
- return NULL;
-}
-
-static SymmSide symm_poly_co_side(const Symm *symm,
- const SymmPoly *sp,
- int v)
-{
- return symm_co_side(symm, symm_poly_co(sp, v));
-}
-
-/* Return the index of the vertex in the destination array at corner
- * 'v' of the polygon, or -1 if not in that array */
-static BMVert *symm_poly_dst(const SymmPoly *sp, int v)
-{
- if (sp->edge_verts[v])
- return sp->edge_verts[v];
- else if (sp->src_verts[v])
- return sp->src_verts[v];
- else
- return NULL;
-}
-
-/* Same as above, but returns the index of the mirror if available, or
- * the same index if on the axis, or -1 otherwise */
-static BMVert *symm_poly_mirror_dst(const Symm *symm,
- const SymmPoly *sp,
- int v)
-{
- if (sp->edge_verts[v])
- return sp->edge_verts[v];
- else if (sp->src_verts[v]) {
- if (BLI_ghash_haskey(symm->vert_symm_map, sp->src_verts[v]))
- return BLI_ghash_lookup(symm->vert_symm_map, sp->src_verts[v]);
- else
- return sp->src_verts[v];
- }
- else
- return NULL;
-}
-
-static bool symm_poly_next_crossing(const Symm *symm,
- const SymmPoly *sp,
- int start,
- int *l1,
- int *l2)
-{
- int i;
-
- for (i = 0; i < sp->len; i++) {
- (*l1) = (start + i) % sp->len;
- (*l2) = ((*l1) + 1) % sp->len;
-
- if ((symm_poly_co_side(symm, sp, *l1) == SYMM_SIDE_KILL) ^
- (symm_poly_co_side(symm, sp, *l2) == SYMM_SIDE_KILL))
- {
- return true;
- }
- }
-
- BLI_assert(!"symm_poly_next_crossing failed");
- return false;
-}
-
-static BMFace *symm_face_create_v(BMesh *bm, BMFace *example,
- BMVert **fv, BMEdge **fe, int len)
-{
- BMFace *f_new;
- int i;
-
- /* TODO: calling symmetrize in dynamic-topology sculpt mode
- * frequently tries to create faces of length less than two,
- * should investigate further */
- if (len < 3)
- return NULL;
-
- for (i = 0; i < len; i++) {
- int j = (i + 1) % len;
- fe[i] = BM_edge_exists(fv[i], fv[j]);
- if (!fe[i]) {
- fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, 0);
- BMO_elem_flag_enable(bm, fe[i], SYMM_OUTPUT_GEOM);
- }
- }
- f_new = BM_face_create(bm, fv, fe, len, BM_CREATE_NO_DOUBLE);
- if (example)
- BM_elem_attrs_copy(bm, bm, example, f_new);
- BM_face_select_set(bm, f_new, true);
- BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM);
+#define ELE_OUT 1
- return f_new;
-}
-
-static void symm_mesh_output_poly_zero_splits(Symm *symm,
- SymmPoly *sp,
- BMVert **fv,
- BMEdge **fe,
- int segment_len,
- int start)
-{
- int i, j;
-
- j = 0;
-
- /* Output the keep side of the input polygon */
- for (i = 0; i < segment_len; i++) {
- const int offset = (start + i) % sp->len;
- BLI_assert(sp->src_verts[offset]);
- fv[j++] = sp->src_verts[offset];
- }
-
- /* Output the kill side of the polygon */
- for (i = segment_len - 1; i >= 0; i--) {
- const int offset = (start + i) % sp->len;
-
- if (symm_poly_co_side(symm, sp, offset) == SYMM_SIDE_KEEP) {
- BLI_assert(sp->src_verts[offset]);
- fv[j++] = BLI_ghash_lookup(symm->vert_symm_map,
- sp->src_verts[offset]);
- }
- }
-
- symm_face_create_v(symm->bm, sp->src_face, fv, fe, j);
-}
-
-static void symm_mesh_output_poly_with_splits(Symm *symm,
- SymmPoly *sp,
- BMVert **fv,
- BMEdge **fe,
- int segment_len,
- int start)
-{
- int i;
-
- /* Output the keep side of the input polygon */
-
- for (i = 0; i < segment_len; i++) {
- const int offset = (start + i) % sp->len;
- BMVert *v = symm_poly_dst(sp, offset);
-
- BLI_assert(v);
-
- fv[i] = v;
- }
-
- symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len);
-
- /* Output the kill side of the input polygon */
-
- for (i = 0; i < segment_len; i++) {
- const int offset = (start + i) % sp->len;
- BMVert *v = symm_poly_mirror_dst(symm, sp, offset);
-
- fv[segment_len - i - 1] = v;
-
- }
-
- symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len);
-}
-
-static void symm_mirror_polygons(Symm *symm)
+void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
{
- BMOIter oiter;
- BMFace *f;
- BMVert **pv = NULL;
- BMVert **fv = NULL;
- BMEdge **fe = NULL;
- BLI_array_declare(pv);
- BLI_array_declare(fv);
- BLI_array_declare(fe);
-
- BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) {
- BMIter iter;
- BMLoop *l;
- bool mirror_all = true, ignore_all = true;
-
- /* Check if entire polygon can be mirrored or ignored */
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- const SymmSide side = symm_co_side(symm, l->v->co);
- if (side == SYMM_SIDE_KILL)
- mirror_all = false;
- else if (side == SYMM_SIDE_KEEP)
- ignore_all = false;
- }
-
- if (mirror_all) {
- int i;
-
- /* Make a mirrored copy of the polygon */
-
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, f->len);
- BLI_array_grow_items(fe, f->len);
-
- i = f->len;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- i--;
-
- if (symm_co_side(symm, l->v->co) == SYMM_SIDE_KEEP)
- fv[i] = BLI_ghash_lookup(symm->vert_symm_map, l->v);
- else
- fv[i] = l->v;
- }
-
- symm_face_create_v(symm->bm, f, fv, fe, f->len);
- }
- else if (ignore_all) {
- BM_face_kill(symm->bm, f);
- }
- else {
- SymmPoly sp;
- int l1, l2, l3, l4;
- int double_l2, double_l3;
- int segment_len;
+ const float dist = BMO_slot_float_get(op->slots_in, "dist");
+ const int direction = BMO_slot_int_get(op->slots_in, "direction");
+ const int axis = direction % 3;
- BLI_array_empty(pv);
- BLI_array_grow_items(pv, f->len * 4);
- sp.src_verts = pv;
- sp.edge_verts = pv + f->len * 2;
- symm_poly_with_splits(symm, f, &sp);
+ BMOperator op_bisect;
+ BMOperator op_dupe;
+ BMOperator op_weld;
- /* Find first loop edge crossing the axis */
- symm_poly_next_crossing(symm, &sp, 0, &l1, &l2);
+ BMOpSlot *slot_vertmap;
+ BMOpSlot *slot_targetmap;
- /* If crossing isn't kill to keep, find the next one */
- if (symm_poly_co_side(symm, &sp, l1) != SYMM_SIDE_KILL) {
- symm_poly_next_crossing(symm, &sp, l2, &l1, &l2);
- }
+ float plane_no[3];
+ float scale[3];
- /* Find next crossing (keep to kill) */
- symm_poly_next_crossing(symm, &sp, l2, &l3, &l4);
-
- if (l2 == l3)
- segment_len = 0;
- else if (l2 < l3)
- segment_len = l3 - l2 + 1;
- else
- segment_len = (sp.len - l2 + 1) + l3;
-
- double_l2 = symm_poly_co_side(symm, &sp, l2) == SYMM_SIDE_KEEP;
- double_l3 = symm_poly_co_side(symm, &sp, l3) == SYMM_SIDE_KEEP;
+ BMOIter siter;
+ BMVert *v;
- /* Calculate number of new polygons/loops */
- if (segment_len == 0) {
- }
- else if (sp.already_symmetric) {
- int new_loops;
+ copy_v3_fl(plane_no, 0.0f);
+ copy_v3_fl(scale, 1.0f);
- if (double_l2 && double_l3)
- new_loops = segment_len * 2;
- else if (!double_l2 && !double_l3)
- new_loops = segment_len * 2 - 2;
- else
- new_loops = segment_len * 2 - 1;
+ plane_no[axis] = direction > 2 ? 1.0f : -1.0f;
+ scale[axis] *= -1.0f;
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, new_loops);
- BLI_array_grow_items(fe, new_loops);
+ /* Cut in half */
+ BMO_op_initf(bm, &op_bisect, op->flag,
+ "bisect_plane geom=%s plane_no=%v dist=%f clear_outer=%b use_snap_center=%b",
+ op, "input", plane_no, dist, true, true);
- symm_mesh_output_poly_zero_splits(symm, &sp,
- fv, fe,
- segment_len, l2);
- BM_face_kill(symm->bm, f);
- }
- else if (!double_l2 && !double_l3) {
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, segment_len);
- BLI_array_grow_items(fe, segment_len);
+ BMO_op_exec(bm, &op_bisect);
- symm_mesh_output_poly_with_splits(symm, &sp,
- fv, fe,
- segment_len,
- l2);
+ /* Duplicate */
+ BMO_op_initf(bm, &op_dupe, op->flag,
+ "duplicate geom=%S",
+ &op_bisect, "geom.out");
- BM_face_kill(symm->bm, f);
- }
- else {
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, segment_len);
- BLI_array_grow_items(fe, segment_len);
+ BMO_op_exec(bm, &op_dupe);
- symm_mesh_output_poly_with_splits(symm, &sp,
- fv, fe,
- segment_len,
- l2);
+ /* Flag for output (some will be merged) */
+ BMO_slot_buffer_flag_enable(bm, op_bisect.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
+ BMO_slot_buffer_flag_enable(bm, op_dupe.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
- BM_face_kill(symm->bm, f);
- /* Output bridge triangle */
+ BMO_op_callf(bm, op->flag, "scale verts=%S vec=%v", &op_dupe, "geom.out", scale);
+ BMO_op_callf(bm, op->flag, "reverse_faces faces=%S", &op_dupe, "geom.out");
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, 3);
- BLI_array_grow_items(fe, 3);
- if (double_l2) {
- fv[0] = symm_poly_dst(&sp, l2);
- fv[1] = symm_poly_mirror_dst(symm, &sp, l2);
- fv[2] = symm_poly_dst(&sp, l3);
- }
- else if (double_l3) {
- fv[0] = symm_poly_dst(&sp, l3);
- fv[1] = symm_poly_mirror_dst(symm, &sp, l3);
- fv[2] = symm_poly_dst(&sp, l2);
- }
+ /* Weld verts */
+ BMO_op_init(bm, &op_weld, op->flag, "weld_verts");
- BLI_assert(fv[0] && fv[1] && fv[2]);
+ slot_vertmap = BMO_slot_get(op_dupe.slots_out, "vert_map.out");
+ slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
- symm_face_create_v(symm->bm, NULL, fv, fe, 3);
- }
- }
+ BMO_ITER (v, &siter, op_bisect.slots_out, "geom_cut.out", BM_VERT) {
+ BMVert *v_dupe = BMO_slot_map_elem_get(slot_vertmap, v);
+ BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_dupe, v);
}
- BLI_array_free(pv);
- BLI_array_free(fv);
- BLI_array_free(fe);
-}
-
-/* Remove unused edges and vertices from the side being copied to */
-static void symm_kill_unused(Symm *symm)
-{
- BMOIter oiter;
- BMEdge *e;
- BMVert *v;
-
- /* Kill unused edges */
- BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
- const int crosses = symm_edge_crosses_axis(symm, e);
- const int symmetric = (crosses &&
- (!BLI_ghash_haskey(symm->edge_split_map, e)));
-
- if (((symm_co_side(symm, e->v1->co) == SYMM_SIDE_KILL) ||
- (symm_co_side(symm, e->v2->co) == SYMM_SIDE_KILL)) &&
- !symmetric)
- {
- /* The edge might be used by a face outside the input set */
- if (BM_edge_is_wire(e))
- BM_edge_kill(symm->bm, e);
- }
- }
-
- /* Kill unused vertices */
- BMO_ITER (v, &oiter, symm->op->slots_in, "input", BM_VERT) {
- if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) {
- if (BM_vert_edge_count(v) == 0)
- BM_vert_kill(symm->bm, v);
- }
- }
-}
-
-void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
-{
- Symm symm;
- BMO_SymmDirection direction = BMO_slot_int_get(op->slots_in, "direction");
-
- symm.bm = bm;
- symm.op = op;
- symm.axis = (ELEM(direction,
- BMO_SYMMETRIZE_NEGATIVE_X,
- BMO_SYMMETRIZE_POSITIVE_X) ? 0 :
- ELEM(direction,
- BMO_SYMMETRIZE_NEGATIVE_Y,
- BMO_SYMMETRIZE_POSITIVE_Y) ? 1 :
- ELEM(direction,
- BMO_SYMMETRIZE_NEGATIVE_Z,
- BMO_SYMMETRIZE_POSITIVE_Z) ? 2 : 0);
- symm.direction = direction;
+ BMO_op_exec(bm, &op_weld);
- symm_verts_mirror(&symm);
- symm_split_asymmetric_edges(&symm);
- symm_mirror_edges(&symm);
- symm_mirror_polygons(&symm);
- symm_kill_unused(&symm);
+ /* Cleanup */
+ BMO_op_finish(bm, &op_weld);
- BLI_ghash_free(symm.vert_symm_map, NULL, NULL);
- BLI_ghash_free(symm.edge_split_map, NULL, NULL);
+ BMO_op_finish(bm, &op_dupe);
+ BMO_op_finish(bm, &op_bisect);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out",
- BM_ALL_NOLOOP, SYMM_OUTPUT_GEOM);
+ /* Create output */
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
}
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 754709b18c0..590b5ea97c4 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -34,6 +34,7 @@
#include "BLI_scanfill.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h"
@@ -58,6 +59,7 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op)
void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
{
const bool use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty");
+ const bool use_dissolve = BMO_slot_bool_get(op->slots_in, "use_dissolve");
BMOIter siter;
BMEdge *e;
ScanFillContext sf_ctx;
@@ -65,8 +67,11 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
ScanFillVert *sf_vert, *sf_vert_1, *sf_vert_2;
ScanFillFace *sf_tri;
SmallHash hash;
+ float normal[3], *normal_pt;
BLI_smallhash_init(&hash);
+
+ BMO_slot_vec_get(op->slots_in, "normal", normal);
BLI_scanfill_begin(&sf_ctx);
@@ -91,7 +96,15 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
/* sf_edge->tmp.p = e; */ /* UNUSED */
}
- BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_HOLES);
+ if (is_zero_v3(normal)) {
+ normal_pt = NULL;
+ }
+ else {
+ normalize_v3(normal);
+ normal_pt = normal;
+ }
+
+ BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_HOLES, normal_pt);
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
BMFace *f = BM_face_create_quad_tri(bm,
@@ -121,4 +134,27 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
}
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW);
+
+ if (use_dissolve) {
+ BMO_ITER (e, &siter, op->slots_out, "geom.out", BM_EDGE) {
+ if (LIKELY(e->l)) { /* in rare cases the edges face will have already been removed from the edge */
+ BMFace *f_new;
+ f_new = BM_faces_join_pair(bm, e->l->f,
+ e->l->radial_next->f, e,
+ false); /* join faces */
+ if (f_new) {
+ BMO_elem_flag_enable(bm, f_new, ELE_NEW);
+ BM_edge_kill(bm, e);
+ }
+ else {
+ BMO_error_clear(bm);
+ }
+ }
+ else {
+ BM_edge_kill(bm, e);
+ }
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c
index c1cfb1866f4..ec222b48751 100644
--- a/source/blender/bmesh/operators/bmo_unsubdivide.c
+++ b/source/blender/bmesh/operators/bmo_unsubdivide.c
@@ -31,6 +31,7 @@
#include "BLI_utildefines.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h" /* own include */
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index 8b8cab9d881..e23358bf4ff 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -41,14 +41,16 @@
#include "intern/bmesh_operators_private.h" /* own include */
+#define ELE_NEW 1
+
void bmo_create_vert_exec(BMesh *bm, BMOperator *op)
{
float vec[3];
BMO_slot_vec_get(op->slots_in, "co", vec);
- BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL, 0), 1);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, 1);
+ BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL, BM_CREATE_NOP), ELE_NEW);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, ELE_NEW);
}
void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op)
diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c
index c07e2c3bbf2..2e5db5210c4 100644
--- a/source/blender/bmesh/operators/bmo_wireframe.c
+++ b/source/blender/bmesh/operators/bmo_wireframe.c
@@ -159,10 +159,11 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary");
const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const bool use_crease = (BMO_slot_bool_get(op->slots_in, "use_crease") &&
- CustomData_has_layer(&bm->edata, CD_CREASE));
+ const bool use_crease = BMO_slot_bool_get(op->slots_in, "use_crease");
const float depth = BMO_slot_float_get(op->slots_in, "thickness");
const float inset = depth;
+ int cd_edge_crease_offset = use_crease ? CustomData_get_offset(&bm->edata, CD_CREASE) : -1;
+ const float crease_weight = 1.0f;
const int totvert_orig = bm->totvert;
@@ -196,6 +197,11 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
int i;
+ if (use_crease && cd_edge_crease_offset == -1) {
+ BM_data_layer_add(bm, &bm->edata, CD_CREASE);
+ cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+ }
+
BM_mesh_elem_index_ensure(bm, BM_VERT);
BM_ITER_MESH_INDEX (v_src, &iter, bm, BM_VERTS_OF_MESH, i) {
@@ -229,9 +235,9 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
}
madd_v3_v3v3fl(tvec, v_src->co, v_src->no, -fac);
- verts_neg[i] = BM_vert_create(bm, tvec, v_src, 0);
+ verts_neg[i] = BM_vert_create(bm, tvec, v_src, BM_CREATE_NOP);
madd_v3_v3v3fl(tvec, v_src->co, v_src->no, fac);
- verts_pos[i] = BM_vert_create(bm, tvec, v_src, 0);
+ verts_pos[i] = BM_vert_create(bm, tvec, v_src, BM_CREATE_NOP);
}
else {
/* could skip this */
@@ -269,7 +275,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
}
madd_v3_v3v3fl(tvec, l->v->co, tvec, fac);
- verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, 0);
+ verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, BM_CREATE_NOP);
if (use_boundary) {
@@ -303,7 +309,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
fac *= verts_relfac[BM_elem_index_get(l_pair[i]->v)];
}
madd_v3_v3v3fl(tvec, l_pair[i]->v->co, tvec, fac);
- verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v, 0);
+ verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v, BM_CREATE_NOP);
}
}
}
@@ -380,16 +386,16 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
if (use_crease) {
BMEdge *e_new;
e_new = BM_edge_exists(v_pos1, v_b1);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
e_new = BM_edge_exists(v_pos2, v_b2);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
e_new = BM_edge_exists(v_neg1, v_b1);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
e_new = BM_edge_exists(v_neg2, v_b2);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
}
}
}
@@ -397,16 +403,16 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
if (use_crease) {
BMEdge *e_new;
e_new = BM_edge_exists(v_pos1, v_l1);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
e_new = BM_edge_exists(v_pos2, v_l2);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
e_new = BM_edge_exists(v_neg1, v_l1);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
e_new = BM_edge_exists(v_neg2, v_l2);
- BM_elem_float_data_set(&bm->edata, e_new, CD_CREASE, 1.0f);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
}
}
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 02f0251bff2..8c3edfa23c4 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -42,6 +42,8 @@
#include "BKE_deform.h"
#include "bmesh.h"
+#include "bmesh_bevel.h" /* own include */
+
#include "./intern/bmesh_private.h"
#define BEVEL_EPSILON_D 1e-6
@@ -177,7 +179,7 @@ static NewVert *mesh_vert(VMesh *vm, int i, int j, int k)
static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg)
{
NewVert *nv = mesh_vert(vm, i, j, k);
- nv->v = BM_vert_create(bm, nv->co, eg, 0);
+ nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP);
BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
}
@@ -255,20 +257,8 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
BMFace *f, *interp_f;
int i;
- if (totv == 3) {
- f = BM_face_create_quad_tri_v(bm, vert_arr, 3, facerep, FALSE);
- }
- else if (totv == 4) {
- f = BM_face_create_quad_tri_v(bm, vert_arr, 4, facerep, FALSE);
- }
- else {
- BMEdge **ee = BLI_array_alloca(ee, totv);
+ f = BM_face_create_verts(bm, vert_arr, totv, facerep, BM_CREATE_NOP, true);
- for (i = 0; i < totv; i++) {
- ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, BM_CREATE_NO_DOUBLE);
- }
- f = BM_face_create(bm, vert_arr, ee, totv, 0);
- }
if ((facerep || (face_arr && face_arr[0])) && f) {
BM_elem_attrs_copy(bm, bm, facerep ? facerep : face_arr[0], f);
if (do_interp) {
@@ -428,14 +418,14 @@ static void bev_merge_uvs(BMesh *bm, BMVert *v)
n = 0;
zero_v2(uv);
- BM_ITER_ELEM(l, &iter, v, BM_LOOPS_OF_VERT) {
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
n++;
}
if (n > 1) {
mul_v2_fl(uv, 1.0f / (float)n);
- BM_ITER_ELEM(l, &iter, v, BM_LOOPS_OF_VERT) {
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(luv->uv, uv);
}
@@ -744,14 +734,14 @@ static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[
float co[3])
{
float m[4][4], minv[4][4];
- float edir[3], va0[3], vb0[3], vmid0[3], p[3], snap[3];
+ float edir[3], va0[3], vb0[3], vmid0[3], p[3], snap[3], plane[4];
sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co);
- normalize_v3(edir);
/* project va and vb onto plane P, with normal edir and containing co */
- closest_to_plane_v3(va0, co, edir, va);
- closest_to_plane_v3(vb0, co, edir, vb);
+ plane_from_point_normal_v3(plane, co, edir);
+ closest_to_plane_v3(va0, plane, va);
+ closest_to_plane_v3(vb0, plane, vb);
project_to_edge(e->e, va0, vb0, vmid0);
if (make_unit_square_map(va0, vmid0, vb0, m)) {
/* Transform co and project it onto the unit circle.
@@ -910,7 +900,12 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
BLI_assert(vm->count >= 2);
if (bp->vertex_only) {
- vm->mesh_kind = bp->seg > 1 ? M_ADJ_SUBDIV : M_POLY;
+ if (vm->count == 2)
+ vm->mesh_kind = M_NONE;
+ else if (bp->seg > 1)
+ vm->mesh_kind = M_ADJ_SUBDIV;
+ else
+ vm->mesh_kind = M_POLY;
}
else if (vm->count == 2 && bv->edgecount == 3) {
vm->mesh_kind = M_NONE;
@@ -1143,7 +1138,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
mul_v3_fl(midco, 1.0f / nn);
if (epipe)
snap_to_edge_profile(epipe, va_pipe, vb_pipe, midco);
- bmv = BM_vert_create(bm, midco, NULL, 0);
+ bmv = BM_vert_create(bm, midco, NULL, BM_CREATE_NOP);
v = vm->boundstart;
do {
i = v->index;
@@ -1212,8 +1207,12 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
f = boundvert_rep_face(v);
f2 = boundvert_rep_face(v->next);
if (!v->any_seam) {
- for (ring = 1; ring < ns2; ring++)
- bev_merge_uvs(bm, mesh_vert(vm, i, ring, ns2)->v);
+ for (ring = 1; ring < ns2; ring++) {
+ BMVert *v_uv = mesh_vert(vm, i, ring, ns2)->v;
+ if (v_uv) {
+ bev_merge_uvs(bm, v_uv);
+ }
+ }
}
} while ((v = v->next) != vm->boundstart);
if (!bv->any_seam)
@@ -1972,7 +1971,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
if (!first_bme)
first_bme = v->e;
- if ((nsel == 0 && !bp->vertex_only) || (ntot < 3 && bp->vertex_only)) {
+ if ((nsel == 0 && !bp->vertex_only) || (ntot < 2 && bp->vertex_only)) {
/* signal this vert isn't being beveled */
BM_elem_flag_disable(v, BM_ELEM_TAG);
return;
@@ -2333,14 +2332,14 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
bool vbeveled;
limited_offset = bp->offset;
- BM_ITER_MESH(v, &v_iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
if (bp->vertex_only) {
vbeveled = true;
}
else {
vbeveled = false;
- BM_ITER_ELEM(e, &e_iter, v, BM_EDGES_OF_VERT) {
+ BM_ITER_ELEM (e, &e_iter, v, BM_EDGES_OF_VERT) {
if (BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) {
vbeveled = true;
break;
@@ -2348,7 +2347,7 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
}
}
if (vbeveled) {
- BM_ITER_ELEM(e, &e_iter, v, BM_EDGES_OF_VERT) {
+ BM_ITER_ELEM (e, &e_iter, v, BM_EDGES_OF_VERT) {
half_elen = 0.5f * BM_edge_calc_length(e);
if (half_elen < limited_offset)
limited_offset = half_elen;
@@ -2376,7 +2375,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments,
const struct MDeformVert *dvert, const int vertex_group)
{
BMIter iter;
- BMVert *v;
+ BMVert *v, *v_next;
BMEdge *e;
BevelParams bp = {NULL};
@@ -2419,7 +2418,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments,
}
}
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
BLI_assert(find_bevvert(&bp, v) != NULL);
BM_vert_kill(bm, v);
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
new file mode 100644
index 00000000000..9cfe17d6413
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -0,0 +1,408 @@
+/*
+ * ***** 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): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/tools/bmesh_bisect_plane.c
+ * \ingroup bmesh
+ *
+ * Cut the geometry in half using a plane.
+ *
+ * \par Implementation
+ * This simply works by splitting tagged edges whos verts span either side of
+ * the plane, then splitting faces along their dividing verts.
+ * The only complex case is when a ngon spans the axis multiple times,
+ * in this case we need to do some extra checks to correctly bisect the ngon.
+ * see: #bm_face_bisect_verts
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_linklist.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_math.h"
+
+#include "bmesh.h"
+#include "bmesh_bisect_plane.h" /* own include */
+
+#include "BLI_strict_flags.h" /* keep last */
+
+
+/* -------------------------------------------------------------------- */
+/* Math utils */
+
+static int plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth)
+{
+ const float f = plane_point_side_v3(plane, co);
+ *r_depth = f;
+
+ if (f <= -eps) return -1;
+ else if (f >= eps) return 1;
+ else return 0;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Wrappers to hide internal data-structure abuse,
+ * later we may want to move this into some hash lookup
+ * to a separate struct, but for now we can store in BMesh data */
+
+#define BM_VERT_DIR(v) ((v)->head.index) /* Direction -1/0/1 */
+#define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */
+#define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */
+#define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \
+ (*((unsigned int *)(&(v)->no[2])))
+
+/**
+ * Hide flag access
+ * (for more readable code since same flag is used differently for vert/edgeface)...
+ */
+
+/* enable when vertex is in the center and its faces have been added to the stack */
+BLI_INLINE void vert_is_center_enable(BMVert *v) { BM_elem_flag_enable(v, BM_ELEM_TAG); }
+BLI_INLINE void vert_is_center_disable(BMVert *v) { BM_elem_flag_disable(v, BM_ELEM_TAG); }
+BLI_INLINE bool vert_is_center_test(BMVert *v) { return (BM_elem_flag_test(v, BM_ELEM_TAG) != 0); }
+
+/* enable when the edge can be cut */
+BLI_INLINE void edge_is_cut_enable(BMEdge *e) { BM_elem_flag_enable(e, BM_ELEM_TAG); }
+BLI_INLINE void edge_is_cut_disable(BMEdge *e) { BM_elem_flag_disable(e, BM_ELEM_TAG); }
+BLI_INLINE bool edge_is_cut_test(BMEdge *e) { return (BM_elem_flag_test(e, BM_ELEM_TAG) != 0); }
+
+/* enable when the faces are added to the stack */
+BLI_INLINE void face_in_stack_enable(BMFace *f) { BM_elem_flag_disable(f, BM_ELEM_TAG); }
+BLI_INLINE void face_in_stack_disable(BMFace *f) { BM_elem_flag_enable(f, BM_ELEM_TAG); }
+BLI_INLINE bool face_in_stack_test(BMFace *f) { return (BM_elem_flag_test(f, BM_ELEM_TAG) == 0); }
+
+/* -------------------------------------------------------------------- */
+/* BMesh utils */
+
+static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v)
+{
+ const float val_a = BM_VERT_SORTVAL(*((BMVert **)v_a_v));
+ const float val_b = BM_VERT_SORTVAL(*((BMVert **)v_b_v));
+
+ if (val_a > val_b) return 1;
+ else if (val_a < val_b) return -1;
+ return 0;
+}
+
+
+static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center)
+{
+ /* unlikely more then 2 verts are needed */
+ const unsigned int f_len_orig = (unsigned int)f->len;
+ BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig);
+ STACK_DECLARE(vert_split_arr);
+ BMLoop *l_iter, *l_first;
+ bool use_dirs[3] = {false, false, false};
+
+ STACK_INIT(vert_split_arr);
+
+ l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* add plane-aligned verts to the stack
+ * and check we have verts from both sides in this face,
+ * ... that the face doesn't only have boundry verts on the plane for eg. */
+ l_iter = l_first;
+ do {
+ if (vert_is_center_test(l_iter->v)) {
+ BLI_assert(BM_VERT_DIR(l_iter->v) == 0);
+ STACK_PUSH(vert_split_arr, l_iter->v);
+ }
+ use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if ((STACK_SIZE(vert_split_arr) > 1) &&
+ (use_dirs[0] && use_dirs[2]))
+ {
+ BMLoop *l_new;
+
+ if (LIKELY(STACK_SIZE(vert_split_arr) == 2)) {
+ /* common case, just cut the face once */
+ l_new = NULL;
+ BM_face_split(bm, f, vert_split_arr[0], vert_split_arr[1], &l_new, NULL, true);
+ if (l_new) {
+ if (oflag_center) {
+ BMO_elem_flag_enable(bm, l_new->e, oflag_center);
+ BMO_elem_flag_enable(bm, l_new->f, oflag_center);
+ BMO_elem_flag_enable(bm, f, oflag_center);
+ }
+ }
+ }
+ else {
+ /* less common case, _complicated_ we need to calculate how to do multiple cuts */
+ float (*face_verts_proj_2d)[2] = BLI_array_alloca(face_verts_proj_2d, f_len_orig);
+ float axis_mat[3][3];
+
+ BMFace **face_split_arr = BLI_array_alloca(face_split_arr, STACK_SIZE(vert_split_arr));
+ STACK_DECLARE(face_split_arr);
+
+ float sort_dir[3];
+ unsigned int i;
+
+
+ /* ---- */
+ /* Calculate the direction to sort verts in the face intersecting the plane */
+
+ /* exact dir isn't so important,
+ * just need a dir for sorting verts across face,
+ * 'sort_dir' could be flipped either way, it not important, we only need to order the array
+ */
+ cross_v3_v3v3(sort_dir, f->no, plane);
+ if (UNLIKELY(normalize_v3(sort_dir) == 0.0f)) {
+ /* find any 2 verts and get their direction */
+ for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
+ if (!equals_v3v3(vert_split_arr[0]->co, vert_split_arr[i]->co)) {
+ sub_v3_v3v3(sort_dir, vert_split_arr[0]->co, vert_split_arr[i]->co);
+ normalize_v3(sort_dir);
+ }
+ }
+ if (UNLIKELY(i == STACK_SIZE(vert_split_arr))) {
+ /* ok, we can't do anything useful here,
+ * face has no area or so, bail out, this is highly unlikely but not impossible */
+ goto finally;
+ }
+ }
+
+
+ /* ---- */
+ /* Calculate 2d coords to use for intersection checks */
+
+ /* get the faces 2d coords */
+ BLI_assert(BM_face_is_normal_valid(f));
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ l_iter = l_first;
+ i = 0;
+ do {
+ BM_VERT_LOOPINDEX(l_iter->v) = i;
+ mul_v2_m3v3(face_verts_proj_2d[i], axis_mat, l_iter->v->co);
+ i++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+
+ /* ---- */
+ /* Sort the verts across the face from one side to another */
+ for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
+ BMVert *v = vert_split_arr[i];
+ BM_VERT_SORTVAL(v) = dot_v3v3(sort_dir, v->co);
+ }
+
+ qsort(vert_split_arr, STACK_SIZE(vert_split_arr), sizeof(*vert_split_arr), bm_vert_sortval_cb);
+
+
+ /* ---- */
+ /* Split the face across sorted splits */
+
+ /* note: we don't know which face gets which splits,
+ * so at the moment we have to search all faces for the vert pair,
+ * while not all that nice, typically there are < 5 resulting faces,
+ * so its not _that_ bad. */
+
+ STACK_INIT(face_split_arr);
+ STACK_PUSH(face_split_arr, f);
+
+ for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) {
+ BMVert *v_a = vert_split_arr[i];
+ BMVert *v_b = vert_split_arr[i + 1];
+ float co_mid[2];
+
+ /* geometric test before doing face lookups,
+ * find if the split spans a filled region of the polygon. */
+ mid_v2_v2v2(co_mid,
+ face_verts_proj_2d[BM_VERT_LOOPINDEX(v_a)],
+ face_verts_proj_2d[BM_VERT_LOOPINDEX(v_b)]);
+
+ if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig, false)) {
+ BMLoop *l_a, *l_b;
+ bool found = false;
+ unsigned int j;
+
+ for (j = 0; j < STACK_SIZE(face_split_arr); j++) {
+ /* would be nice to avoid loop lookup here,
+ * but we need to know which face the verts are in */
+ if ((l_a = BM_face_vert_share_loop(face_split_arr[j], v_a)) &&
+ (l_b = BM_face_vert_share_loop(face_split_arr[j], v_b)))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ BLI_assert(found == true);
+
+ /* in fact this simple test is good enough,
+ * test if the loops are adjacent */
+ if (found && (l_a->next != l_b && l_a->prev != l_b)) {
+ BMFace *f_tmp;
+ f_tmp = BM_face_split(bm, face_split_arr[j], l_a->v, l_b->v, NULL, NULL, true);
+ if (f_tmp) {
+ if (f_tmp != face_split_arr[j]) {
+ STACK_PUSH(face_split_arr, f_tmp);
+ BLI_assert(STACK_SIZE(face_split_arr) <= STACK_SIZE(vert_split_arr));
+ }
+ }
+ }
+ }
+ else {
+ // printf("no intersect\n");
+ }
+ }
+ }
+ }
+
+finally:
+ STACK_FREE(vert_split_arr);
+
+}
+
+/* -------------------------------------------------------------------- */
+/* Main logic */
+
+/**
+ * \param use_tag Only bisect tagged edges and faces.
+ * \param use_snap Snap verts onto the plane.
+ * \param oflag_center Operator flag, enabled for geometry on the axis (existing and created)
+ */
+void BM_mesh_bisect_plane(BMesh *bm, float plane[4],
+ const bool use_snap_center, const bool use_tag,
+ const short oflag_center, const float eps)
+{
+ unsigned int einput_len;
+ unsigned int i;
+ BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__);
+
+ BLI_LINKSTACK_DECLARE(face_stack, BMFace *);
+
+ BMVert *v;
+ BMFace *f;
+
+ BMIter iter;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ vert_is_center_disable(v);
+
+ BM_VERT_DIR(v) = plane_point_test_v3(plane, v->co, eps, &(BM_VERT_DIST(v)));
+ if (BM_VERT_DIR(v) == 0) {
+ if (oflag_center) {
+ BMO_elem_flag_enable(bm, v, oflag_center);
+ }
+ if (use_snap_center) {
+ closest_to_plane_v3(v->co, plane, v->co);
+ }
+ }
+ }
+
+ if (use_tag) {
+ /* build tagged edge array */
+ BMEdge *e;
+ einput_len = 0;
+ /* keep face tags as is */
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if (edge_is_cut_test(e)) {
+ edges_arr[einput_len++] = e;
+ }
+ }
+
+ }
+ else {
+ BMEdge *e;
+ einput_len = (unsigned int)bm->totedge;
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ edge_is_cut_enable(e);
+ edges_arr[i] = e;
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ face_in_stack_disable(f);
+ }
+ }
+
+ /* store a stack of faces to be evaluated for splitting */
+ BLI_LINKSTACK_INIT(face_stack);
+
+ for (i = 0; i < einput_len; i++) {
+ /* we could check edge_is_cut_test(e) but there is no point */
+ BMEdge *e = edges_arr[i];
+ const int side[2] = {BM_VERT_DIR(e->v1), BM_VERT_DIR(e->v2)};
+ const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)};
+
+ if (side[0] && side[1] && (side[0] != side[1])) {
+ const float e_fac = fabsf(dist[0]) / fabsf(dist[0] - dist[1]);
+ BMVert *v_new;
+
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (!face_in_stack_test(l_iter->f)) {
+ face_in_stack_enable(l_iter->f);
+ BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac);
+ vert_is_center_enable(v_new);
+ if (oflag_center) {
+ BMO_elem_flag_enable(bm, v_new, oflag_center);
+ }
+
+ BM_VERT_DIR(v_new) = 0;
+ BM_VERT_DIST(v_new) = 0.0f;
+ }
+ else {
+ /* check if either edge verts are aligned,
+ * if so - tag and push all faces that use it into the stack */
+ unsigned int j;
+ BM_ITER_ELEM_INDEX (v, &iter, e, BM_VERTS_OF_EDGE, j) {
+ if (side[j] == 0) {
+ if (vert_is_center_test(v) == 0) {
+ BMIter itersub;
+ BMLoop *l_iter;
+
+ vert_is_center_enable(v);
+
+ BM_ITER_ELEM (l_iter, &itersub, v, BM_LOOPS_OF_VERT) {
+ if (!face_in_stack_test(l_iter->f)) {
+ face_in_stack_enable(l_iter->f);
+ BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN(edges_arr);
+
+ while ((f = BLI_LINKSTACK_POP(face_stack))) {
+ bm_face_bisect_verts(bm, f, plane, oflag_center);
+ }
+
+ /* now we have all faces to split in the stack */
+ BLI_LINKSTACK_FREE(face_stack);
+}
diff --git a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h
index 36668bc9338..15f902642c8 100644
--- a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.h
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * ***** 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
@@ -15,21 +15,20 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
-#ifndef _COM_RenderLayersAlphaProg_h
-#define _COM_RenderLayersAlphaProg_h
-
-#include "COM_RenderLayersBaseProg.h"
+#ifndef __BMESH_BISECT_PLANE_H__
+#define __BMESH_BISECT_PLANE_H__
-class RenderLayersAlphaProg : public RenderLayersBaseProg {
-public:
- RenderLayersAlphaProg();
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
+/** \file blender/bmesh/tools/bmesh_bisect_plane.h
+ * \ingroup bmesh
+ */
-};
+void BM_mesh_bisect_plane(BMesh *bm, float plane[4],
+ const bool use_snap_center, const bool use_tag,
+ const short oflag_center, const float eps);
-#endif
+#endif /* __BMESH_BISECT_PLANE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
index 310357453a3..96af37f4400 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
@@ -293,7 +293,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
}
/* re-calculate costs */
- BM_ITER_ELEM(v_iter, &iter, e_new, BM_VERTS_OF_EDGE) {
+ BM_ITER_ELEM (v_iter, &iter, e_new, BM_VERTS_OF_EDGE) {
const int j = BM_elem_index_get(v_iter);
if (j != -1 && vheap_table[j]) {
const float cost = bm_vert_edge_face_angle(v_iter);
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index 0667d560615..868caa49ec7 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -32,8 +32,7 @@
#include "BLI_math.h"
#include "bmesh.h"
-
-#include "intern/bmesh_operators_private.h" /* own include */
+#include "bmesh_decimate.h" /* own include */
static bool bm_vert_dissolve_fan_test(BMVert *v)
@@ -198,7 +197,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
}
for (iter_step = 0; iter_step < iterations; iter_step++) {
- BMVert *v;
+ BMVert *v, *v_next;
bool iter_done;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -319,7 +318,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
/* now we tagged all verts -1 for removal, lets loop over and rebuild faces */
iter_done = false;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) {
if (bm_vert_dissolve_fan(bm, v)) {
iter_done = true;
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
new file mode 100644
index 00000000000..14d474fed61
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -0,0 +1,508 @@
+/*
+ * ***** 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): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/tools/bmesh_edgenet.c
+ * \ingroup bmesh
+ *
+ * Edgenet Fill.
+ *
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_mempool.h"
+#include "BLI_linklist.h"
+
+#include "bmesh.h"
+#include "bmesh_edgenet.h" /* own include */
+
+#include "BLI_strict_flags.h" /* keep last */
+
+
+/* Data for one end of an edge involved in a bevel */
+typedef struct VertNetInfo {
+ BMVert *prev; /* previous vertex */
+ int pass; /* path scanning pass value, for internal calculation */
+ int face; /* face index connected to the edge between this and the previous vert */
+ int flag; /* flag */
+} VertNetInfo;
+
+enum {
+ VNINFO_FLAG_IS_MIXFACE = (1 << 0),
+};
+
+/**
+ * Check if this edge can be used in a path.
+ */
+static bool bm_edge_step_ok(BMEdge *e)
+{
+ return BM_elem_flag_test(e, BM_ELEM_TAG) && ((e->l == NULL) || (e->l->radial_next == e->l));
+}
+
+static int bm_edge_face(BMEdge *e)
+{
+ return e->l ? BM_elem_index_get(e->l->f) : -1;
+}
+
+/**
+ * Get the next available edge we can use to attempt tp calculate a path from.
+ */
+static BMEdge *bm_edgenet_edge_get_next(
+ BMesh *bm,
+ LinkNode **edge_queue, BLI_mempool *edge_queue_pool)
+{
+ BMEdge *e;
+ BMIter iter;
+
+ while (*edge_queue) {
+ e = BLI_linklist_pop_pool(edge_queue, edge_queue_pool);
+ if (bm_edge_step_ok(e)) {
+ return e;
+ }
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (bm_edge_step_ok(e)) {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Edge loops are built up using links to the 'prev' member.
+ * with each side of the loop having its own pass (negated from the other).
+ *
+ * This function returns half a loop, the caller needs to run twice to get both sides.
+ */
+static unsigned int bm_edgenet_path_from_pass(
+ BMVert *v, LinkNode **v_ls,
+ VertNetInfo *vnet_info, BLI_mempool *path_pool)
+{
+ VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
+ const int pass = vn->pass;
+ unsigned int v_ls_tot = 0;
+
+ do {
+ BLI_linklist_prepend_pool(v_ls, v, path_pool);
+ v_ls_tot += 1;
+ v = vn->prev;
+ vn = &vnet_info[BM_elem_index_get(v)];
+ } while (vn->pass == pass);
+
+ return v_ls_tot;
+}
+
+/**
+ * Specialized wrapper for #BM_face_exists_overlap_subset
+ * that gets the verts from a path before we allocate it in the correct order.
+ */
+static bool bm_edgenet_path_check_overlap(
+ BMVert *v1, BMVert *v2,
+ VertNetInfo *vnet_info)
+{
+ /* vert order doesn't matter */
+ unsigned int v_ls_tot = 0;
+ LinkNode *v_ls = NULL;
+ BMVert *v_pair[2] = {v1, v2};
+ unsigned int i;
+
+ for (i = 0; i < 2; i++) {
+ BMVert *v = v_pair[i];
+ VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
+ const int pass = vn->pass;
+ do {
+ BLI_linklist_prepend_alloca(&v_ls, v);
+ v_ls_tot += 1;
+ v = vn->prev;
+ vn = &vnet_info[BM_elem_index_get(v)];
+ } while (vn->pass == pass);
+ }
+
+ if (v_ls_tot) {
+ BMVert **vert_arr = BLI_array_alloca(vert_arr, v_ls_tot);
+ LinkNode *v_lnk;
+ for (i = 0, v_lnk = v_ls; i < v_ls_tot; v_lnk = v_lnk->next, i++) {
+ vert_arr[i] = v_lnk->link;
+ }
+
+ return BM_face_exists_overlap_subset(vert_arr, (int)v_ls_tot);
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Create a face from the path.
+ */
+static BMFace *bm_edgenet_face_from_path(
+ BMesh *bm, LinkNode *path, const unsigned int path_len)
+{
+ BMFace *f;
+ LinkNode *v_lnk;
+ unsigned int i;
+ unsigned int i_prev;
+
+ BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, path_len);
+
+ for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
+ vert_arr[i] = v_lnk->link;
+ }
+
+ i_prev = path_len - 1;
+ for (i = 0; i < path_len; i++) {
+ edge_arr[i_prev] = BM_edge_exists(vert_arr[i], vert_arr[i_prev]);
+ i_prev = i;
+ }
+
+ /* no need for this, we do overlap checks before allowing the path to be used */
+#if 0
+ if (BM_face_exists_multi(vert_arr, edge_arr, path_len)) {
+ return NULL;
+ }
+#endif
+
+ f = BM_face_create(bm, vert_arr, edge_arr, (int)path_len, NULL, BM_CREATE_NOP);
+
+ return f;
+}
+
+/**
+ * Step along the path from \a v_curr to any vert not already in the path.
+ *
+ * \return The connecting edge if the path is found, otherwise NULL.
+ */
+static BMEdge *bm_edgenet_path_step(
+ BMVert *v_curr, LinkNode **v_ls,
+ VertNetInfo *vnet_info, BLI_mempool *path_pool)
+{
+ const VertNetInfo *vn_curr = &vnet_info[BM_elem_index_get(v_curr)];
+
+ BMEdge *e;
+ BMIter iter;
+ unsigned int tot = 0;
+ unsigned int v_ls_tot = 0;
+
+ BM_ITER_ELEM (e, &iter, v_curr, BM_EDGES_OF_VERT) {
+ BMVert *v_next = BM_edge_other_vert(e, v_curr);
+ if (v_next != vn_curr->prev) {
+ if (bm_edge_step_ok(e)) {
+ VertNetInfo *vn_next = &vnet_info[BM_elem_index_get(v_next)];
+
+ /* check we're not looping back on ourselves */
+ if (vn_curr->pass != vn_next->pass) {
+
+ if (vn_curr->pass == -vn_next->pass) {
+ if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) ||
+ (vn_next->flag & VNINFO_FLAG_IS_MIXFACE))
+ {
+ /* found connecting edge */
+ if (bm_edgenet_path_check_overlap(v_curr, v_next, vnet_info) == false) {
+ return e;
+ }
+ }
+ }
+ else {
+ vn_next->face = bm_edge_face(e);
+ vn_next->pass = vn_curr->pass;
+ vn_next->prev = v_curr;
+
+ /* flush flag down the path */
+ vn_next->flag &= ~VNINFO_FLAG_IS_MIXFACE;
+ if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) ||
+ (vn_next->face == -1) ||
+ (vn_next->face != vn_curr->face))
+ {
+ vn_next->flag |= VNINFO_FLAG_IS_MIXFACE;
+ }
+
+ /* add to the list! */
+ BLI_linklist_prepend_pool(v_ls, v_next, path_pool);
+ v_ls_tot += 1;
+ }
+ }
+ }
+ tot += 1;
+ }
+ }
+
+ /* trick to walk along wire-edge paths */
+ if (v_ls_tot == 1 && tot == 1) {
+ v_curr = BLI_linklist_pop_pool(v_ls, path_pool);
+ bm_edgenet_path_step(v_curr, v_ls, vnet_info, path_pool);
+ }
+
+ return NULL;
+}
+
+/**
+ * Given an edge, find the first path that can form a face.
+ *
+ * \return A linked list of verts.
+ */
+static LinkNode *bm_edgenet_path_calc(
+ BMEdge *e, const int pass_nr, const unsigned int path_cost_max,
+ unsigned int *r_path_len, unsigned int *r_path_cost,
+ VertNetInfo *vnet_info, BLI_mempool *path_pool)
+{
+ VertNetInfo *vn_1, *vn_2;
+ const int f_index = bm_edge_face(e);
+ bool found;
+
+ LinkNode *v_ls_prev = NULL;
+ LinkNode *v_ls_next = NULL;
+
+ unsigned int path_cost_accum = 0;
+
+ BLI_assert(bm_edge_step_ok(e));
+
+ *r_path_len = 0;
+ *r_path_cost = 0;
+
+ vn_1 = &vnet_info[BM_elem_index_get(e->v1)];
+ vn_2 = &vnet_info[BM_elem_index_get(e->v2)];
+
+ vn_1->pass = pass_nr;
+ vn_2->pass = -pass_nr;
+
+ vn_1->prev = e->v2;
+ vn_2->prev = e->v1;
+
+ vn_1->face =
+ vn_2->face = f_index;
+
+ vn_1->flag =
+ vn_2->flag = (f_index == -1) ? VNINFO_FLAG_IS_MIXFACE : 0;
+
+ /* prime the searchlist */
+ BLI_linklist_prepend_pool(&v_ls_prev, e->v1, path_pool);
+ BLI_linklist_prepend_pool(&v_ls_prev, e->v2, path_pool);
+
+ do {
+ found = false;
+
+ /* no point to continue, we're over budget */
+ if (path_cost_accum >= path_cost_max) {
+ BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
+ BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
+ return NULL;
+ }
+
+ while (v_ls_prev) {
+ const LinkNode *v_ls_next_old = v_ls_next;
+ BMVert *v = BLI_linklist_pop_pool(&v_ls_prev, path_pool);
+ BMEdge *e_found = bm_edgenet_path_step(v, &v_ls_next, vnet_info, path_pool);
+
+ if (e_found) {
+ LinkNode *path = NULL;
+ unsigned int path_len;
+ 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);
+
+ path_len = bm_edgenet_path_from_pass(e_found->v1, &path, vnet_info, path_pool);
+ BLI_linklist_reverse(&path);
+ path_len += bm_edgenet_path_from_pass(e_found->v2, &path, vnet_info, path_pool);
+ *r_path_len = path_len;
+ *r_path_cost = path_cost_accum;
+ return path;
+ }
+ else {
+ /* check if a change was made */
+ if (v_ls_next_old != v_ls_next) {
+ found = true;
+ }
+ }
+
+ }
+ BLI_assert(v_ls_prev == NULL);
+
+ path_cost_accum++;
+
+ /* swap */
+ v_ls_prev = v_ls_next;
+ v_ls_next = NULL;
+
+ } while (found);
+
+ BLI_assert(v_ls_prev == NULL);
+ BLI_assert(v_ls_next == NULL);
+
+ /* tag not to search again */
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+
+ return NULL;
+}
+
+/**
+ * Wrapper for #bm_edgenet_path_calc which ensures all included edges
+ * _don't_ have a better option.
+ */
+static LinkNode *bm_edgenet_path_calc_best(
+ BMEdge *e, int *pass_nr, unsigned int path_cost_max,
+ unsigned int *r_path_len, unsigned int *r_path_cost,
+ VertNetInfo *vnet_info, BLI_mempool *path_pool)
+{
+ LinkNode *path;
+ unsigned int path_cost;
+
+ path = bm_edgenet_path_calc(e, *pass_nr, path_cost_max,
+ r_path_len, &path_cost,
+ vnet_info, path_pool);
+ (*pass_nr)++;
+
+ if (path == NULL) {
+ return NULL;
+ }
+ else if (path_cost <= 1) {
+ /* any face that takes 1-2 iterations to find we consider valid */
+ return path;
+ }
+ else {
+ /* Check every edge to see if any can give a better path.
+ * This avoids very strange/long paths from being created. */
+
+ const unsigned int path_len = *r_path_len;
+ unsigned int i, i_prev;
+ BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
+ LinkNode *v_lnk;
+
+ for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
+ vert_arr[i] = v_lnk->link;
+ }
+
+ i_prev = path_len - 1;
+ for (i = 0; i < path_len; i++) {
+ BMEdge *e_other = BM_edge_exists(vert_arr[i], vert_arr[i_prev]);
+ if (e_other != e) {
+ LinkNode *path_test;
+ unsigned int path_len_test;
+ unsigned int path_cost_test;
+
+ path_test = bm_edgenet_path_calc(e_other, *pass_nr, path_cost,
+ &path_len_test, &path_cost_test,
+ vnet_info, path_pool);
+ (*pass_nr)++;
+
+ if (path_test) {
+ BLI_assert(path_cost_test < path_cost);
+
+ BLI_linklist_free_pool(path, NULL, path_pool);
+ path = path_test;
+ *r_path_len = path_len_test;
+ *r_path_cost = path_cost_test;
+ path_cost = path_cost_test;
+ }
+ }
+
+ i_prev = i;
+ }
+ }
+ return path;
+}
+
+/**
+ * Fill in faces from an edgenet made up of boundary and wire edges.
+ *
+ * \note New faces currently don't have their normals calculated and are flipped randomly.
+ * The caller needs to flip faces correctly.
+ *
+ * \param bm The mesh to operate on.
+ * \param use_edge_tag Only fill tagged edges.
+ * \param face_oflag if nonzero, apply all new faces with this bmo flag.
+ */
+void BM_mesh_edgenet(BMesh *bm,
+ const bool use_edge_tag, const bool use_new_face_tag)
+{
+ VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__);
+ BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 1, 512, 0);
+ BLI_mempool *path_pool = BLI_mempool_create(sizeof(LinkNode), 1, 512, 0);
+ LinkNode *edge_queue = NULL;
+
+ BMEdge *e;
+ BMIter iter;
+
+ int pass_nr = 1;
+
+ if (use_edge_tag == false) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ BM_elem_flag_set(e, BM_ELEM_TAG, bm_edge_step_ok(e));
+ }
+ }
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+
+ while (true) {
+ LinkNode *path = NULL;
+ unsigned int path_len;
+ unsigned int path_cost;
+
+ e = bm_edgenet_edge_get_next(bm, &edge_queue, edge_queue_pool);
+ if (e == NULL) {
+ break;
+ }
+
+ BLI_assert(bm_edge_step_ok(e) == true);
+
+ path = bm_edgenet_path_calc_best(e, &pass_nr, UINT_MAX,
+ &path_len, &path_cost,
+ vnet_info, path_pool);
+
+ if (path) {
+ BMFace *f = bm_edgenet_face_from_path(bm, path, path_len);
+ /* queue edges to operate on */
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (bm_edge_step_ok(l_iter->e)) {
+ BLI_linklist_prepend_pool(&edge_queue, l_iter->e, edge_queue_pool);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (use_new_face_tag) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+
+ /* the face index only needs to be unique, not kept valid */
+ BM_elem_index_set(f, bm->totface - 1); /* set_dirty */
+ }
+
+ BLI_linklist_free_pool(path, NULL, path_pool);
+ BLI_assert(BLI_mempool_count(path_pool) == 0);
+ }
+
+ bm->elem_index_dirty |= BM_FACE;
+
+ BLI_mempool_destroy(edge_queue_pool);
+ BLI_mempool_destroy(path_pool);
+ MEM_freeN(vnet_info);
+}
diff --git a/source/blender/compositor/operations/COM_RenderLayersColorOperation.h b/source/blender/bmesh/tools/bmesh_edgenet.h
index 4f4dfbfb6f3..327a7f5aa23 100644
--- a/source/blender/compositor/operations/COM_RenderLayersColorOperation.h
+++ b/source/blender/bmesh/tools/bmesh_edgenet.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * ***** 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
@@ -15,19 +15,19 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
-#ifndef _COM_RenderLayersColorOperation_h
-#define _COM_RenderLayersColorOperation_h
+#ifndef __BMESH_EDGENET_H__
+#define __BMESH_EDGENET_H__
-#include "COM_RenderLayersBaseProg.h"
+/** \file blender/bmesh/tools/bmesh_edgenet.h
+ * \ingroup bmesh
+ */
-class RenderLayersColorOperation : public RenderLayersBaseProg {
-public:
- RenderLayersColorOperation();
-};
+void BM_mesh_edgenet(BMesh *bm,
+ const bool use_edge_tag, const bool use_new_face_tag);
-#endif
+#endif /* __BMESH_EDGENET_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
index aad600d13fa..412253aafe9 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.c
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -193,11 +193,13 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
bmesh_vert_separate(bm, v, &vtar, &vtar_len, copy_select);
- if (vtar_len) {
+ /* first value is always in 'v' */
+ if (vtar_len > 1) {
BMEditSelection *ese = BLI_ghash_lookup(ese_gh, v);
+ BLI_assert(v == vtar[0]);
if (UNLIKELY(ese)) {
int j;
- for (j = 0; j < vtar_len; j++) {
+ for (j = 1; j < vtar_len; j++) {
BLI_assert(v != vtar[j]);
BM_select_history_store_after_notest(bm, ese, vtar[j]);
}
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.h b/source/blender/bmesh/tools/bmesh_triangulate.h
index 936a90d3a16..141aa2f82b4 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.h
+++ b/source/blender/bmesh/tools/bmesh_triangulate.h
@@ -27,10 +27,10 @@
*
*/
-#ifndef __BMESH_TRIAMGULATE_H__
-#define __BMESH_TRIAMGULATE_H__
+#ifndef __BMESH_TRIANGULATE_H__
+#define __BMESH_TRIANGULATE_H__
void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only,
BMOperator *op, BMOpSlot *slot_facemap_out);
-#endif /* __BMESH_TRIAMGULATE_H__ */
+#endif /* __BMESH_TRIANGULATE_H__ */
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index bcbcdd42752..c1b6dc83139 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -963,10 +963,10 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
else
copy_m4_m4(mat, pchan->pose_mat);
- // SECOND_LIFE_COMPATIBILITY
+ // 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->second_life) {
+ if (export_settings->open_sim) {
float temp[4][4];
copy_m4_m4(temp, bone->arm_mat);
temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 438421ccd14..174331c4644 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -193,11 +193,11 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
// and not it's head, seems arbitrary.
(*i)->parentinv[3][1] += bone->length;
- // SECOND_LIFE_COMPATIBILITY
+ // OPEN_SIM_COMPATIBILITY
// TODO: when such objects are animated as
// single matrix the tweak must be applied
// to the result.
- if (export_settings->second_life) {
+ if (export_settings->open_sim) {
// tweak objects parentinverse to match compatibility
float temp[4][4];
@@ -272,8 +272,8 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
copy_m4_m4(mat, bone->arm_mat);
}
- // SECOND_LIFE_COMPATIBILITY
- if (export_settings->second_life) {
+ // OPEN_SIM_COMPATIBILITY
+ if (export_settings->open_sim) {
// Remove rotations vs armature from transform
// parent_rest_rot * mat * irest_rot
float temp[4][4];
diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp
index fc56ff8c63c..649288c2db4 100644
--- a/source/blender/collada/CameraExporter.cpp
+++ b/source/blender/collada/CameraExporter.cpp
@@ -63,7 +63,6 @@ void CamerasExporter::exportCameras(Scene *sce)
}
void CamerasExporter::operator()(Object *ob, Scene *sce)
{
- // TODO: shiftx, shifty, YF_dofdist
Camera *cam = (Camera *)ob->data;
std::string cam_id(get_camera_id(ob));
std::string cam_name(id_name(cam));
@@ -78,7 +77,9 @@ void CamerasExporter::operator()(Object *ob, Scene *sce)
persp.setZFar(cam->clipend, false, "zfar");
persp.setZNear(cam->clipsta, false, "znear");
COLLADASW::Camera ccam(mSW, &persp, cam_id, cam_name);
+ exportBlenderProfile(ccam, cam);
addCamera(ccam);
+
break;
}
case CAM_ORTHO:
@@ -90,8 +91,17 @@ void CamerasExporter::operator()(Object *ob, Scene *sce)
ortho.setZFar(cam->clipend, false, "zfar");
ortho.setZNear(cam->clipsta, false, "znear");
COLLADASW::Camera ccam(mSW, &ortho, cam_id, cam_name);
+ exportBlenderProfile(ccam, cam);
addCamera(ccam);
break;
}
}
}
+bool CamerasExporter::exportBlenderProfile(COLLADASW::Camera &cm,Camera *cam)
+{
+ cm.addExtraTechniqueParameter("blender","shiftx",cam->shiftx);
+ cm.addExtraTechniqueParameter("blender","shifty",cam->shifty);
+ cm.addExtraTechniqueParameter("blender","YF_dofdist",cam->YF_dofdist);
+ return true;
+
+}
diff --git a/source/blender/collada/CameraExporter.h b/source/blender/collada/CameraExporter.h
index 5405df8ab9e..a0c2d5790c8 100644
--- a/source/blender/collada/CameraExporter.h
+++ b/source/blender/collada/CameraExporter.h
@@ -37,6 +37,7 @@ extern "C" {
}
#include "ExportSettings.h"
+#include "DNA_camera_types.h"
class CamerasExporter: COLLADASW::LibraryCameras
{
@@ -45,6 +46,7 @@ public:
void exportCameras(Scene *sce);
void operator()(Object *ob, Scene *sce);
private:
+ bool exportBlenderProfile(COLLADASW::Camera &cla,Camera *cam);
const ExportSettings *export_settings;
};
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index d04ed8d6fa1..948a3dc5ae1 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -507,8 +507,8 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
float world[4][4];
float inv_bind_mat[4][4];
- // SECOND_LIFE_COMPATIBILITY
- if (export_settings->second_life) {
+ // OPEN_SIM_COMPATIBILITY
+ if (export_settings->open_sim) {
// Only translations, no rotation vs armature
float temp[4][4];
unit_m4(temp);
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index c6337e27218..79c725166f6 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -933,6 +933,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
Camera *cam = NULL;
std::string cam_id, cam_name;
+ ExtraTags *et=getExtraTags(camera->getUniqueId());
cam_id = camera->getOriginalId();
cam_name = camera->getName();
if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
@@ -942,6 +943,12 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
fprintf(stderr, "Cannot create camera.\n");
return true;
}
+
+ if (et && et->isProfile("blender")) {
+ et->setData("shiftx",&(cam->shiftx));
+ et->setData("shifty",&(cam->shifty));
+ et->setData("YF_dofdist",&(cam->YF_dofdist));
+ }
cam->clipsta = camera->getNearClippingPlane().getValue();
cam->clipend = camera->getFarClippingPlane().getValue();
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index f9eb4cbc26f..3dc7e74379e 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -50,7 +50,7 @@ public:
bool use_object_instantiation;
bool sort_by_name;
BC_export_transformation_type export_transformation_type;
- bool second_life;
+ bool open_sim;
char *filepath;
LinkNode *export_set;
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 8aa68ed9d04..c7652bd7ae7 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -665,7 +665,12 @@ void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i,
v[0] = (*values)[i++];
v[1] = (*values)[i++];
- v[2] = (*values)[i];
+ if (stride>=3) {
+ v[2] = (*values)[i];
+ }
+ else {
+ v[2] = 0.0f;
+ }
}
break;
@@ -676,13 +681,19 @@ void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i,
v[0] = (float)(*values)[i++];
v[1] = (float)(*values)[i++];
- v[2] = (float)(*values)[i];
+ if (stride >= 3) {
+ v[2] = (float)(*values)[i];
+ }
+ else {
+ v[2] = 0.0f;
+ }
}
break;
default:
break;
}
}
+
bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count)
{
float a[3], b[3];
@@ -857,7 +868,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
*
* During import all materials have been assigned to Object.
* Now we iterate over the imported objects and optimize
- * the assignements as follows:
+ * the assignments as follows:
*
* for each imported geometry:
* if number of users is 1:
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index 1eb5ac6ca4d..223ab3eca2a 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -79,20 +79,10 @@ int collada_export(Scene *sce,
int use_object_instantiation,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int second_life)
+ int open_sim)
{
ExportSettings export_settings;
- /* annoying, collada crashes if file cant be created! [#27162] */
- if (!BLI_exists(filepath)) {
- BLI_make_existing_file(filepath); /* makes the dir if its not there */
- if (!BLI_file_touch(filepath)) {
- fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
- return 0;
- }
- }
- /* end! */
-
export_settings.filepath = (char *)filepath;
export_settings.apply_modifiers = apply_modifiers != 0;
@@ -112,7 +102,7 @@ int collada_export(Scene *sce,
export_settings.use_object_instantiation = use_object_instantiation != 0;
export_settings.sort_by_name = sort_by_name != 0;
export_settings.export_transformation_type = export_transformation_type;
- export_settings.second_life = second_life != 0;
+ export_settings.open_sim = open_sim != 0;
int includeFilter = OB_REL_NONE;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index b3a8156b6fe..e96bc2ea8a4 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -77,7 +77,7 @@ int collada_export(Scene *sce,
int use_object_instantiation,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int second_life);
+ int open_sim);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 3e17472e9c2..146aff5ca5b 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -56,7 +56,9 @@ extern "C" {
#include "WM_api.h" // XXX hrm, see if we can do without this
#include "WM_types.h"
+
#include "bmesh.h"
+#include "bmesh_tools.h"
}
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
diff --git a/source/blender/collada/version.conf b/source/blender/collada/version.conf
new file mode 100644
index 00000000000..d39af7a53df
--- /dev/null
+++ b/source/blender/collada/version.conf
@@ -0,0 +1 @@
+463ba8a2ef5a021ce21df614dde29e0ee800e10b
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index c1b99274bed..e6a3c33ea5d 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -101,6 +101,8 @@ set(SRC
intern/COM_ChannelInfo.h
intern/COM_SingleThreadedNodeOperation.cpp
intern/COM_SingleThreadedNodeOperation.h
+ intern/COM_Debug.cpp
+ intern/COM_Debug.h
operations/COM_QualityStepHelper.h
operations/COM_QualityStepHelper.cpp
@@ -184,6 +186,9 @@ set(SRC
nodes/COM_GlareNode.cpp
nodes/COM_GlareNode.h
+ nodes/COM_PlaneTrackDeformNode.cpp
+ nodes/COM_PlaneTrackDeformNode.h
+
nodes/COM_CropNode.cpp
nodes/COM_CropNode.h
operations/COM_CropOperation.cpp
@@ -365,48 +370,8 @@ set(SRC
operations/COM_ColorSpillOperation.cpp
operations/COM_ColorSpillOperation.h
- operations/COM_RenderLayersBaseProg.cpp
- operations/COM_RenderLayersBaseProg.h
- operations/COM_RenderLayersImageProg.cpp
- operations/COM_RenderLayersImageProg.h
- operations/COM_RenderLayersAlphaProg.cpp
- operations/COM_RenderLayersAlphaProg.h
- operations/COM_RenderLayersDepthProg.cpp
- operations/COM_RenderLayersDepthProg.h
- operations/COM_RenderLayersNormalOperation.cpp
- operations/COM_RenderLayersNormalOperation.h
- operations/COM_RenderLayersSpeedOperation.cpp
- operations/COM_RenderLayersSpeedOperation.h
- operations/COM_RenderLayersColorOperation.cpp
- operations/COM_RenderLayersColorOperation.h
- operations/COM_RenderLayersUVOperation.cpp
- operations/COM_RenderLayersUVOperation.h
- operations/COM_RenderLayersMistOperation.cpp
- operations/COM_RenderLayersMistOperation.h
- operations/COM_RenderLayersObjectIndexOperation.cpp
- operations/COM_RenderLayersObjectIndexOperation.h
- operations/COM_RenderLayersMaterialIndexOperation.cpp
- operations/COM_RenderLayersMaterialIndexOperation.h
- operations/COM_RenderLayersDiffuseOperation.cpp
- operations/COM_RenderLayersDiffuseOperation.h
- operations/COM_RenderLayersSpecularOperation.cpp
- operations/COM_RenderLayersSpecularOperation.h
- operations/COM_RenderLayersShadowOperation.cpp
- operations/COM_RenderLayersShadowOperation.h
- operations/COM_RenderLayersAOOperation.cpp
- operations/COM_RenderLayersAOOperation.h
- operations/COM_RenderLayersEmitOperation.cpp
- operations/COM_RenderLayersEmitOperation.h
- operations/COM_RenderLayersReflectionOperation.cpp
- operations/COM_RenderLayersReflectionOperation.h
- operations/COM_RenderLayersRefractionOperation.cpp
- operations/COM_RenderLayersRefractionOperation.h
- operations/COM_RenderLayersEnvironmentOperation.cpp
- operations/COM_RenderLayersEnvironmentOperation.h
- operations/COM_RenderLayersIndirectOperation.cpp
- operations/COM_RenderLayersIndirectOperation.h
- operations/COM_RenderLayersCyclesOperation.cpp
- operations/COM_RenderLayersCyclesOperation.h
+ operations/COM_RenderLayersProg.cpp
+ operations/COM_RenderLayersProg.h
operations/COM_ImageOperation.cpp
operations/COM_ImageOperation.h
@@ -431,37 +396,11 @@ set(SRC
operations/COM_PreviewOperation.cpp
operations/COM_SplitOperation.h
operations/COM_SplitOperation.cpp
- operations/COM_ConvertValueToColorProg.h
- operations/COM_ConvertValueToColorProg.cpp
- operations/COM_ConvertColorToValueProg.h
- operations/COM_ConvertColorToValueProg.cpp
- operations/COM_ConvertColorToBWOperation.h
- operations/COM_ConvertColorToBWOperation.cpp
- operations/COM_ConvertColorToVectorOperation.h
- operations/COM_ConvertColorToVectorOperation.cpp
- operations/COM_ConvertValueToVectorOperation.h
- operations/COM_ConvertValueToVectorOperation.cpp
- operations/COM_ConvertVectorToColorOperation.h
- operations/COM_ConvertVectorToColorOperation.cpp
- operations/COM_ConvertVectorToValueOperation.h
- operations/COM_ConvertVectorToValueOperation.cpp
operations/COM_ConvertDepthToRadiusOperation.h
operations/COM_ConvertDepthToRadiusOperation.cpp
operations/COM_ZCombineOperation.cpp
operations/COM_ZCombineOperation.h
- operations/COM_ConvertRGBToYCCOperation.h
- operations/COM_ConvertRGBToYCCOperation.cpp
- operations/COM_ConvertYCCToRGBOperation.h
- operations/COM_ConvertYCCToRGBOperation.cpp
- operations/COM_ConvertRGBToYUVOperation.h
- operations/COM_ConvertRGBToYUVOperation.cpp
- operations/COM_ConvertYUVToRGBOperation.h
- operations/COM_ConvertYUVToRGBOperation.cpp
- operations/COM_ConvertRGBToHSVOperation.h
- operations/COM_ConvertRGBToHSVOperation.cpp
- operations/COM_ConvertHSVToRGBOperation.h
- operations/COM_ConvertHSVToRGBOperation.cpp
operations/COM_ChangeHSVOperation.h
operations/COM_ChangeHSVOperation.cpp
operations/COM_ColorCurveOperation.h
@@ -488,25 +427,13 @@ set(SRC
operations/COM_ColorMatteOperation.h
operations/COM_ChannelMatteOperation.cpp
operations/COM_ChannelMatteOperation.h
- operations/COM_ConvertPremulToStraightOperation.cpp
- operations/COM_ConvertPremulToStraightOperation.h
- operations/COM_ConvertStraightToPremulOperation.cpp
- operations/COM_ConvertStraightToPremulOperation.h
operations/COM_ReadBufferOperation.cpp
operations/COM_ReadBufferOperation.h
operations/COM_WriteBufferOperation.cpp
operations/COM_WriteBufferOperation.h
- operations/COM_MixBaseOperation.h
- operations/COM_MixBaseOperation.cpp
- operations/COM_MixBlendOperation.cpp
- operations/COM_MixBlendOperation.h
- operations/COM_MixGlareOperation.cpp
- operations/COM_MixGlareOperation.h
- operations/COM_MixAddOperation.h
- operations/COM_MixAddOperation.cpp
- operations/COM_MixMultiplyOperation.h
- operations/COM_MixMultiplyOperation.cpp
+ operations/COM_MixOperation.h
+ operations/COM_MixOperation.cpp
operations/COM_BrightnessOperation.cpp
operations/COM_BrightnessOperation.h
operations/COM_GammaOperation.cpp
@@ -520,37 +447,6 @@ set(SRC
operations/COM_SetVectorOperation.h
operations/COM_SetVectorOperation.cpp
- operations/COM_MixBurnOperation.h
- operations/COM_MixBurnOperation.cpp
- operations/COM_MixColorOperation.h
- operations/COM_MixColorOperation.cpp
- operations/COM_MixDarkenOperation.h
- operations/COM_MixDarkenOperation.cpp
- operations/COM_MixDodgeOperation.h
- operations/COM_MixDodgeOperation.cpp
- operations/COM_MixDifferenceOperation.h
- operations/COM_MixDifferenceOperation.cpp
- operations/COM_MixDivideOperation.h
- operations/COM_MixDivideOperation.cpp
- operations/COM_MixHueOperation.h
- operations/COM_MixHueOperation.cpp
- operations/COM_MixLightenOperation.h
- operations/COM_MixLightenOperation.cpp
- operations/COM_MixLinearLightOperation.h
- operations/COM_MixLinearLightOperation.cpp
- operations/COM_MixOverlayOperation.h
- operations/COM_MixOverlayOperation.cpp
- operations/COM_MixSaturationOperation.h
- operations/COM_MixSaturationOperation.cpp
- operations/COM_MixScreenOperation.h
- operations/COM_MixScreenOperation.cpp
- operations/COM_MixSoftLightOperation.h
- operations/COM_MixSoftLightOperation.cpp
- operations/COM_MixValueOperation.h
- operations/COM_MixValueOperation.cpp
- operations/COM_MixSubtractOperation.h
- operations/COM_MixSubtractOperation.cpp
-
operations/COM_MathBaseOperation.h
operations/COM_MathBaseOperation.cpp
@@ -595,6 +491,12 @@ set(SRC
operations/COM_ProjectorLensDistortionOperation.h
operations/COM_ScreenLensDistortionOperation.cpp
operations/COM_ScreenLensDistortionOperation.h
+ operations/COM_PlaneTrackCommonOperation.cpp
+ operations/COM_PlaneTrackCommonOperation.h
+ operations/COM_PlaneTrackMaskOperation.cpp
+ operations/COM_PlaneTrackMaskOperation.h
+ operations/COM_PlaneTrackWarpImageOperation.cpp
+ operations/COM_PlaneTrackWarpImageOperation.h
#Filter operations
operations/COM_ConvolutionFilterOperation.h
@@ -626,11 +528,8 @@ set(SRC
#Convert operations
operations/COM_IDMaskOperation.cpp
operations/COM_IDMaskOperation.h
-
- operations/COM_SeparateChannelOperation.cpp
- operations/COM_SeparateChannelOperation.h
- operations/COM_CombineChannelsOperation.cpp
- operations/COM_CombineChannelsOperation.h
+ operations/COM_ConvertOperation.cpp
+ operations/COM_ConvertOperation.h
operations/COM_DotproductOperation.cpp
operations/COM_DotproductOperation.h
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index 204c3237e65..1936909b004 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -20,6 +20,9 @@
* Monique Dewanchand
*/
+#ifndef __COM_COMPOSITOR_H__
+#define __COM_COMPOSITOR_H__
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -343,3 +346,5 @@ int COM_isHighlightedbNode(bNode *bnode);
#ifdef __cplusplus
}
#endif
+
+#endif /* __COM_COMPOSITOR_H__ */
diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index 3cc161a5877..3b0e9f239bb 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -20,8 +20,8 @@
* Monique Dewanchand
*/
-#ifndef _COM_defines_h_
-#define _COM_defines_h_
+#ifndef __COM_DEFINES_H__
+#define __COM_DEFINES_H__
/**
* @brief possible data types for SocketConnection
@@ -109,4 +109,4 @@ typedef enum OrderOfChunks {
#define COM_BLUR_BOKEH_PIXELS 512
-#endif
+#endif /* __COM_DEFINES_H__ */
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 80ae952b87f..384cfbe47fa 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -47,12 +47,7 @@
#include "COM_CombineYUVANode.h"
#include "COM_CompositorNode.h"
#include "COM_ConvertAlphaNode.h"
-#include "COM_ConvertColorToVectorOperation.h"
-#include "COM_ConvertColorToValueProg.h"
-#include "COM_ConvertValueToColorProg.h"
-#include "COM_ConvertValueToVectorOperation.h"
-#include "COM_ConvertVectorToColorOperation.h"
-#include "COM_ConvertVectorToValueOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_Converter.h"
#include "COM_CropNode.h"
#include "COM_DefocusNode.h"
@@ -121,6 +116,7 @@
#include "COM_ViewerNode.h"
#include "COM_ZCombineNode.h"
#include "COM_PixelateNode.h"
+#include "COM_PlaneTrackDeformNode.h"
Node *Converter::convert(bNode *b_node, bool fast)
{
@@ -402,6 +398,9 @@ Node *Converter::convert(bNode *b_node, bool fast)
case CMP_NODE_PIXELATE:
node = new PixelateNode(b_node);
break;
+ case CMP_NODE_PLANETRACKDEFORM:
+ node = new PlaneTrackDeformNode(b_node);
+ break;
default:
node = new MuteNode(b_node);
break;
@@ -416,13 +415,13 @@ void Converter::convertDataType(SocketConnection *connection, ExecutionSystem *s
DataType toDatatype = inputSocket->getDataType();
NodeOperation *converter = NULL;
if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_COLOR) {
- converter = new ConvertValueToColorProg();
+ converter = new ConvertValueToColorOperation();
}
else if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_VECTOR) {
converter = new ConvertValueToVectorOperation();
}
else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VALUE) {
- converter = new ConvertColorToValueProg();
+ converter = new ConvertColorToValueOperation();
}
else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VECTOR) {
converter = new ConvertColorToVectorOperation();
diff --git a/source/blender/compositor/intern/COM_Debug.cpp b/source/blender/compositor/intern/COM_Debug.cpp
new file mode 100644
index 00000000000..b57de38522a
--- /dev/null
+++ b/source/blender/compositor/intern/COM_Debug.cpp
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#include "COM_Debug.h"
+
+#ifdef COM_DEBUG
+
+#include <typeinfo>
+#include <map>
+#include <vector>
+
+extern "C" {
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "DNA_node_types.h"
+#include "BKE_node.h"
+}
+
+#include "COM_Node.h"
+#include "COM_ExecutionSystem.h"
+#include "COM_ExecutionGroup.h"
+
+#include "COM_ReadBufferOperation.h"
+#include "COM_ViewerOperation.h"
+#include "COM_WriteBufferOperation.h"
+
+
+int DebugInfo::m_file_index = 0;
+DebugInfo::NodeNameMap DebugInfo::m_node_names;
+std::string DebugInfo::m_current_node_name;
+DebugInfo::GroupStateMap DebugInfo::m_group_states;
+
+std::string DebugInfo::node_name(NodeBase *node)
+{
+ NodeNameMap::const_iterator it = m_node_names.find(node);
+ if (it != m_node_names.end())
+ return it->second;
+ else
+ return "";
+}
+
+void DebugInfo::convert_started()
+{
+ m_node_names.clear();
+}
+
+void DebugInfo::execute_started(ExecutionSystem *system)
+{
+ m_file_index = 1;
+ m_group_states.clear();
+ for (int i = 0; i < system->getExecutionGroups().size(); ++i)
+ m_group_states[system->getExecutionGroups()[i]] = EG_WAIT;
+}
+
+void DebugInfo::node_added(Node *node)
+{
+ m_node_names[node] = std::string(node->getbNode() ? node->getbNode()->name : "");
+}
+
+void DebugInfo::node_to_operations(Node *node)
+{
+ m_current_node_name = m_node_names[node];
+}
+
+void DebugInfo::operation_added(NodeOperation *operation)
+{
+ m_node_names[operation] = m_current_node_name;
+}
+
+void DebugInfo::operation_read_write_buffer(NodeOperation *operation)
+{
+ m_current_node_name = m_node_names[operation];
+}
+
+void DebugInfo::execution_group_started(ExecutionGroup *group)
+{
+ m_group_states[group] = EG_RUNNING;
+}
+
+void DebugInfo::execution_group_finished(ExecutionGroup *group)
+{
+ m_group_states[group] = EG_FINISHED;
+}
+
+int DebugInfo::graphviz_operation(ExecutionSystem *system, NodeOperation *operation, ExecutionGroup *group, char *str, int maxlen)
+{
+ int len = 0;
+
+ std::string fillcolor = "gainsboro";
+ if (operation->isViewerOperation()) {
+ ViewerOperation *viewer = (ViewerOperation *)operation;
+ if (viewer->isActiveViewerOutput()) {
+ fillcolor = "lightskyblue1";
+ }
+ else {
+ fillcolor = "lightskyblue3";
+ }
+ }
+ else if (operation->isOutputOperation(system->getContext().isRendering())) {
+ fillcolor = "dodgerblue1";
+ }
+ else if (operation->isSetOperation()) {
+ fillcolor = "khaki1";
+ }
+ else if (operation->isReadBufferOperation()) {
+ fillcolor = "darkolivegreen3";
+ }
+ else if (operation->isWriteBufferOperation()) {
+ fillcolor = "darkorange";
+ }
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// OPERATION: %p\r\n", operation);
+ if (group)
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p_%p\"", operation, group);
+ else
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p\"", operation);
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " [fillcolor=%s,style=filled,shape=record,label=\"{", fillcolor.c_str());
+
+ int totinputs = operation->getNumberOfInputSockets();
+ if (totinputs != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
+ for (int k = 0; k < totinputs; k++) {
+ InputSocket *socket = operation->getInputSocket(k);
+ if (k != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<IN_%p>", socket);
+ switch (socket->getDataType()) {
+ case COM_DT_VALUE:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
+ break;
+ case COM_DT_VECTOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
+ break;
+ case COM_DT_COLOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
+ break;
+ }
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ }
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "%s\\n(%s)", m_node_names[operation].c_str(), typeid(*operation).name());
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " (%d,%d)", operation->getWidth(), operation->getHeight());
+
+ int totoutputs = operation->getNumberOfOutputSockets();
+ if (totoutputs != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{");
+ for (int k = 0; k < totoutputs; k++) {
+ OutputSocket *socket = operation->getOutputSocket(k);
+ if (k != 0) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "|");
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<OUT_%p>", socket);
+ switch (socket->getDataType()) {
+ case COM_DT_VALUE:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Value");
+ break;
+ case COM_DT_VECTOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
+ break;
+ case COM_DT_COLOR:
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
+ break;
+ }
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
+ }
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\"]");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
+
+ return len;
+}
+
+int DebugInfo::graphviz_legend_color(const char *name, const char *color, char *str, int maxlen)
+{
+ int len = 0;
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD>%s</TD><TD BGCOLOR=\"%s\"></TD></TR>\r\n", name, color);
+ return len;
+}
+
+int DebugInfo::graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen)
+{
+ /* XXX TODO */
+ int len = 0;
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
+ return len;
+}
+
+int DebugInfo::graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen)
+{
+ int len = 0;
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD>%s</TD><TD CELLPADDING=\"4\"><TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\"><TR><TD BGCOLOR=\"%s\"></TD></TR></TABLE></TD></TR>\r\n", name, color);
+ return len;
+}
+
+int DebugInfo::graphviz_legend(char *str, int maxlen)
+{
+ int len = 0;
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "{\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "rank = sink;\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Legend [shape=none, margin=0, label=<\r\n");
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>\r\n");
+
+ len += graphviz_legend_color("Operation", "gainsboro", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color("Output", "dodgerblue1", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color("Viewer", "lightskyblue3", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color("Active Viewer", "lightskyblue1", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color("Write Buffer", "darkorange", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color("Read Buffer", "darkolivegreen3", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_color("Input Value", "khaki1", str + len, maxlen > len ? maxlen - len : 0);
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "<TR><TD></TD></TR>\r\n");
+
+ len += graphviz_legend_group("Group Waiting", "white", "dashed", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_group("Group Running", "firebrick1", "solid", str + len, maxlen > len ? maxlen - len : 0);
+ len += graphviz_legend_group("Group Finished", "chartreuse4", "solid", str + len, maxlen > len ? maxlen - len : 0);
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "</TABLE>\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, ">];\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
+
+ return len;
+}
+
+bool DebugInfo::graphviz_system(ExecutionSystem *system, char *str, int maxlen)
+{
+ char strbuf[64];
+ int len = 0;
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "digraph compositorexecution {\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "ranksep=1.5\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "splines=false\r\n");
+
+ int totnodes = system->getNodes().size();
+ for (int i = 0; i < totnodes; i++) {
+ Node *node = system->getNodes()[i];
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
+ }
+
+ int totgroups = system->getExecutionGroups().size();
+ int totops = system->getOperations().size();
+ std::map<NodeOperation *, std::vector<std::string> > op_groups;
+ for (int i = 0; i < totgroups; ++i) {
+ ExecutionGroup *group = system->getExecutionGroups()[i];
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// GROUP: %d\r\n", i);
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "subgraph cluster_%d{\r\n", i);
+ /* used as a check for executing group */
+ if (m_group_states[group] == EG_WAIT) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=dashed\r\n");
+ }
+ else if (m_group_states[group] == EG_RUNNING) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=filled\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "color=black\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "fillcolor=firebrick1\r\n");
+ }
+ else if (m_group_states[group] == EG_FINISHED) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "style=filled\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "color=black\r\n");
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "fillcolor=chartreuse4\r\n");
+ }
+
+ for (int j = 0; j < totops; ++j) {
+ NodeOperation *operation = system->getOperations()[j];
+ if (!group->containsOperation(operation))
+ continue;
+
+ sprintf(strbuf, "_%p", group);
+ op_groups[operation].push_back(std::string(strbuf));
+
+ len += graphviz_operation(system, operation, group, str + len, maxlen > len ? maxlen - len : 0);
+ }
+
+// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, "// OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
+// len += snprintf(str+len, maxlen>len ? maxlen-len : 0, " O_%p\r\n", group->getOutputNodeOperation());
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
+ }
+
+ /* operations not included in any group */
+ for (int j = 0; j < totops; ++j) {
+ NodeOperation *operation = system->getOperations()[j];
+ if (op_groups.find(operation) != op_groups.end())
+ continue;
+
+ op_groups[operation].push_back(std::string(""));
+
+ len += graphviz_operation(system, operation, 0, str + len, maxlen > len ? maxlen - len : 0);
+ }
+
+ for (int i = 0; i < totops; i++) {
+ NodeOperation *operation = system->getOperations()[i];
+
+ if (operation->isReadBufferOperation()) {
+ ReadBufferOperation *read = (ReadBufferOperation *)operation;
+ WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
+ std::vector<std::string> &read_groups = op_groups[read];
+ std::vector<std::string> &write_groups = op_groups[write];
+
+ for (int k = 0; k < write_groups.size(); ++k) {
+ for (int l = 0; l < read_groups.size(); ++l) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p%s\" -> \"O_%p%s\" [style=dotted]\r\n", write, write_groups[k].c_str(), read, read_groups[l].c_str());
+ }
+ }
+ }
+ }
+
+ int totcon = system->getConnections().size();
+ for (int i = 0; i < totcon; i++) {
+ SocketConnection *connection = system->getConnections()[i];
+
+ std::string color;
+ if (!connection->isValid()) {
+ color = "red";
+ }
+ else {
+ switch (connection->getFromSocket()->getDataType()) {
+ case COM_DT_VALUE:
+ color = "grey";
+ break;
+ case COM_DT_VECTOR:
+ color = "blue";
+ break;
+ case COM_DT_COLOR:
+ color = "orange";
+ break;
+ }
+ }
+
+ NodeBase *from_node = connection->getFromNode();
+ NodeBase *to_node = connection->getToNode();
+ OutputSocket *from_sock = connection->getFromSocket();
+ InputSocket *to_sock = connection->getToSocket();
+ if (from_node->isOperation() && to_node->isOperation()) {
+ NodeOperation *from_op = (NodeOperation *)from_node;
+ NodeOperation *to_op = (NodeOperation *)to_node;
+ std::vector<std::string> &from_groups = op_groups[from_op];
+ std::vector<std::string> &to_groups = op_groups[to_op];
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "// CONNECTION: %p.%p -> %p.%p\r\n", from_op, from_sock, to_op, to_sock);
+ for (int k = 0; k < from_groups.size(); ++k) {
+ for (int l = 0; l < to_groups.size(); ++l) {
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\"O_%p%s\":\"OUT_%p\":s -> \"O_%p%s\":\"IN_%p\":n", from_op, from_groups[k].c_str(), from_sock, to_op, to_groups[l].c_str(), to_sock);
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, " [color=%s]", color.c_str());
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "\r\n");
+ }
+ }
+ }
+ }
+
+ len += graphviz_legend(str + len, maxlen > len ? maxlen - len : 0);
+
+ len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}\r\n");
+
+ return (len < maxlen);
+}
+
+void DebugInfo::graphviz(ExecutionSystem *system)
+{
+ char str[1000000];
+ if (graphviz_system(system, str, sizeof(str) - 1)) {
+ char basename[FILE_MAX];
+ char filename[FILE_MAX];
+
+ BLI_snprintf(basename, sizeof(basename), "compositor_%d.dot", m_file_index);
+ BLI_join_dirfile(filename, sizeof(filename), BLI_temporary_dir(), basename);
+ ++m_file_index;
+
+ FILE *fp = BLI_fopen(filename, "wb");
+ fputs(str, fp);
+ fclose(fp);
+ }
+}
+
+#else
+
+std::string DebugInfo::node_name(NodeBase */*node*/) { return ""; }
+void DebugInfo::convert_started() {}
+void DebugInfo::execute_started(ExecutionSystem */*system*/) {}
+void DebugInfo::node_added(Node */*node*/) {}
+void DebugInfo::node_to_operations(Node */*node*/) {}
+void DebugInfo::operation_added(NodeOperation */*operation*/) {}
+void DebugInfo::operation_read_write_buffer(NodeOperation */*operation*/) {}
+void DebugInfo::execution_group_started(ExecutionGroup */*group*/) {}
+void DebugInfo::execution_group_finished(ExecutionGroup */*group*/) {}
+void DebugInfo::graphviz(ExecutionSystem */*system*/) {}
+
+#endif
diff --git a/source/blender/compositor/intern/COM_Debug.h b/source/blender/compositor/intern/COM_Debug.h
new file mode 100644
index 00000000000..cc108157769
--- /dev/null
+++ b/source/blender/compositor/intern/COM_Debug.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#ifndef _COM_Debug_h
+#define _COM_Debug_h
+
+#include <map>
+#include <string>
+
+#include "COM_defines.h"
+
+class NodeBase;
+class Node;
+class NodeOperation;
+class ExecutionSystem;
+class ExecutionGroup;
+
+class DebugInfo {
+public:
+ typedef enum {
+ EG_WAIT,
+ EG_RUNNING,
+ EG_FINISHED
+ } GroupState;
+
+ typedef std::map<NodeBase *, std::string> NodeNameMap;
+ typedef std::map<ExecutionGroup *, GroupState> GroupStateMap;
+
+ static std::string node_name(NodeBase *node);
+
+ static void convert_started();
+ static void execute_started(ExecutionSystem *system);
+
+ static void node_added(Node *node);
+ static void node_to_operations(Node *node);
+ static void operation_added(NodeOperation *operation);
+ static void operation_read_write_buffer(NodeOperation *operation);
+
+ static void execution_group_started(ExecutionGroup *group);
+ static void execution_group_finished(ExecutionGroup *group);
+
+ static void graphviz(ExecutionSystem *system);
+
+#ifdef COM_DEBUG
+protected:
+ static int graphviz_operation(ExecutionSystem *system, NodeOperation *operation, ExecutionGroup *group, char *str, int maxlen);
+ static int graphviz_legend_color(const char *name, const char *color, char *str, int maxlen);
+ static int graphviz_legend_line(const char *name, const char *color, const char *style, char *str, int maxlen);
+ static int graphviz_legend_group(const char *name, const char *color, const char *style, char *str, int maxlen);
+ static int graphviz_legend(char *str, int maxlen);
+ static bool graphviz_system(ExecutionSystem *system, char *str, int maxlen);
+
+private:
+ static int m_file_index;
+ static NodeNameMap m_node_names; /**< map nodes to usable names for debug output */
+ static std::string m_current_node_name; /**< base name for all operations added by a node */
+ static GroupStateMap m_group_states; /**< for visualizing group states */
+#endif
+};
+
+#endif
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
index 827b93c350e..a4ff1ce7a19 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
@@ -37,6 +37,7 @@
#include "COM_ViewerOperation.h"
#include "COM_ChunkOrder.h"
#include "COM_ExecutionSystemHelper.h"
+#include "COM_Debug.h"
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -343,6 +344,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
break;
}
+ DebugInfo::execution_group_started(this);
+ DebugInfo::graphviz(graph);
+
bool breaked = false;
bool finished = false;
unsigned int startIndex = 0;
@@ -383,6 +387,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
breaked = true;
}
}
+ DebugInfo::execution_group_finished(this);
+ DebugInfo::graphviz(graph);
MEM_freeN(chunkOrder);
}
@@ -518,17 +524,19 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area
// find all chunks inside the rect
// determine minxchunk, minychunk, maxxchunk, maxychunk where x and y are chunknumbers
- float chunkSizef = this->m_chunkSize;
-
int indexx, indexy;
- int minxchunk = floor((area->xmin - this->m_viewerBorder.xmin) / chunkSizef);
- int maxxchunk = ceil((area->xmax - 1) / chunkSizef);
- int minychunk = floor((area->ymin - this->m_viewerBorder.ymin) / chunkSizef);
- int maxychunk = ceil((area->ymax - 1) / chunkSizef);
- minxchunk = max(minxchunk, 0);
- minychunk = max(minychunk, 0);
- maxxchunk = min(maxxchunk, (int)this->m_numberOfXChunks);
- maxychunk = min(maxychunk, (int)this->m_numberOfYChunks);
+ int minx = max_ii(area->xmin - m_viewerBorder.xmin, 0);
+ int maxx = min_ii(area->xmax - m_viewerBorder.xmin, m_viewerBorder.xmax - m_viewerBorder.xmin);
+ int miny = max_ii(area->ymin - m_viewerBorder.ymin, 0);
+ int maxy = min_ii(area->ymax - m_viewerBorder.ymin, m_viewerBorder.ymax - m_viewerBorder.ymin);
+ int minxchunk = minx / (int)m_chunkSize;
+ int maxxchunk = (maxx + (int)m_chunkSize - 1) / (int)m_chunkSize;
+ int minychunk = miny / (int)m_chunkSize;
+ int maxychunk = (maxy + (int)m_chunkSize - 1) / (int)m_chunkSize;
+ minxchunk = max_ii(minxchunk, 0);
+ minychunk = max_ii(minychunk, 0);
+ maxxchunk = min_ii(maxxchunk, (int)m_numberOfXChunks);
+ maxychunk = min_ii(maxychunk, (int)m_numberOfYChunks);
bool result = true;
for (indexx = minxchunk; indexx < maxxchunk; indexx++) {
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index 537dcb5974a..47f8447015d 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -422,6 +422,9 @@ public:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
#endif
+
+ /* allow the DebugInfo class to peek inside without having to add getters for everything */
+ friend class DebugInfo;
};
#endif
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index ad29405d2e9..716e99a0fa3 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -22,8 +22,6 @@
#include "COM_ExecutionSystem.h"
-#include <sstream>
-
#include "PIL_time.h"
#include "BLI_utildefines.h"
extern "C" {
@@ -40,6 +38,7 @@ extern "C" {
#include "COM_WriteBufferOperation.h"
#include "COM_ReadBufferOperation.h"
#include "COM_ExecutionSystemHelper.h"
+#include "COM_Debug.h"
#include "BKE_global.h"
@@ -101,9 +100,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
}
}
-#ifdef COM_DEBUG
- ExecutionSystemHelper::debugDump(this);
-#endif
+// DebugInfo::graphviz(this);
}
ExecutionSystem::~ExecutionSystem()
@@ -133,6 +130,8 @@ ExecutionSystem::~ExecutionSystem()
void ExecutionSystem::execute()
{
+ DebugInfo::execute_started(this);
+
unsigned int order = 0;
for (vector<NodeOperation *>::iterator iter = this->m_operations.begin(); iter != this->m_operations.end(); ++iter) {
NodeBase *node = *iter;
@@ -199,11 +198,13 @@ void ExecutionSystem::executeGroups(CompositorPriority priority)
void ExecutionSystem::addOperation(NodeOperation *operation)
{
ExecutionSystemHelper::addOperation(this->m_operations, operation);
-// operation->setBTree
+ DebugInfo::operation_added(operation);
}
void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation)
{
+ DebugInfo::operation_read_write_buffer(operation);
+
// for every input add write and read operation if input is not a read operation
// only add read operation to other links when they are attached to buffered operations.
unsigned int index;
@@ -283,8 +284,10 @@ static void debug_check_node_connections(Node *node)
void ExecutionSystem::convertToOperations()
{
unsigned int index;
+
for (index = 0; index < this->m_nodes.size(); index++) {
Node *node = (Node *)this->m_nodes[index];
+ DebugInfo::node_to_operations(node);
node->convertToOperations(this, &this->m_context);
debug_check_node_connections(node);
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
index 9024cd33745..9516deee7e3 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
@@ -22,9 +22,6 @@
#include "COM_ExecutionSystemHelper.h"
-#include <sstream>
-#include <stdio.h>
-
#include "PIL_time.h"
#include "COM_Converter.h"
@@ -37,6 +34,7 @@
#include "COM_WriteBufferOperation.h"
#include "COM_ReadBufferOperation.h"
#include "COM_ViewerOperation.h"
+#include "COM_Debug.h"
extern "C" {
#include "BKE_node.h"
@@ -93,6 +91,8 @@ Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool
if (node) {
node->setIsInActiveGroup(inActiveGroup);
addNode(nodes, node);
+
+ DebugInfo::node_added(node);
}
return node;
}
@@ -166,144 +166,3 @@ SocketConnection *ExecutionSystemHelper::addLink(vector<SocketConnection *>& lin
links.push_back(newconnection);
return newconnection;
}
-
-void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
-{
- Node *node;
- NodeOperation *operation;
- ExecutionGroup *group;
- SocketConnection *connection;
- int tot, tot2;
- printf("-- BEGIN COMPOSITOR DUMP --\r\n");
- printf("digraph compositorexecution {\r\n");
- tot = system->getNodes().size();
- for (int i = 0; i < tot; i++) {
- node = system->getNodes()[i];
- printf("// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
- }
- tot = system->getOperations().size();
- for (int i = 0; i < tot; i++) {
- operation = system->getOperations()[i];
- printf("// OPERATION: %p\r\n", operation);
- printf("\t\"O_%p\"", operation);
- printf(" [shape=record,label=\"{");
- tot2 = operation->getNumberOfInputSockets();
- if (tot2 != 0) {
- printf("{");
- for (int j = 0; j < tot2; j++) {
- InputSocket *socket = operation->getInputSocket(j);
- if (j != 0) {
- printf("|");
- }
- printf("<IN_%p>", socket);
- switch (socket->getDataType()) {
- case COM_DT_VALUE:
- printf("Value");
- break;
- case COM_DT_VECTOR:
- printf("Vector");
- break;
- case COM_DT_COLOR:
- printf("Color");
- break;
- }
- }
- printf("}");
- printf("|");
- }
- if (operation->isViewerOperation()) {
- ViewerOperation *viewer = (ViewerOperation *)operation;
- if (viewer->isActiveViewerOutput()) {
- printf("Active viewer");
- }
- else {
- printf("Viewer");
- }
- }
- else if (operation->isOutputOperation(system->getContext().isRendering())) {
- printf("Output");
- }
- else if (operation->isSetOperation()) {
- printf("Set");
- }
- else if (operation->isReadBufferOperation()) {
- printf("ReadBuffer");
- }
- else if (operation->isWriteBufferOperation()) {
- printf("WriteBuffer");
- }
- else {
- printf("O_%p", operation);
- }
- printf(" (%d,%d)", operation->getWidth(), operation->getHeight());
- tot2 = operation->getNumberOfOutputSockets();
- if (tot2 != 0) {
- printf("|");
- printf("{");
- for (int j = 0; j < tot2; j++) {
- OutputSocket *socket = operation->getOutputSocket(j);
- if (j != 0) {
- printf("|");
- }
- printf("<OUT_%p>", socket);
- switch (socket->getDataType()) {
- case COM_DT_VALUE:
- printf("Value");
- break;
- case COM_DT_VECTOR:
- printf("Vector");
- break;
- case COM_DT_COLOR:
- printf("Color");
- break;
- }
- }
- printf("}");
- }
- printf("}\"]");
- printf("\r\n");
- }
- tot = system->getExecutionGroups().size();
- for (int i = 0; i < tot; i++) {
- group = system->getExecutionGroups()[i];
- printf("// GROUP: %d\r\n", i);
- printf("subgraph {\r\n");
- printf("// OUTPUTOPERATION: %p\r\n", group->getOutputNodeOperation());
- printf(" O_%p\r\n", group->getOutputNodeOperation());
- printf("}\r\n");
- }
- tot = system->getOperations().size();
- for (int i = 0; i < tot; i++) {
- operation = system->getOperations()[i];
- if (operation->isReadBufferOperation()) {
- ReadBufferOperation *read = (ReadBufferOperation *)operation;
- WriteBufferOperation *write = read->getMemoryProxy()->getWriteBufferOperation();
- printf("\t\"O_%p\" -> \"O_%p\" [style=dotted]\r\n", write, read);
- }
- }
- tot = system->getConnections().size();
- for (int i = 0; i < tot; i++) {
- connection = system->getConnections()[i];
- printf("// CONNECTION: %p.%p -> %p.%p\r\n", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
- printf("\t\"O_%p\":\"OUT_%p\" -> \"O_%p\":\"IN_%p\"", connection->getFromNode(), connection->getFromSocket(), connection->getToNode(), connection->getToSocket());
- if (!connection->isValid()) {
- printf(" [color=red]");
- }
- else {
- switch (connection->getFromSocket()->getDataType()) {
- case COM_DT_VALUE:
- printf(" [color=grey]");
- break;
- case COM_DT_VECTOR:
- printf(" [color=blue]");
- break;
- case COM_DT_COLOR:
- printf(" [color=orange]");
- break;
- }
- }
- printf("\r\n");
- }
- printf("}\r\n");
- printf("-- END COMPOSITOR DUMP --\r\n");
-}
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
index e05796b9127..002423c195c 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
@@ -118,12 +118,6 @@ public:
*/
static SocketConnection *addLink(vector<SocketConnection *>& links, OutputSocket *fromSocket, InputSocket *toSocket);
- /**
- * @brief dumps the content of the execution system to standard out
- * @param system the execution system to dump
- */
- static void debugDump(ExecutionSystem *system);
-
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionSystemHelper")
#endif
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index 357a4c1d4c0..4bebf004a89 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -335,8 +335,7 @@ void MemoryBuffer::readEWA(float result[4], float fx, float fy, float dx, float
float tc[4];
const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q];
read(tc, clipuv(u, width), clipuv(v, height));
- madd_v3_v3fl(result, tc, wt);
- result[3] += result[3] ? tc[3] * wt : 0.f;
+ madd_v4_v4fl(result, tc, wt);
d += wt;
}
Q += DQ;
@@ -346,9 +345,5 @@ void MemoryBuffer::readEWA(float result[4], float fx, float fy, float dx, float
// d should hopefully never be zero anymore
d = 1.f / d;
- result[0] *= d;
- result[1] *= d;
- result[2] *= d;
- // clipping can be ignored if alpha used, texr->ta already includes filtered edge
- result[3] = result[3] ? result[3] * d : 1.f;
+ mul_v4_fl(result, d);
}
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index d176298578f..548744f6660 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -46,6 +46,12 @@ typedef enum MemoryBufferState {
COM_MB_TEMPORARILY = 6
} MemoryBufferState;
+typedef enum MemoryBufferExtend {
+ COM_MB_CLIP,
+ COM_MB_EXTEND,
+ COM_MB_REPEAT
+} MemoryBufferExtend;
+
class MemoryProxy;
/**
@@ -125,31 +131,66 @@ public:
this->m_state = COM_MB_AVAILABLE;
}
- inline void read(float result[4], int x, int y)
+ inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
{
- if (x >= this->m_rect.xmin && x < this->m_rect.xmax &&
- y >= this->m_rect.ymin && y < this->m_rect.ymax)
- {
- const int dx = x - this->m_rect.xmin;
- const int dy = y - this->m_rect.ymin;
- const int offset = (this->m_chunkWidth * dy + dx) * COM_NUMBER_OF_CHANNELS;
- copy_v4_v4(result, &this->m_buffer[offset]);
+ int w = m_rect.xmax - m_rect.xmin;
+ int h = m_rect.ymax - m_rect.ymin;
+ x = x - m_rect.xmin;
+ y = y - m_rect.ymin;
+
+ switch (extend_x) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (x < 0) x = 0;
+ if (x >= w) x = w;
+ break;
+ case COM_MB_REPEAT:
+ x = (x >= 0.0f ? (x % w) : (x % w) + w);
+ break;
}
- else {
+
+ switch (extend_y) {
+ case COM_MB_CLIP:
+ break;
+ case COM_MB_EXTEND:
+ if (y < 0) y = 0;
+ if (y >= h) y = h;
+ break;
+ case COM_MB_REPEAT:
+ y = (y >= 0.0f ? (y % h) : (y % h) + h);
+ break;
+ }
+ }
+
+ inline void read(float result[4], int x, int y,
+ MemoryBufferExtend extend_x = COM_MB_CLIP,
+ MemoryBufferExtend extend_y = COM_MB_CLIP)
+ {
+ bool clip_x = (extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax));
+ bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax));
+ if (clip_x || clip_y) {
+ /* clip result outside rect is zero */
zero_v4(result);
}
+ else {
+ wrap_pixel(x, y, extend_x, extend_y);
+ const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS;
+ copy_v4_v4(result, &this->m_buffer[offset]);
+ }
}
- inline void readNoCheck(float result[4], int x, int y)
+ inline void readNoCheck(float result[4], int x, int y,
+ MemoryBufferExtend extend_x = COM_MB_CLIP,
+ MemoryBufferExtend extend_y = COM_MB_CLIP)
{
- const int dx = x - this->m_rect.xmin;
- const int dy = y - this->m_rect.ymin;
- const int offset = (this->m_chunkWidth * dy + dx) * COM_NUMBER_OF_CHANNELS;
+ wrap_pixel(x, y, extend_x, extend_y);
+ const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS;
BLI_assert(offset >= 0);
BLI_assert(offset < this->determineBufferSize() * COM_NUMBER_OF_CHANNELS);
- BLI_assert(x >= this->m_rect.xmin && x < this->m_rect.xmax &&
- y >= this->m_rect.ymin && y < this->m_rect.ymax);
+ BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) &&
+ !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax)));
#if 0
/* always true */
@@ -162,12 +203,16 @@ public:
void writePixel(int x, int y, const float color[4]);
void addPixel(int x, int y, const float color[4]);
- inline void readCubic(float result[4], float x, float y)
+ inline void readBilinear(float result[4], float x, float y,
+ MemoryBufferExtend extend_x = COM_MB_CLIP,
+ MemoryBufferExtend extend_y = COM_MB_CLIP)
{
int x1 = floor(x);
- int x2 = x1 + 1;
int y1 = floor(y);
+ int x2 = x1 + 1;
int y2 = y1 + 1;
+ wrap_pixel(x1, y1, extend_x, extend_y);
+ wrap_pixel(x2, y2, extend_x, extend_y);
float valuex = x - x1;
float valuey = y - y1;
@@ -199,8 +244,6 @@ public:
result[2] = color1[2] * mvaluex + color3[2] * valuex;
result[3] = color1[3] * mvaluex + color3[3] * valuex;
}
-
-
void readEWA(float result[4], float fx, float fy, float dx, float dy, PixelSampler sampler);
diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h
index 41b6ab70bf9..e2072575509 100644
--- a/source/blender/compositor/intern/COM_NodeBase.h
+++ b/source/blender/compositor/intern/COM_NodeBase.h
@@ -153,9 +153,9 @@ public:
*/
InputSocket *getInputSocket(const unsigned int index);
-
virtual bool isStatic() const { return false; }
void getStaticValues(float *result) const { }
+
protected:
NodeBase();
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index 114a00b9e8d..160e493073e 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -199,7 +199,8 @@ public:
* Mostly Filter types (Blurs, Convolution, Defocus etc) need this to be set to true.
*/
const bool isComplex() const { return this->m_complex; }
- virtual const bool isSetOperation() const { return false; }
+
+ virtual bool isSetOperation() const { return false; }
/**
* @brief is this operation of type ReadBufferOperation
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index 1bac06fc4ab..330e61e7fea 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -313,7 +313,8 @@ void WorkScheduler::initialize(bool use_opencl)
cl_uint numberOfPlatforms = 0;
cl_int error;
error = clGetPlatformIDs(0, 0, &numberOfPlatforms);
- if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
+ if (error == -1001) { } /* GPU not supported */
+ else if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
if (G.f & G_DEBUG) printf("%d number of platforms\n", numberOfPlatforms);
cl_platform_id *platforms = (cl_platform_id *)MEM_mallocN(sizeof(cl_platform_id) * numberOfPlatforms, __func__);
error = clGetPlatformIDs(numberOfPlatforms, platforms, 0);
diff --git a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp
index 4f3ed36aadb..bf081cae097 100644
--- a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp
+++ b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp
@@ -22,7 +22,7 @@
#include "COM_AlphaOverNode.h"
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
#include "COM_AlphaOverKeyOperation.h"
#include "COM_AlphaOverMixedOperation.h"
#include "COM_AlphaOverPremultiplyOperation.h"
diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
index c1511ee611b..4c136583936 100644
--- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
@@ -22,9 +22,7 @@
#include "COM_ChannelMatteNode.h"
#include "BKE_node.h"
#include "COM_ChannelMatteOperation.h"
-#include "COM_ConvertRGBToHSVOperation.h"
-#include "COM_ConvertRGBToYCCOperation.h"
-#include "COM_ConvertRGBToYUVOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_SetAlphaOperation.h"
ChannelMatteNode::ChannelMatteNode(bNode *editorNode) : Node(editorNode)
diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
index d2598e661a9..c23f242ca5c 100644
--- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
@@ -22,7 +22,7 @@
#include "COM_ChromaMatteNode.h"
#include "BKE_node.h"
#include "COM_ChromaMatteOperation.h"
-#include "COM_ConvertRGBToYCCOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_SetAlphaOperation.h"
ChromaMatteNode::ChromaMatteNode(bNode *editorNode) : Node(editorNode)
diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp
index aeed859b350..5578fdae54e 100644
--- a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp
@@ -25,7 +25,7 @@
#include "COM_ColorBalanceASCCDLOperation.h"
#include "COM_ExecutionSystem.h"
#include "BKE_node.h"
-#include "COM_MixBlendOperation.h"
+#include "COM_MixOperation.h"
ColorBalanceNode::ColorBalanceNode(bNode *editorNode) : Node(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
index 54e6762961b..8ab93a58a1d 100644
--- a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
@@ -22,7 +22,7 @@
#include "COM_ColorMatteNode.h"
#include "BKE_node.h"
#include "COM_ColorMatteOperation.h"
-#include "COM_ConvertRGBToHSVOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_SetAlphaOperation.h"
ColorMatteNode::ColorMatteNode(bNode *editorNode) : Node(editorNode)
diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.cpp b/source/blender/compositor/nodes/COM_ColorRampNode.cpp
index a79c7885ae4..6f715a8f278 100644
--- a/source/blender/compositor/nodes/COM_ColorRampNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorRampNode.cpp
@@ -24,7 +24,7 @@
#include "COM_ExecutionSystem.h"
#include "BKE_node.h"
#include "COM_ColorRampOperation.h"
-#include "COM_SeparateChannelOperation.h"
+#include "COM_ConvertOperation.h"
#include "DNA_texture_types.h"
ColorRampNode::ColorRampNode(bNode *editorNode) : Node(editorNode)
diff --git a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp
index 511fdf09f41..07be93dab86 100644
--- a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp
@@ -22,7 +22,7 @@
#include "COM_ColorToBWNode.h"
-#include "COM_ConvertColorToBWOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
ColorToBWNode::ColorToBWNode(bNode *editorNode) : Node(editorNode)
diff --git a/source/blender/compositor/nodes/COM_CombineHSVANode.cpp b/source/blender/compositor/nodes/COM_CombineHSVANode.cpp
index beba41fade9..9f6614ed8c3 100644
--- a/source/blender/compositor/nodes/COM_CombineHSVANode.cpp
+++ b/source/blender/compositor/nodes/COM_CombineHSVANode.cpp
@@ -22,11 +22,11 @@
#include "COM_CombineHSVANode.h"
-#include "COM_CombineChannelsOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
-#include "COM_ConvertHSVToRGBOperation.h"
+#include "COM_ConvertOperation.h"
CombineHSVANode::CombineHSVANode(bNode *editorNode) : CombineRGBANode(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_CombineRGBANode.cpp b/source/blender/compositor/nodes/COM_CombineRGBANode.cpp
index a8cdd8c2950..8dfded049e5 100644
--- a/source/blender/compositor/nodes/COM_CombineRGBANode.cpp
+++ b/source/blender/compositor/nodes/COM_CombineRGBANode.cpp
@@ -22,7 +22,7 @@
#include "COM_CombineRGBANode.h"
-#include "COM_CombineChannelsOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
diff --git a/source/blender/compositor/nodes/COM_CombineYCCANode.cpp b/source/blender/compositor/nodes/COM_CombineYCCANode.cpp
index 5319eb84184..ee787a4f9c1 100644
--- a/source/blender/compositor/nodes/COM_CombineYCCANode.cpp
+++ b/source/blender/compositor/nodes/COM_CombineYCCANode.cpp
@@ -20,7 +20,7 @@
*/
#include "COM_CombineYCCANode.h"
-#include "COM_ConvertYCCToRGBOperation.h"
+#include "COM_ConvertOperation.h"
CombineYCCANode::CombineYCCANode(bNode *editorNode) : CombineRGBANode(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_CombineYUVANode.cpp b/source/blender/compositor/nodes/COM_CombineYUVANode.cpp
index 48c2c6ca649..feee443cf05 100644
--- a/source/blender/compositor/nodes/COM_CombineYUVANode.cpp
+++ b/source/blender/compositor/nodes/COM_CombineYUVANode.cpp
@@ -20,7 +20,7 @@
*/
#include "COM_CombineYUVANode.h"
-#include "COM_ConvertYUVToRGBOperation.h"
+#include "COM_ConvertOperation.h"
CombineYUVANode::CombineYUVANode(bNode *editorNode) : CombineRGBANode(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
index a7149cc63b2..72f3ed07fd5 100644
--- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
+++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
@@ -20,8 +20,7 @@
*/
#include "COM_ConvertAlphaNode.h"
-#include "COM_ConvertPremulToStraightOperation.h"
-#include "COM_ConvertStraightToPremulOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
index 782c897f6fb..3c532fe0b1d 100644
--- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
@@ -24,7 +24,7 @@
#include "COM_DistanceRGBMatteOperation.h"
#include "COM_DistanceYCCMatteOperation.h"
#include "COM_SetAlphaOperation.h"
-#include "COM_ConvertRGBToYCCOperation.h"
+#include "COM_ConvertOperation.h"
DistanceMatteNode::DistanceMatteNode(bNode *editorNode) : Node(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_FilterNode.cpp b/source/blender/compositor/nodes/COM_FilterNode.cpp
index 990cdb480ca..3b75e3e0a1a 100644
--- a/source/blender/compositor/nodes/COM_FilterNode.cpp
+++ b/source/blender/compositor/nodes/COM_FilterNode.cpp
@@ -25,7 +25,7 @@
#include "COM_ConvolutionEdgeFilterOperation.h"
#include "COM_ExecutionSystem.h"
#include "BKE_node.h"
-#include "COM_MixBlendOperation.h"
+#include "COM_MixOperation.h"
FilterNode::FilterNode(bNode *editorNode) : Node(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_GlareNode.cpp b/source/blender/compositor/nodes/COM_GlareNode.cpp
index 8782e6bb6d9..a6a83846623 100644
--- a/source/blender/compositor/nodes/COM_GlareNode.cpp
+++ b/source/blender/compositor/nodes/COM_GlareNode.cpp
@@ -26,7 +26,7 @@
#include "COM_GlareSimpleStarOperation.h"
#include "COM_GlareStreaksOperation.h"
#include "COM_SetValueOperation.h"
-#include "COM_MixGlareOperation.h"
+#include "COM_MixOperation.h"
#include "COM_FastGaussianBlurOperation.h"
#include "COM_GlareGhostOperation.h"
#include "COM_GlareFogGlowOperation.h"
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp
index fd961030ebf..66b98b29d5e 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp
@@ -22,11 +22,9 @@
#include "COM_HueSaturationValueCorrectNode.h"
-#include "COM_ConvertColorToValueProg.h"
+#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
-#include "COM_ConvertRGBToHSVOperation.h"
-#include "COM_ConvertHSVToRGBOperation.h"
-#include "COM_MixBlendOperation.h"
+#include "COM_MixOperation.h"
#include "COM_SetColorOperation.h"
#include "COM_SetValueOperation.h"
#include "COM_ChangeHSVOperation.h"
diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
index 29e10db0758..5001433513c 100644
--- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
+++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp
@@ -22,11 +22,9 @@
#include "COM_HueSaturationValueNode.h"
-#include "COM_ConvertColorToValueProg.h"
+#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
-#include "COM_ConvertRGBToHSVOperation.h"
-#include "COM_ConvertHSVToRGBOperation.h"
-#include "COM_MixBlendOperation.h"
+#include "COM_MixOperation.h"
#include "COM_SetColorOperation.h"
#include "COM_SetValueOperation.h"
#include "COM_ChangeHSVOperation.h"
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index b8d9841c92a..6e4bff460d1 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -25,7 +25,7 @@
#include "COM_ExecutionSystem.h"
#include "COM_ImageOperation.h"
#include "COM_MultilayerImageOperation.h"
-#include "COM_ConvertPremulToStraightOperation.h"
+#include "COM_ConvertOperation.h"
#include "BKE_node.h"
#include "BLI_utildefines.h"
@@ -38,19 +38,19 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-NodeOperation *ImageNode::doMultilayerCheck(ExecutionSystem *system, RenderLayer *rl, Image *image, ImageUser *user, int framenumber, int outputsocketIndex, int pass, DataType datatype)
+NodeOperation *ImageNode::doMultilayerCheck(ExecutionSystem *system, RenderLayer *rl, Image *image, ImageUser *user, int framenumber, int outputsocketIndex, int passindex, DataType datatype)
{
OutputSocket *outputSocket = this->getOutputSocket(outputsocketIndex);
MultilayerBaseOperation *operation = NULL;
switch (datatype) {
case COM_DT_VALUE:
- operation = new MultilayerValueOperation(pass);
+ operation = new MultilayerValueOperation(passindex);
break;
case COM_DT_VECTOR:
- operation = new MultilayerVectorOperation(pass);
+ operation = new MultilayerVectorOperation(passindex);
break;
case COM_DT_COLOR:
- operation = new MultilayerColorOperation(pass);
+ operation = new MultilayerColorOperation(passindex);
break;
default:
break;
@@ -93,10 +93,19 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
socket = this->getOutputSocket(index);
if (socket->isConnected() || index == 0) {
bNodeSocket *bnodeSocket = socket->getbNodeSocket();
- NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
- int passindex = storage->pass_index;
-
+ /* Passes in the file can differ from passes stored in sockets (#36755).
+ * Look up the correct file pass using the socket identifier instead.
+ */
+ #if 0
+ NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;*/
+ int passindex = storage->pass_index;*/
RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
+ #endif
+ int passindex;
+ RenderPass *rpass;
+ for (rpass = (RenderPass *)rl->passes.first, passindex = 0; rpass; rpass = rpass->next, ++passindex)
+ if (STREQ(rpass->name, bnodeSocket->identifier))
+ break;
if (rpass) {
imageuser->pass = passindex;
switch (rpass->channels) {
diff --git a/source/blender/compositor/nodes/COM_ImageNode.h b/source/blender/compositor/nodes/COM_ImageNode.h
index 49006efbed5..12b4da6c8b3 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.h
+++ b/source/blender/compositor/nodes/COM_ImageNode.h
@@ -35,7 +35,7 @@ extern "C" {
*/
class ImageNode : public Node {
private:
- NodeOperation *doMultilayerCheck(ExecutionSystem *system, RenderLayer *rl, Image *image, ImageUser *user, int framenumber, int outputsocketIndex, int pass, DataType datatype);
+ NodeOperation *doMultilayerCheck(ExecutionSystem *system, RenderLayer *rl, Image *image, ImageUser *user, int framenumber, int outputsocketIndex, int passindex, DataType datatype);
public:
ImageNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp
index 51ea2913e65..786530bd3c4 100644
--- a/source/blender/compositor/nodes/COM_KeyingNode.cpp
+++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp
@@ -32,10 +32,7 @@
#include "COM_MathBaseOperation.h"
-#include "COM_SeparateChannelOperation.h"
-#include "COM_CombineChannelsOperation.h"
-#include "COM_ConvertRGBToYCCOperation.h"
-#include "COM_ConvertYCCToRGBOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_SetValueOperation.h"
#include "COM_DilateErodeOperation.h"
diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
index 4656e00b006..b1e6967ba42 100644
--- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
@@ -22,7 +22,7 @@
#include "COM_LuminanceMatteNode.h"
#include "BKE_node.h"
#include "COM_LuminanceMatteOperation.h"
-#include "COM_ConvertRGBToYUVOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_SetAlphaOperation.h"
LuminanceMatteNode::LuminanceMatteNode(bNode *editorNode) : Node(editorNode)
diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp
index ab4e464327d..42217243fdf 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cpp
+++ b/source/blender/compositor/nodes/COM_MixNode.cpp
@@ -22,24 +22,7 @@
#include "COM_MixNode.h"
-#include "COM_MixBlendOperation.h"
-#include "COM_MixAddOperation.h"
-#include "COM_MixMultiplyOperation.h"
-#include "COM_MixBurnOperation.h"
-#include "COM_MixColorOperation.h"
-#include "COM_MixDarkenOperation.h"
-#include "COM_MixDifferenceOperation.h"
-#include "COM_MixDivideOperation.h"
-#include "COM_MixHueOperation.h"
-#include "COM_MixLightenOperation.h"
-#include "COM_MixLinearLightOperation.h"
-#include "COM_MixOverlayOperation.h"
-#include "COM_MixSaturationOperation.h"
-#include "COM_MixScreenOperation.h"
-#include "COM_MixSoftLightOperation.h"
-#include "COM_MixSubtractOperation.h"
-#include "COM_MixValueOperation.h"
-#include "COM_MixDodgeOperation.h"
+#include "COM_MixOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
index 3b1871b307b..94e5efe77e0 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
@@ -59,12 +59,12 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte
bool hasConnections = false;
for (int i = 0; i < num_inputs; ++i) {
InputSocket *input = getInputSocket(i);
+ NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)input->getbNodeSocket()->storage;
+
+ outputOperation->add_layer(sockdata->layer, input->getDataType());
+
if (input->isConnected()) {
hasConnections = true;
- NodeImageMultiFileSocket *sockdata = (NodeImageMultiFileSocket *)input->getbNodeSocket()->storage;
-
- outputOperation->add_layer(sockdata->layer, input->getDataType());
-
input->relinkConnections(outputOperation->getInputSocket(i));
}
}
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
new file mode 100644
index 00000000000..d6434c26c7d
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013, 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:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ * Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackDeformNode.h"
+#include "COM_ExecutionSystem.h"
+
+#include "COM_PlaneTrackMaskOperation.h"
+#include "COM_PlaneTrackWarpImageOperation.h"
+
+extern "C" {
+ #include "BKE_node.h"
+ #include "BKE_movieclip.h"
+ #include "BKE_tracking.h"
+}
+
+PlaneTrackDeformNode::PlaneTrackDeformNode(bNode *editorNode) : Node(editorNode)
+{
+ /* pass */
+}
+
+void PlaneTrackDeformNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
+{
+ InputSocket *input_image = this->getInputSocket(0);
+
+ OutputSocket *output_warped_image = this->getOutputSocket(0);
+ OutputSocket *output_plane = this->getOutputSocket(1);
+
+ bNode *editorNode = this->getbNode();
+ MovieClip *clip = (MovieClip *) editorNode->id;
+
+ NodePlaneTrackDeformData *data = (NodePlaneTrackDeformData *) editorNode->storage;
+
+ int frame_number = context->getFramenumber();
+
+ if (output_warped_image->isConnected()) {
+ PlaneTrackWarpImageOperation *warp_image_operation = new PlaneTrackWarpImageOperation();
+
+ warp_image_operation->setMovieClip(clip);
+ warp_image_operation->setTrackingObject(data->tracking_object);
+ warp_image_operation->setPlaneTrackName(data->plane_track_name);
+ warp_image_operation->setFramenumber(frame_number);
+
+ input_image->relinkConnections(warp_image_operation->getInputSocket(0), 0, graph);
+ output_warped_image->relinkConnections(warp_image_operation->getOutputSocket());
+
+ graph->addOperation(warp_image_operation);
+ }
+
+ if (output_plane->isConnected()) {
+ PlaneTrackMaskOperation *plane_mask_operation = new PlaneTrackMaskOperation();
+
+ plane_mask_operation->setMovieClip(clip);
+ plane_mask_operation->setTrackingObject(data->tracking_object);
+ plane_mask_operation->setPlaneTrackName(data->plane_track_name);
+ plane_mask_operation->setFramenumber(frame_number);
+
+ output_plane->relinkConnections(plane_mask_operation->getOutputSocket());
+
+ graph->addOperation(plane_mask_operation);
+ }
+}
diff --git a/source/blender/compositor/operations/COM_RenderLayersMistOperation.h b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
index ad838c9e340..cf173cd19f9 100644
--- a/source/blender/compositor/operations/COM_RenderLayersMistOperation.h
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011, Blender Foundation.
+ * Copyright 2013, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -16,18 +16,23 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Sergey Sharybin
*/
-#ifndef _COM_RenderLayersMistOperation_h
-#define _COM_RenderLayersMistOperation_h
+#include "COM_Node.h"
+#include "DNA_node_types.h"
-#include "COM_RenderLayersBaseProg.h"
+extern "C" {
+ #include "DNA_movieclip_types.h"
+ #include "DNA_node_types.h"
+}
-class RenderLayersMistOperation : public RenderLayersBaseProg {
+/**
+ * @brief PlaneTrackDeformNode
+ * @ingroup Node
+ */
+class PlaneTrackDeformNode : public Node {
public:
- RenderLayersMistOperation();
+ PlaneTrackDeformNode(bNode *editorNode);
+ void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
};
-
-#endif
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
index 74e557c77ce..512f8eec90f 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
@@ -22,26 +22,7 @@
#include "COM_RenderLayersNode.h"
#include "COM_ExecutionSystem.h"
-#include "COM_RenderLayersImageProg.h"
-#include "COM_RenderLayersAlphaProg.h"
-#include "COM_RenderLayersDepthProg.h"
-#include "COM_RenderLayersNormalOperation.h"
-#include "COM_RenderLayersSpeedOperation.h"
-#include "COM_RenderLayersColorOperation.h"
-#include "COM_RenderLayersUVOperation.h"
-#include "COM_RenderLayersMistOperation.h"
-#include "COM_RenderLayersObjectIndexOperation.h"
-#include "COM_RenderLayersDiffuseOperation.h"
-#include "COM_RenderLayersSpecularOperation.h"
-#include "COM_RenderLayersShadowOperation.h"
-#include "COM_RenderLayersAOOperation.h"
-#include "COM_RenderLayersEmitOperation.h"
-#include "COM_RenderLayersReflectionOperation.h"
-#include "COM_RenderLayersRefractionOperation.h"
-#include "COM_RenderLayersEnvironmentOperation.h"
-#include "COM_RenderLayersIndirectOperation.h"
-#include "COM_RenderLayersMaterialIndexOperation.h"
-#include "COM_RenderLayersCyclesOperation.h"
+#include "COM_RenderLayersProg.h"
#include "COM_TranslateOperation.h"
#include "COM_RotateOperation.h"
#include "COM_ScaleOperation.h"
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h
index 9bd74624b0c..0c769d32aea 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.h
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h
@@ -22,7 +22,7 @@
#include "COM_Node.h"
#include "DNA_node_types.h"
-#include "COM_RenderLayersBaseProg.h"
+#include "COM_RenderLayersProg.h"
/**
* @brief RenderLayersNode
diff --git a/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp b/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp
index 4f93b226fa1..4cd77d4bae6 100644
--- a/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp
+++ b/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp
@@ -22,10 +22,9 @@
#include "COM_SeparateHSVANode.h"
-#include "COM_SeparateChannelOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
-#include "COM_ConvertRGBToHSVOperation.h"
+#include "COM_ConvertOperation.h"
SeparateHSVANode::SeparateHSVANode(bNode *editorNode) : SeparateRGBANode(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp b/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp
index 7fcdebadb46..7d9bff30a93 100644
--- a/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp
+++ b/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp
@@ -22,7 +22,7 @@
#include "COM_SeparateRGBANode.h"
-#include "COM_SeparateChannelOperation.h"
+#include "COM_ConvertOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
#include "DNA_material_types.h" // the ramp types
diff --git a/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp b/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp
index 154e2bcd550..797cd49316a 100644
--- a/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp
+++ b/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp
@@ -20,10 +20,9 @@
*/
#include "COM_SeparateYCCANode.h"
-#include "COM_SeparateChannelOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
-#include "COM_ConvertRGBToYCCOperation.h"
+#include "COM_ConvertOperation.h"
SeparateYCCANode::SeparateYCCANode(bNode *editorNode) : SeparateRGBANode(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp b/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp
index 8a647b7f849..9a6ec20fa80 100644
--- a/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp
+++ b/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp
@@ -20,10 +20,9 @@
*/
#include "COM_SeparateYUVANode.h"
-#include "COM_SeparateChannelOperation.h"
#include "COM_ExecutionSystem.h"
#include "COM_SetValueOperation.h"
-#include "COM_ConvertRGBToYUVOperation.h"
+#include "COM_ConvertOperation.h"
SeparateYUVANode::SeparateYUVANode(bNode *editorNode) : SeparateRGBANode(editorNode)
{
diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
index 81c0744564f..6fb8467674b 100644
--- a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
@@ -35,9 +35,8 @@ SplitViewerNode::SplitViewerNode(bNode *editorNode) : Node(editorNode)
void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
bNode *editorNode = this->getbNode();
- bool is_active = ((editorNode->flag & NODE_DO_OUTPUT_RECALC) &&
- (editorNode->flag & NODE_DO_OUTPUT) && this->isInActiveGroup()) ||
- context->isRendering();
+ bool is_active = ((editorNode->flag & NODE_DO_OUTPUT_RECALC || context->isRendering()) &&
+ (editorNode->flag & NODE_DO_OUTPUT) && this->isInActiveGroup());
InputSocket *image1Socket = this->getInputSocket(0);
InputSocket *image2Socket = this->getInputSocket(1);
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cpp b/source/blender/compositor/nodes/COM_TranslateNode.cpp
index 44d796c2911..d2cd009449c 100644
--- a/source/blender/compositor/nodes/COM_TranslateNode.cpp
+++ b/source/blender/compositor/nodes/COM_TranslateNode.cpp
@@ -24,6 +24,7 @@
#include "COM_TranslateOperation.h"
#include "COM_WrapOperation.h"
+#include "COM_WriteBufferOperation.h"
#include "COM_ExecutionSystem.h"
TranslateNode::TranslateNode(bNode *editorNode) : Node(editorNode)
@@ -43,10 +44,15 @@ void TranslateNode::convertToOperations(ExecutionSystem *graph, CompositorContex
NodeTranslateData *data = (NodeTranslateData *)bnode->storage;
if (data->wrap_axis) {
+ WriteBufferOperation *writeOperation = new WriteBufferOperation();
WrapOperation *wrapOperation = new WrapOperation();
+ wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy());
wrapOperation->setWrapping(data->wrap_axis);
- inputSocket->relinkConnections(wrapOperation->getInputSocket(0), 0, graph);
+
+ inputSocket->relinkConnections(writeOperation->getInputSocket(0), 0, graph);
addLink(graph, wrapOperation->getOutputSocket(), operation->getInputSocket(0));
+
+ graph->addOperation(writeOperation);
graph->addOperation(wrapOperation);
}
else {
diff --git a/source/blender/compositor/nodes/COM_ZCombineNode.cpp b/source/blender/compositor/nodes/COM_ZCombineNode.cpp
index b48d974e893..b5fe4882f57 100644
--- a/source/blender/compositor/nodes/COM_ZCombineNode.cpp
+++ b/source/blender/compositor/nodes/COM_ZCombineNode.cpp
@@ -28,7 +28,7 @@
#include "COM_SetValueOperation.h"
#include "COM_MathBaseOperation.h"
#include "COM_AntiAliasOperation.h"
-#include "COM_MixBlendOperation.h"
+#include "COM_MixOperation.h"
#include "DNA_material_types.h" // the ramp types
diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
index fa884bacf49..31b0422918a 100644
--- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
@@ -22,7 +22,7 @@
#ifndef _COM_AlphaOverKeyOperation_h
#define _COM_AlphaOverKeyOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
index 91128454783..14e7325ec1d 100644
--- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
@@ -22,7 +22,7 @@
#ifndef _COM_AlphaOverMixedOperation_h_
#define _COM_AlphaOverMixedOperation_h_
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
index d6e9e31c35f..16bd2aeaeed 100644
--- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
@@ -22,7 +22,7 @@
#ifndef _COM_AlphaOverPremultiplyOperation_h
#define _COM_AlphaOverPremultiplyOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.h b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
index 57e5dc991e9..01852084e41 100644
--- a/source/blender/compositor/operations/COM_ChangeHSVOperation.h
+++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
@@ -22,7 +22,7 @@
#ifndef _COM_ChangeHSVOperation_h
#define _COM_ChangeHSVOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.h b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
index 17f84965f63..efb4f7427ca 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.h
@@ -21,7 +21,7 @@
#ifndef _COM_ChannelMatteOperation_h
#define _COM_ChannelMatteOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.h b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
index adebb7a30c2..9557faec855 100644
--- a/source/blender/compositor/operations/COM_ChromaMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.h
@@ -21,7 +21,7 @@
#ifndef _COM_ChromaMatteOperation_h
#define _COM_ChromaMatteOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.h b/source/blender/compositor/operations/COM_ColorMatteOperation.h
index 582a94e1873..f065a5f7e89 100644
--- a/source/blender/compositor/operations/COM_ColorMatteOperation.h
+++ b/source/blender/compositor/operations/COM_ColorMatteOperation.h
@@ -21,7 +21,7 @@
#ifndef _COM_ColorMatteOperation_h
#define _COM_ColorMatteOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp b/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp
deleted file mode 100644
index 3ced0548bb8..00000000000
--- a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_CombineChannelsOperation.h"
-#include "BLI_utildefines.h"
-
-CombineChannelsOperation::CombineChannelsOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_VALUE);
- this->addInputSocket(COM_DT_VALUE);
- this->addInputSocket(COM_DT_VALUE);
- this->addInputSocket(COM_DT_VALUE);
- this->addOutputSocket(COM_DT_COLOR);
- this->setResolutionInputSocketIndex(0);
- this->m_inputChannel1Operation = NULL;
- this->m_inputChannel2Operation = NULL;
- this->m_inputChannel3Operation = NULL;
- this->m_inputChannel4Operation = NULL;
-}
-
-void CombineChannelsOperation::initExecution()
-{
- this->m_inputChannel1Operation = this->getInputSocketReader(0);
- this->m_inputChannel2Operation = this->getInputSocketReader(1);
- this->m_inputChannel3Operation = this->getInputSocketReader(2);
- this->m_inputChannel4Operation = this->getInputSocketReader(3);
-}
-
-void CombineChannelsOperation::deinitExecution()
-{
- this->m_inputChannel1Operation = NULL;
- this->m_inputChannel2Operation = NULL;
- this->m_inputChannel3Operation = NULL;
- this->m_inputChannel4Operation = NULL;
-}
-
-
-void CombineChannelsOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float input[4];
- if (this->m_inputChannel1Operation) {
- this->m_inputChannel1Operation->read(input, x, y, sampler);
- output[0] = input[0];
- }
- if (this->m_inputChannel2Operation) {
- this->m_inputChannel2Operation->read(input, x, y, sampler);
- output[1] = input[0];
- }
- if (this->m_inputChannel3Operation) {
- this->m_inputChannel3Operation->read(input, x, y, sampler);
- output[2] = input[0];
- }
- if (this->m_inputChannel4Operation) {
- this->m_inputChannel4Operation->read(input, x, y, sampler);
- output[3] = input[0];
- }
-}
diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.h b/source/blender/compositor/operations/COM_CombineChannelsOperation.h
deleted file mode 100644
index 7c8742b1557..00000000000
--- a/source/blender/compositor/operations/COM_CombineChannelsOperation.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_CombineChannelsOperation_h_
-#define _COM_CombineChannelsOperation_h_
-
-#include "COM_NodeOperation.h"
-
-class CombineChannelsOperation : public NodeOperation {
-private:
- SocketReader *m_inputChannel1Operation;
- SocketReader *m_inputChannel2Operation;
- SocketReader *m_inputChannel3Operation;
- SocketReader *m_inputChannel4Operation;
-public:
- CombineChannelsOperation();
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- void initExecution();
- void deinitExecution();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp
deleted file mode 100644
index 3b5aa8cd755..00000000000
--- a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertColorToBWOperation.h"
-
-ConvertColorToBWOperation::ConvertColorToBWOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_VALUE);
- this->m_inputOperation = NULL;
-}
-
-void ConvertColorToBWOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertColorToBWOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- this->m_inputOperation->read(inputColor, x, y, sampler);
- output[0] = rgb_to_bw(inputColor);
-}
-
-void ConvertColorToBWOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.h b/source/blender/compositor/operations/COM_ConvertColorToBWOperation.h
deleted file mode 100644
index 963bd32a2f6..00000000000
--- a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertColorToBWOperation_h
-#define _COM_ConvertColorToBWOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertColorToBWOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertColorToBWOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertColorToValueProg.cpp b/source/blender/compositor/operations/COM_ConvertColorToValueProg.cpp
deleted file mode 100644
index 44e751d1cae..00000000000
--- a/source/blender/compositor/operations/COM_ConvertColorToValueProg.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertColorToValueProg.h"
-
-ConvertColorToValueProg::ConvertColorToValueProg() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_VALUE);
- this->m_inputOperation = NULL;
-}
-
-void ConvertColorToValueProg::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertColorToValueProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- this->m_inputOperation->read(inputColor, x, y, sampler);
- output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f;
-}
-
-void ConvertColorToValueProg::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertColorToValueProg.h b/source/blender/compositor/operations/COM_ConvertColorToValueProg.h
deleted file mode 100644
index 5c25d5d0540..00000000000
--- a/source/blender/compositor/operations/COM_ConvertColorToValueProg.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertColorToValueProg_h
-#define _COM_ConvertColorToValueProg_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertColorToValueProg : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertColorToValueProg();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.cpp
deleted file mode 100644
index a9b8cbb4272..00000000000
--- a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertColorToVectorOperation.h"
-
-ConvertColorToVectorOperation::ConvertColorToVectorOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_VECTOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertColorToVectorOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertColorToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- this->m_inputOperation->read(output, x, y, sampler);
-}
-
-void ConvertColorToVectorOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.h b/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.h
deleted file mode 100644
index 93644cb5d1c..00000000000
--- a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertColorToVectorOperation_h
-#define _COM_ConvertColorToVectorOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertColorToVectorOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertColorToVectorOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.cpp b/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.cpp
deleted file mode 100644
index 65907a8e537..00000000000
--- a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertHSVToRGBOperation.h"
-#include "BLI_math_color.h"
-
-ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertHSVToRGBOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertHSVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- this->m_inputOperation->read(inputColor, x, y, sampler);
- hsv_to_rgb_v(inputColor, output);
- output[3] = inputColor[3];
-}
-
-void ConvertHSVToRGBOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
-
diff --git a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.h b/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.h
deleted file mode 100644
index 17419ca2a05..00000000000
--- a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertHSVToRGBOperation_h
-#define _COM_ConvertHSVToRGBOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertHSVToRGBOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertHSVToRGBOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp
new file mode 100644
index 00000000000..d72aabb078e
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp
@@ -0,0 +1,429 @@
+/*
+ * Copyright 2011, 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:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ */
+
+#include "COM_ConvertOperation.h"
+
+
+ConvertBaseOperation::ConvertBaseOperation()
+{
+ this->m_inputOperation = NULL;
+}
+
+void ConvertBaseOperation::initExecution()
+{
+ this->m_inputOperation = this->getInputSocketReader(0);
+}
+
+void ConvertBaseOperation::deinitExecution()
+{
+ this->m_inputOperation = NULL;
+}
+
+
+/* ******** Value to Color ******** */
+
+ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_VALUE);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertValueToColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputValue[4];
+ this->m_inputOperation->read(inputValue, x, y, sampler);
+ output[0] = output[1] = output[2] = inputValue[0];
+ output[3] = 1.0f;
+}
+
+
+/* ******** Color to Value ******** */
+
+ConvertColorToValueOperation::ConvertColorToValueOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+void ConvertColorToValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+ output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f;
+}
+
+
+/* ******** Color to BW ******** */
+
+ConvertColorToBWOperation::ConvertColorToBWOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+void ConvertColorToBWOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+ output[0] = rgb_to_bw(inputColor);
+}
+
+
+/* ******** Color to Vector ******** */
+
+ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VECTOR);
+}
+
+void ConvertColorToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ this->m_inputOperation->read(output, x, y, sampler);
+}
+
+
+/* ******** Value to Vector ******** */
+
+ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_VALUE);
+ this->addOutputSocket(COM_DT_VECTOR);
+}
+
+void ConvertValueToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float input[4];
+ this->m_inputOperation->read(input, x, y, sampler);
+ output[0] = input[0];
+ output[1] = input[0];
+ output[2] = input[0];
+ output[3] = 0.0f;
+}
+
+
+/* ******** Vector to Color ******** */
+
+ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_VECTOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertVectorToColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ this->m_inputOperation->read(output, x, y, sampler);
+ output[3] = 1.0f;
+}
+
+
+/* ******** Vector to Value ******** */
+
+ConvertVectorToValueOperation::ConvertVectorToValueOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_VECTOR);
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+void ConvertVectorToValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float input[4];
+ this->m_inputOperation->read(input, x, y, sampler);
+ output[0] = (input[0] + input[1] + input[2]) / 3.0f;
+}
+
+
+/* ******** RGB to YCC ******** */
+
+ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertRGBToYCCOperation::setMode(int mode)
+{
+ switch (mode) {
+ case 1:
+ this->m_mode = BLI_YCC_ITU_BT709;
+ break;
+ case 2:
+ this->m_mode = BLI_YCC_JFIF_0_255;
+ break;
+ case 0:
+ default:
+ this->m_mode = BLI_YCC_ITU_BT601;
+ break;
+ }
+}
+
+void ConvertRGBToYCCOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ float color[3];
+
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+ rgb_to_ycc(inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode);
+
+ /* divided by 255 to normalize for viewing in */
+ /* R,G,B --> Y,Cb,Cr */
+ mul_v3_v3fl(output, color, 1.0f / 255.0f);
+ output[3] = inputColor[3];
+}
+
+/* ******** YCC to RGB ******** */
+
+ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertYCCToRGBOperation::setMode(int mode)
+{
+ switch (mode) {
+ case 1:
+ this->m_mode = BLI_YCC_ITU_BT709;
+ break;
+ case 2:
+ this->m_mode = BLI_YCC_JFIF_0_255;
+ break;
+ case 0:
+ default:
+ this->m_mode = BLI_YCC_ITU_BT601;
+ break;
+ }
+}
+
+void ConvertYCCToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+
+ /* need to un-normalize the data */
+ /* R,G,B --> Y,Cb,Cr */
+ mul_v3_fl(inputColor, 255.0f);
+
+ ycc_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], this->m_mode);
+ output[3] = inputColor[3];
+}
+
+
+/* ******** RGB to YUV ******** */
+
+ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertRGBToYUVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+ rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]);
+ output[3] = inputColor[3];
+}
+
+
+/* ******** YUV to RGB ******** */
+
+ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertYUVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+ yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]);
+ output[3] = inputColor[3];
+}
+
+
+/* ******** RGB to HSV ******** */
+
+ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertRGBToHSVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+ rgb_to_hsv_v(inputColor, output);
+ output[3] = inputColor[3];
+}
+
+
+/* ******** HSV to RGB ******** */
+
+ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertHSVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor[4];
+ this->m_inputOperation->read(inputColor, x, y, sampler);
+ hsv_to_rgb_v(inputColor, output);
+ output[3] = inputColor[3];
+}
+
+
+/* ******** Premul to Straight ******** */
+
+ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertPremulToStraightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputValue[4];
+ float alpha;
+
+ this->m_inputOperation->read(inputValue, x, y, sampler);
+ alpha = inputValue[3];
+
+ if (fabsf(alpha) < 1e-5f) {
+ zero_v3(output);
+ }
+ else {
+ mul_v3_v3fl(output, inputValue, 1.0f / alpha);
+ }
+
+ /* never touches the alpha */
+ output[3] = alpha;
+}
+
+
+/* ******** Straight to Premul ******** */
+
+ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : ConvertBaseOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+void ConvertStraightToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputValue[4];
+ float alpha;
+
+ this->m_inputOperation->read(inputValue, x, y, sampler);
+ alpha = inputValue[3];
+
+ mul_v3_v3fl(output, inputValue, alpha);
+
+ /* never touches the alpha */
+ output[3] = alpha;
+}
+
+
+/* ******** Separate Channels ******** */
+
+SeparateChannelOperation::SeparateChannelOperation() : NodeOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_VALUE);
+ this->m_inputOperation = NULL;
+}
+void SeparateChannelOperation::initExecution()
+{
+ this->m_inputOperation = this->getInputSocketReader(0);
+}
+
+void SeparateChannelOperation::deinitExecution()
+{
+ this->m_inputOperation = NULL;
+}
+
+
+void SeparateChannelOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float input[4];
+ this->m_inputOperation->read(input, x, y, sampler);
+ output[0] = input[this->m_channel];
+}
+
+
+/* ******** Combine Channels ******** */
+
+CombineChannelsOperation::CombineChannelsOperation() : NodeOperation()
+{
+ this->addInputSocket(COM_DT_VALUE);
+ this->addInputSocket(COM_DT_VALUE);
+ this->addInputSocket(COM_DT_VALUE);
+ this->addInputSocket(COM_DT_VALUE);
+ this->addOutputSocket(COM_DT_COLOR);
+ this->setResolutionInputSocketIndex(0);
+ this->m_inputChannel1Operation = NULL;
+ this->m_inputChannel2Operation = NULL;
+ this->m_inputChannel3Operation = NULL;
+ this->m_inputChannel4Operation = NULL;
+}
+
+void CombineChannelsOperation::initExecution()
+{
+ this->m_inputChannel1Operation = this->getInputSocketReader(0);
+ this->m_inputChannel2Operation = this->getInputSocketReader(1);
+ this->m_inputChannel3Operation = this->getInputSocketReader(2);
+ this->m_inputChannel4Operation = this->getInputSocketReader(3);
+}
+
+void CombineChannelsOperation::deinitExecution()
+{
+ this->m_inputChannel1Operation = NULL;
+ this->m_inputChannel2Operation = NULL;
+ this->m_inputChannel3Operation = NULL;
+ this->m_inputChannel4Operation = NULL;
+}
+
+
+void CombineChannelsOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float input[4];
+ if (this->m_inputChannel1Operation) {
+ this->m_inputChannel1Operation->read(input, x, y, sampler);
+ output[0] = input[0];
+ }
+ if (this->m_inputChannel2Operation) {
+ this->m_inputChannel2Operation->read(input, x, y, sampler);
+ output[1] = input[0];
+ }
+ if (this->m_inputChannel3Operation) {
+ this->m_inputChannel3Operation->read(input, x, y, sampler);
+ output[2] = input[0];
+ }
+ if (this->m_inputChannel4Operation) {
+ this->m_inputChannel4Operation->read(input, x, y, sampler);
+ output[3] = input[0];
+ }
+}
diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h
new file mode 100644
index 00000000000..06aeb2e52d7
--- /dev/null
+++ b/source/blender/compositor/operations/COM_ConvertOperation.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2011, 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:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ */
+
+#ifndef _COM_ConvertOperation_h
+#define _COM_ConvertOperation_h
+
+#include "COM_NodeOperation.h"
+
+
+class ConvertBaseOperation : public NodeOperation {
+protected:
+ SocketReader *m_inputOperation;
+
+public:
+ ConvertBaseOperation();
+
+ void initExecution();
+ void deinitExecution();
+};
+
+
+class ConvertValueToColorOperation : public ConvertBaseOperation {
+public:
+ ConvertValueToColorOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertColorToValueOperation : public ConvertBaseOperation {
+public:
+ ConvertColorToValueOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertColorToBWOperation : public ConvertBaseOperation {
+public:
+ ConvertColorToBWOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertColorToVectorOperation : public ConvertBaseOperation {
+public:
+ ConvertColorToVectorOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertValueToVectorOperation : public ConvertBaseOperation {
+public:
+ ConvertValueToVectorOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertVectorToColorOperation : public ConvertBaseOperation {
+public:
+ ConvertVectorToColorOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertVectorToValueOperation : public ConvertBaseOperation {
+public:
+ ConvertVectorToValueOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertRGBToYCCOperation : public ConvertBaseOperation {
+private:
+ /** YCbCr mode (Jpeg, ITU601, ITU709) */
+ int m_mode;
+public:
+ ConvertRGBToYCCOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+ /** Set the YCC mode */
+ void setMode(int mode);
+};
+
+
+class ConvertYCCToRGBOperation : public ConvertBaseOperation {
+private:
+ /** YCbCr mode (Jpeg, ITU601, ITU709) */
+ int m_mode;
+public:
+ ConvertYCCToRGBOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+ /** Set the YCC mode */
+ void setMode(int mode);
+};
+
+
+class ConvertRGBToYUVOperation : public ConvertBaseOperation {
+public:
+ ConvertRGBToYUVOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertYUVToRGBOperation : public ConvertBaseOperation {
+public:
+ ConvertYUVToRGBOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertRGBToHSVOperation : public ConvertBaseOperation {
+public:
+ ConvertRGBToHSVOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertHSVToRGBOperation : public ConvertBaseOperation {
+public:
+ ConvertHSVToRGBOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertPremulToStraightOperation : public ConvertBaseOperation {
+public:
+ ConvertPremulToStraightOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class ConvertStraightToPremulOperation : public ConvertBaseOperation {
+public:
+ ConvertStraightToPremulOperation();
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+
+class SeparateChannelOperation : public NodeOperation {
+private:
+ SocketReader *m_inputOperation;
+ int m_channel;
+public:
+ SeparateChannelOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+ void initExecution();
+ void deinitExecution();
+
+ void setChannel(int channel) { this->m_channel = channel; }
+};
+
+
+class CombineChannelsOperation : public NodeOperation {
+private:
+ SocketReader *m_inputChannel1Operation;
+ SocketReader *m_inputChannel2Operation;
+ SocketReader *m_inputChannel3Operation;
+ SocketReader *m_inputChannel4Operation;
+public:
+ CombineChannelsOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+ void initExecution();
+ void deinitExecution();
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp
deleted file mode 100644
index 2af4b55de1a..00000000000
--- a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2012, 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:
- * Dalai Felinto
- */
-
-#include "COM_ConvertPremulToStraightOperation.h"
-#include "BLI_math.h"
-
-ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
-
- this->m_inputColor = NULL;
-}
-
-void ConvertPremulToStraightOperation::initExecution()
-{
- this->m_inputColor = getInputSocketReader(0);
-}
-
-void ConvertPremulToStraightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputValue[4];
- float alpha;
-
- this->m_inputColor->read(inputValue, x, y, sampler);
- alpha = inputValue[3];
-
- if (fabsf(alpha) < 1e-5f) {
- zero_v3(output);
- }
- else {
- mul_v3_v3fl(output, inputValue, 1.0f / alpha);
- }
-
- /* never touches the alpha */
- output[3] = alpha;
-}
-
-void ConvertPremulToStraightOperation::deinitExecution()
-{
- this->m_inputColor = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.cpp b/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.cpp
deleted file mode 100644
index 3c7a9d5fd50..00000000000
--- a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertRGBToHSVOperation.h"
-#include "BLI_math_color.h"
-
-ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertRGBToHSVOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertRGBToHSVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- this->m_inputOperation->read(inputColor, x, y, sampler);
- rgb_to_hsv_v(inputColor, output);
- output[3] = inputColor[3];
-}
-
-void ConvertRGBToHSVOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.h b/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.h
deleted file mode 100644
index fdc8dfed31b..00000000000
--- a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertRGBToHSVOperation_h
-#define _COM_ConvertRGBToHSVOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertRGBToHSVOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertRGBToHSVOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.cpp b/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.cpp
deleted file mode 100644
index 6f6dffdc72b..00000000000
--- a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#include "COM_ConvertRGBToYCCOperation.h"
-#include "BLI_math_color.h"
-
-ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertRGBToYCCOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertRGBToYCCOperation::setMode(int mode)
-{
- switch (mode) {
- case 1:
- this->m_mode = BLI_YCC_ITU_BT709;
- break;
- case 2:
- this->m_mode = BLI_YCC_JFIF_0_255;
- break;
- case 0:
- default:
- this->m_mode = BLI_YCC_ITU_BT601;
- break;
- }
-}
-
-void ConvertRGBToYCCOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- float color[3];
-
- this->m_inputOperation->read(inputColor, x, y, sampler);
- rgb_to_ycc(inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode);
-
- /* divided by 255 to normalize for viewing in */
- /* R,G,B --> Y,Cb,Cr */
- mul_v3_v3fl(output, color, 1.0f / 255.0f);
- output[3] = inputColor[3];
-}
-
-void ConvertRGBToYCCOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.h b/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.h
deleted file mode 100644
index 3f85555f3bb..00000000000
--- a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#ifndef _COM_ConvertRGBToYCCOperation_h
-#define _COM_ConvertRGBToYCCOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertRGBToYCCOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-
- /**
- * YCbCr mode (Jpeg, ITU601, ITU709)
- */
- int m_mode;
-public:
- /**
- * Default constructor
- */
- ConvertRGBToYCCOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-
- /**
- * Set the YCC mode
- */
- void setMode(int mode);
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.cpp b/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.cpp
deleted file mode 100644
index 8ce9e150080..00000000000
--- a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#include "COM_ConvertRGBToYUVOperation.h"
-#include "BLI_math_color.h"
-
-ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertRGBToYUVOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertRGBToYUVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- this->m_inputOperation->read(inputColor, x, y, sampler);
- rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]);
- output[3] = inputColor[3];
-}
-
-void ConvertRGBToYUVOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.h b/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.h
deleted file mode 100644
index 97d57f657ec..00000000000
--- a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#ifndef _COM_ConvertRGBToYUVOperation_h
-#define _COM_ConvertRGBToYUVOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertRGBToYUVOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertRGBToYUVOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp
deleted file mode 100644
index ae55d949ff2..00000000000
--- a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012, 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:
- * Dalai Felinto
- */
-
-#include "COM_ConvertStraightToPremulOperation.h"
-#include "BLI_math.h"
-
-ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
-
- this->m_inputColor = NULL;
-}
-
-void ConvertStraightToPremulOperation::initExecution()
-{
- this->m_inputColor = getInputSocketReader(0);
-}
-
-void ConvertStraightToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputValue[4];
- float alpha;
-
- this->m_inputColor->read(inputValue, x, y, sampler);
- alpha = inputValue[3];
-
- mul_v3_v3fl(output, inputValue, alpha);
-
- /* never touches the alpha */
- output[3] = alpha;
-}
-
-void ConvertStraightToPremulOperation::deinitExecution()
-{
- this->m_inputColor = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertValueToColorProg.cpp b/source/blender/compositor/operations/COM_ConvertValueToColorProg.cpp
deleted file mode 100644
index 98e7650aa56..00000000000
--- a/source/blender/compositor/operations/COM_ConvertValueToColorProg.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertValueToColorProg.h"
-
-ConvertValueToColorProg::ConvertValueToColorProg() : NodeOperation()
-{
- this->addInputSocket(COM_DT_VALUE);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputProgram = NULL;
-}
-void ConvertValueToColorProg::initExecution()
-{
- this->m_inputProgram = this->getInputSocketReader(0);
-}
-
-void ConvertValueToColorProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputValue[4];
- this->m_inputProgram->read(inputValue, x, y, sampler);
- output[0] = output[1] = output[2] = inputValue[0];
- output[3] = 1.0f;
-}
-
-void ConvertValueToColorProg::deinitExecution()
-{
- this->m_inputProgram = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertValueToColorProg.h b/source/blender/compositor/operations/COM_ConvertValueToColorProg.h
deleted file mode 100644
index f0f6cfb8fd2..00000000000
--- a/source/blender/compositor/operations/COM_ConvertValueToColorProg.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertValueToColorProg_h
-#define _COM_ConvertValueToColorProg_h
-#include "COM_NodeOperation.h"
-
-
-class ConvertValueToColorProg : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputProgram;
-public:
- ConvertValueToColorProg();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.cpp b/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.cpp
deleted file mode 100644
index 411409d263c..00000000000
--- a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertValueToVectorOperation.h"
-
-ConvertValueToVectorOperation::ConvertValueToVectorOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_VALUE);
- this->addOutputSocket(COM_DT_VECTOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertValueToVectorOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertValueToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float input[4];
- this->m_inputOperation->read(input, x, y, sampler);
- output[0] = input[0];
- output[1] = input[0];
- output[2] = input[0];
- output[3] = 0.0f;
-}
-
-void ConvertValueToVectorOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.h b/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.h
deleted file mode 100644
index da45848ca34..00000000000
--- a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertValueToVectorOperation_h
-#define _COM_ConvertValueToVectorOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertValueToVectorOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertValueToVectorOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.cpp b/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.cpp
deleted file mode 100644
index 78cb706c32d..00000000000
--- a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertVectorToColorOperation.h"
-
-ConvertVectorToColorOperation::ConvertVectorToColorOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_VECTOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertVectorToColorOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertVectorToColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- this->m_inputOperation->read(output, x, y, sampler);
- output[3] = 1.0f;
-}
-
-void ConvertVectorToColorOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.h b/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.h
deleted file mode 100644
index 9ef5f8fece3..00000000000
--- a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertVectorToColorOperation_h
-#define _COM_ConvertVectorToColorOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertVectorToColorOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertVectorToColorOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.cpp b/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.cpp
deleted file mode 100644
index a3612414029..00000000000
--- a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_ConvertVectorToValueOperation.h"
-
-ConvertVectorToValueOperation::ConvertVectorToValueOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_VECTOR);
- this->addOutputSocket(COM_DT_VALUE);
- this->m_inputOperation = NULL;
-}
-
-void ConvertVectorToValueOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertVectorToValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float input[4];
- this->m_inputOperation->read(input, x, y, sampler);
- output[0] = (input[0] + input[1] + input[2]) / 3.0f;
-}
-
-void ConvertVectorToValueOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.h b/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.h
deleted file mode 100644
index e42f235a12b..00000000000
--- a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_ConvertVectorToValueOperation_h
-#define _COM_ConvertVectorToValueOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertVectorToValueOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertVectorToValueOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.cpp b/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.cpp
deleted file mode 100644
index 8f9eaf49ea4..00000000000
--- a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#include "COM_ConvertYCCToRGBOperation.h"
-#include "BLI_math_color.h"
-
-ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertYCCToRGBOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertYCCToRGBOperation::setMode(int mode)
-{
- switch (mode) {
- case 1:
- this->m_mode = BLI_YCC_ITU_BT709;
- break;
- case 2:
- this->m_mode = BLI_YCC_JFIF_0_255;
- break;
- case 0:
- default:
- this->m_mode = BLI_YCC_ITU_BT601;
- break;
- }
-}
-
-void ConvertYCCToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- this->m_inputOperation->read(inputColor, x, y, sampler);
-
- /* need to un-normalize the data */
- /* R,G,B --> Y,Cb,Cr */
- mul_v3_fl(inputColor, 255.0f);
-
- ycc_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], this->m_mode);
- output[3] = inputColor[3];
-}
-
-void ConvertYCCToRGBOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
-
diff --git a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.h b/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.h
deleted file mode 100644
index 0a8b67e0bee..00000000000
--- a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#ifndef _COM_ConvertYCCToRGBOperation_h
-#define _COM_ConvertYCCToRGBOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertYCCToRGBOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-
- /**
- * YCbCr mode (Jpeg, ITU601, ITU709)
- */
- int m_mode;
-public:
- /**
- * Default constructor
- */
- ConvertYCCToRGBOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-
- /**
- * Set the YCC mode
- */
- void setMode(int mode);
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.cpp b/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.cpp
deleted file mode 100644
index 197c7f9f043..00000000000
--- a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#include "COM_ConvertYUVToRGBOperation.h"
-#include "BLI_math_color.h"
-
-ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputOperation = NULL;
-}
-
-void ConvertYUVToRGBOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void ConvertYUVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor[4];
- this->m_inputOperation->read(inputColor, x, y, sampler);
- yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]);
- output[3] = inputColor[3];
-}
-
-void ConvertYUVToRGBOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
-
diff --git a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.h b/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.h
deleted file mode 100644
index ee11ef8df60..00000000000
--- a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Dalai Felinto
- */
-
-#ifndef _COM_ConvertYUVToRGBOperation_h
-#define _COM_ConvertYUVToRGBOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertYUVToRGBOperation : public NodeOperation {
-private:
- /**
- * Cached reference to the inputProgram
- */
- SocketReader *m_inputOperation;
-public:
- /**
- * Default constructor
- */
- ConvertYUVToRGBOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
index e7d881cbbd5..e0a38f703ed 100644
--- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h
@@ -22,7 +22,7 @@
#ifndef _COM_DifferenceMatteOperation_h
#define _COM_DifferenceMatteOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
index 5a34135b1a4..43299486f60 100644
--- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h
@@ -21,7 +21,7 @@
#ifndef _COM_DistanceRGBMatteOperation_h
#define _COM_DistanceRGBMatteOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
index f4866a327f1..27025188d49 100644
--- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
+++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h
@@ -21,7 +21,7 @@
#ifndef _COM_DistanceYCCMatteOperation_h
#define _COM_DistanceYCCMatteOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
#include "COM_DistanceRGBMatteOperation.h"
diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
index c4f8b3a0ddb..8854be52ded 100644
--- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
@@ -83,11 +83,11 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
for (x = 0; x < gbuf->getWidth(); x++) {
u = ((float)x + 0.5f) / (float)gbuf->getWidth();
s = (u - 0.5f) * sc + 0.5f, t = (v - 0.5f) * sc + 0.5f;
- tbuf1->readCubic(c, s * gbuf->getWidth(), t * gbuf->getHeight());
+ tbuf1->readBilinear(c, s * gbuf->getWidth(), t * gbuf->getHeight());
sm = smoothMask(s, t);
mul_v3_fl(c, sm);
s = (u - 0.5f) * isc + 0.5f, t = (v - 0.5f) * isc + 0.5f;
- tbuf2->readCubic(tc, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f);
+ tbuf2->readBilinear(tc, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f);
sm = smoothMask(s, t);
madd_v3_v3fl(c, tc, sm);
@@ -108,7 +108,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
np = (n << 2) + p;
s = (u - 0.5f) * scalef[np] + 0.5f;
t = (v - 0.5f) * scalef[np] + 0.5f;
- gbuf->readCubic(c, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f);
+ gbuf->readBilinear(c, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f);
mul_v3_v3(c, cm[np]);
sm = smoothMask(s, t) * 0.25f;
madd_v3_v3fl(tc, c, sm);
diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
index 60d37fb8145..5644ff30ef3 100644
--- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
@@ -54,9 +54,9 @@ void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile,
// first pass no offset, always same for every pass, exact copy,
// otherwise results in uneven brightness, only need once
if (n == 0) tsrc->read(c1, x, y); else c1[0] = c1[1] = c1[2] = 0;
- tsrc->readCubic(c2, x + vxp, y + vyp);
- tsrc->readCubic(c3, x + vxp * 2.f, y + vyp * 2.f);
- tsrc->readCubic(c4, x + vxp * 3.f, y + vyp * 3.f);
+ tsrc->readBilinear(c2, x + vxp, y + vyp);
+ tsrc->readBilinear(c3, x + vxp * 2.f, y + vyp * 2.f);
+ tsrc->readBilinear(c4, x + vxp * 3.f, y + vyp * 3.f);
// modulate color to look vaguely similar to a color spectrum
c2[1] *= cmo;
c2[2] *= cmo;
diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp
index c8e3dbf993d..cface29fdca 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_ImageOperation.cpp
@@ -40,7 +40,8 @@ BaseImageOperation::BaseImageOperation() : NodeOperation()
{
this->m_image = NULL;
this->m_buffer = NULL;
- this->m_imageBuffer = NULL;
+ this->m_imageFloatBuffer = NULL;
+ this->m_imageByteBuffer = NULL;
this->m_imageUser = NULL;
this->m_imagewidth = 0;
this->m_imageheight = 0;
@@ -70,10 +71,6 @@ ImBuf *BaseImageOperation::getImBuf()
BKE_image_release_ibuf(this->m_image, ibuf, NULL);
return NULL;
}
-
- if (ibuf->rect_float == NULL) {
- IMB_float_from_rect(ibuf);
- }
return ibuf;
}
@@ -83,7 +80,8 @@ void BaseImageOperation::initExecution()
ImBuf *stackbuf = getImBuf();
this->m_buffer = stackbuf;
if (stackbuf) {
- this->m_imageBuffer = stackbuf->rect_float;
+ this->m_imageFloatBuffer = stackbuf->rect_float;
+ this->m_imageByteBuffer = stackbuf->rect;
this->m_depthBuffer = stackbuf->zbuf_float;
this->m_imagewidth = stackbuf->x;
this->m_imageheight = stackbuf->y;
@@ -93,7 +91,8 @@ void BaseImageOperation::initExecution()
void BaseImageOperation::deinitExecution()
{
- this->m_imageBuffer = NULL;
+ this->m_imageFloatBuffer = NULL;
+ this->m_imageByteBuffer = NULL;
BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL);
}
@@ -112,23 +111,48 @@ void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigne
BKE_image_release_ibuf(this->m_image, stackbuf, NULL);
}
-void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+static void sampleImageAtLocation(ImBuf *ibuf, float x, float y, PixelSampler sampler, bool make_linear_rgb, float color[4])
{
- if (this->m_imageBuffer == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
- zero_v4(output);
+ if (ibuf->rect_float) {
+ switch (sampler) {
+ case COM_PS_NEAREST:
+ nearest_interpolation_color(ibuf, NULL, color, x, y);
+ break;
+ case COM_PS_BILINEAR:
+ bilinear_interpolation_color(ibuf, NULL, color, x, y);
+ break;
+ case COM_PS_BICUBIC:
+ bicubic_interpolation_color(ibuf, NULL, color, x, y);
+ break;
+ }
}
else {
+ unsigned char byte_color[4];
switch (sampler) {
case COM_PS_NEAREST:
- nearest_interpolation_color(this->m_buffer, NULL, output, x, y);
+ nearest_interpolation_color(ibuf, byte_color, NULL, x, y);
break;
case COM_PS_BILINEAR:
- bilinear_interpolation_color(this->m_buffer, NULL, output, x, y);
+ bilinear_interpolation_color(ibuf, byte_color, NULL, x, y);
break;
case COM_PS_BICUBIC:
- bicubic_interpolation_color(this->m_buffer, NULL, output, x, y);
+ bicubic_interpolation_color(ibuf, byte_color, NULL, x, y);
break;
}
+ rgba_uchar_to_float(color, byte_color);
+ if (make_linear_rgb) {
+ IMB_colormanagement_colorspace_to_scene_linear_v4(color, false, ibuf->rect_colorspace);
+ }
+ }
+}
+
+void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ if ((this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+ zero_v4(output);
+ }
+ else {
+ sampleImageAtLocation(this->m_buffer, x, y, sampler, true, output);
}
}
@@ -136,22 +160,12 @@ void ImageAlphaOperation::executePixel(float output[4], float x, float y, PixelS
{
float tempcolor[4];
- if (this->m_imageBuffer == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+ if ((this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
output[0] = 0.0f;
}
else {
tempcolor[3] = 1.0f;
- switch (sampler) {
- case COM_PS_NEAREST:
- nearest_interpolation_color(this->m_buffer, NULL, tempcolor, x, y);
- break;
- case COM_PS_BILINEAR:
- bilinear_interpolation_color(this->m_buffer, NULL, tempcolor, x, y);
- break;
- case COM_PS_BICUBIC:
- bicubic_interpolation_color(this->m_buffer, NULL, tempcolor, x, y);
- break;
- }
+ sampleImageAtLocation(this->m_buffer, x, y, sampler, false, tempcolor);
output[0] = tempcolor[3];
}
}
diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h
index e75e7daa186..b51f11edd04 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.h
+++ b/source/blender/compositor/operations/COM_ImageOperation.h
@@ -42,7 +42,8 @@ protected:
ImBuf *m_buffer;
Image *m_image;
ImageUser *m_imageUser;
- float *m_imageBuffer;
+ float *m_imageFloatBuffer;
+ unsigned int *m_imageByteBuffer;
float *m_depthBuffer;
int m_imageheight;
int m_imagewidth;
diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
index 009a1e8825e..cb8cc01efea 100644
--- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
+++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h
@@ -21,7 +21,7 @@
#ifndef _COM_LuminanceMatteOperation_h
#define _COM_LuminanceMatteOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp
index 1fa484ea2b6..a9b6ad3edc1 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.cpp
+++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp
@@ -71,38 +71,12 @@ void MapUVOperation::executePixel(float output[4], float x, float y, PixelSample
dy = 0.5f * (uv_u + uv_d);
- /* more adaptive sampling, red and green (UV) channels */
- this->m_inputUVProgram->read(uv_a, x - 1, y - 1, COM_PS_NEAREST);
- this->m_inputUVProgram->read(uv_b, x - 1, y + 1, COM_PS_NEAREST);
- uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
- uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
- uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
- uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
-
- dx += 0.25f * (uv_l + uv_r);
- dy += 0.25f * (uv_u + uv_d);
-
- this->m_inputUVProgram->read(uv_a, x + 1, y - 1, COM_PS_NEAREST);
- this->m_inputUVProgram->read(uv_b, x + 1, y + 1, COM_PS_NEAREST);
- uv_l = uv_a[2] != 0.f ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
- uv_r = uv_b[2] != 0.f ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
- uv_u = uv_a[2] != 0.f ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
- uv_d = uv_b[2] != 0.f ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
-
- dx += 0.25f * (uv_l + uv_r);
- dy += 0.25f * (uv_u + uv_d);
-
/* UV to alpha threshold */
const float threshold = this->m_alpha * 0.05f;
float alpha = 1.0f - threshold * (dx + dy);
if (alpha < 0.f) alpha = 0.f;
else alpha *= inputUV[2];
- /* should use mipmap */
- dx = min(dx, 0.2f);
- dy = min(dy, 0.2f);
-
-
/* EWA filtering */
u = inputUV[0] * this->m_inputColorProgram->getWidth();
v = inputUV[1] * this->m_inputColorProgram->getHeight();
diff --git a/source/blender/compositor/operations/COM_MixAddOperation.cpp b/source/blender/compositor/operations/COM_MixAddOperation.cpp
deleted file mode 100644
index 4e0876439c0..00000000000
--- a/source/blender/compositor/operations/COM_MixAddOperation.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixAddOperation.h"
-
-MixAddOperation::MixAddOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixAddOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- output[0] = inputColor1[0] + value * inputColor2[0];
- output[1] = inputColor1[1] + value * inputColor2[1];
- output[2] = inputColor1[2] + value * inputColor2[2];
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixAddOperation.h b/source/blender/compositor/operations/COM_MixAddOperation.h
deleted file mode 100644
index 5a52846e847..00000000000
--- a/source/blender/compositor/operations/COM_MixAddOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixAddOperation_h
-#define _COM_MixAddOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixAddOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixAddOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.cpp b/source/blender/compositor/operations/COM_MixBaseOperation.cpp
deleted file mode 100644
index 5b455338bb0..00000000000
--- a/source/blender/compositor/operations/COM_MixBaseOperation.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixBaseOperation.h"
-
-MixBaseOperation::MixBaseOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_VALUE);
- this->addInputSocket(COM_DT_COLOR);
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->m_inputValueOperation = NULL;
- this->m_inputColor1Operation = NULL;
- this->m_inputColor2Operation = NULL;
- this->setUseValueAlphaMultiply(false);
- this->setUseClamp(false);
-}
-
-void MixBaseOperation::initExecution()
-{
- this->m_inputValueOperation = this->getInputSocketReader(0);
- this->m_inputColor1Operation = this->getInputSocketReader(1);
- this->m_inputColor2Operation = this->getInputSocketReader(2);
-}
-
-void MixBaseOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
- output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
- output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
- output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
- output[3] = inputColor1[3];
-}
-
-void MixBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
-{
- InputSocket *socket;
- unsigned int tempPreferredResolution[2] = {0, 0};
- unsigned int tempResolution[2];
-
- socket = this->getInputSocket(1);
- socket->determineResolution(tempResolution, tempPreferredResolution);
- if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
- this->setResolutionInputSocketIndex(1);
- }
- else {
- socket = this->getInputSocket(2);
- socket->determineResolution(tempResolution, tempPreferredResolution);
- if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
- this->setResolutionInputSocketIndex(2);
- }
- else {
- this->setResolutionInputSocketIndex(0);
- }
- }
- NodeOperation::determineResolution(resolution, preferredResolution);
-}
-
-void MixBaseOperation::deinitExecution()
-{
- this->m_inputValueOperation = NULL;
- this->m_inputColor1Operation = NULL;
- this->m_inputColor2Operation = NULL;
-}
diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.h b/source/blender/compositor/operations/COM_MixBaseOperation.h
deleted file mode 100644
index 3c0c0778190..00000000000
--- a/source/blender/compositor/operations/COM_MixBaseOperation.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixBaseOperation_h
-#define _COM_MixBaseOperation_h
-#include "COM_NodeOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixBaseOperation : public NodeOperation {
-protected:
- /**
- * Prefetched reference to the inputProgram
- */
- SocketReader *m_inputValueOperation;
- SocketReader *m_inputColor1Operation;
- SocketReader *m_inputColor2Operation;
- bool m_valueAlphaMultiply;
- bool m_useClamp;
-
- inline void clampIfNeeded(float color[4])
- {
- if (m_useClamp) {
- CLAMP(color[0], 0.0f, 1.0f);
- CLAMP(color[1], 0.0f, 1.0f);
- CLAMP(color[2], 0.0f, 1.0f);
- CLAMP(color[3], 0.0f, 1.0f);
- }
- }
-
-public:
- /**
- * Default constructor
- */
- MixBaseOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
- /**
- * Initialize the execution
- */
- void initExecution();
-
- /**
- * Deinitialize the execution
- */
- void deinitExecution();
-
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
-
- void setUseValueAlphaMultiply(const bool value) { this->m_valueAlphaMultiply = value; }
- bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; }
- void setUseClamp(bool value) { this->m_useClamp = value; }
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixBlendOperation.cpp b/source/blender/compositor/operations/COM_MixBlendOperation.cpp
deleted file mode 100644
index 0ca7d460064..00000000000
--- a/source/blender/compositor/operations/COM_MixBlendOperation.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixBlendOperation.h"
-
-MixBlendOperation::MixBlendOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixBlendOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
- float value;
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
- value = inputValue[0];
-
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
- output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
- output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
- output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
diff --git a/source/blender/compositor/operations/COM_MixBurnOperation.cpp b/source/blender/compositor/operations/COM_MixBurnOperation.cpp
deleted file mode 100644
index d4422c6cc6a..00000000000
--- a/source/blender/compositor/operations/COM_MixBurnOperation.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixBurnOperation.h"
-
-MixBurnOperation::MixBurnOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixBurnOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
- float tmp;
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
-
- tmp = valuem + value * inputColor2[0];
- if (tmp <= 0.0f)
- output[0] = 0.0f;
- else {
- tmp = 1.0f - (1.0f - inputColor1[0]) / tmp;
- if (tmp < 0.0f)
- output[0] = 0.0f;
- else if (tmp > 1.0f)
- output[0] = 1.0f;
- else
- output[0] = tmp;
- }
-
- tmp = valuem + value * inputColor2[1];
- if (tmp <= 0.0f)
- output[1] = 0.0f;
- else {
- tmp = 1.0f - (1.0f - inputColor1[1]) / tmp;
- if (tmp < 0.0f)
- output[1] = 0.0f;
- else if (tmp > 1.0f)
- output[1] = 1.0f;
- else
- output[1] = tmp;
- }
-
- tmp = valuem + value * inputColor2[2];
- if (tmp <= 0.0f)
- output[2] = 0.0f;
- else {
- tmp = 1.0f - (1.0f - inputColor1[2]) / tmp;
- if (tmp < 0.0f)
- output[2] = 0.0f;
- else if (tmp > 1.0f)
- output[2] = 1.0f;
- else
- output[2] = tmp;
- }
-
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixColorOperation.cpp b/source/blender/compositor/operations/COM_MixColorOperation.cpp
deleted file mode 100644
index 6919a636aeb..00000000000
--- a/source/blender/compositor/operations/COM_MixColorOperation.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixColorOperation.h"
-
-extern "C" {
- #include "BLI_math.h"
-}
-
-MixColorOperation::MixColorOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
-
- float colH, colS, colV;
- rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
- if (colS != 0.0f) {
- float rH, rS, rV;
- float tmpr, tmpg, tmpb;
- rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
- hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
- output[0] = (valuem * inputColor1[0]) + (value * tmpr);
- output[1] = (valuem * inputColor1[1]) + (value * tmpg);
- output[2] = (valuem * inputColor1[2]) + (value * tmpb);
- }
- else {
- copy_v3_v3(output, inputColor1);
- }
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixDarkenOperation.cpp b/source/blender/compositor/operations/COM_MixDarkenOperation.cpp
deleted file mode 100644
index d56d9fdf122..00000000000
--- a/source/blender/compositor/operations/COM_MixDarkenOperation.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixDarkenOperation.h"
-
-MixDarkenOperation::MixDarkenOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixDarkenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
- float tmp;
- tmp = inputColor2[0] + ((1.0f - inputColor2[0]) * valuem);
- if (tmp < inputColor1[0]) output[0] = tmp;
- else output[0] = inputColor1[0];
- tmp = inputColor2[1] + ((1.0f - inputColor2[1]) * valuem);
- if (tmp < inputColor1[1]) output[1] = tmp;
- else output[1] = inputColor1[1];
- tmp = inputColor2[2] + ((1.0f - inputColor2[2]) * valuem);
- if (tmp < inputColor1[2]) output[2] = tmp;
- else output[2] = inputColor1[2];
-
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixDarkenOperation.h b/source/blender/compositor/operations/COM_MixDarkenOperation.h
deleted file mode 100644
index f9c35fa364b..00000000000
--- a/source/blender/compositor/operations/COM_MixDarkenOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixDarkenOperation_h
-#define _COM_MixDarkenOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixDarkenOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixDarkenOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixDifferenceOperation.cpp b/source/blender/compositor/operations/COM_MixDifferenceOperation.cpp
deleted file mode 100644
index 13494401c60..00000000000
--- a/source/blender/compositor/operations/COM_MixDifferenceOperation.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixDifferenceOperation.h"
-#include "BLI_math.h"
-
-MixDifferenceOperation::MixDifferenceOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixDifferenceOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
- output[0] = valuem * inputColor1[0] + value *fabsf(inputColor1[0] - inputColor2[0]);
- output[1] = valuem * inputColor1[1] + value *fabsf(inputColor1[1] - inputColor2[1]);
- output[2] = valuem * inputColor1[2] + value *fabsf(inputColor1[2] - inputColor2[2]);
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixDifferenceOperation.h b/source/blender/compositor/operations/COM_MixDifferenceOperation.h
deleted file mode 100644
index 7e4bf3c675c..00000000000
--- a/source/blender/compositor/operations/COM_MixDifferenceOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixDifferenceOperation_h
-#define _COM_MixDifferenceOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixDifferenceOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixDifferenceOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixDivideOperation.cpp b/source/blender/compositor/operations/COM_MixDivideOperation.cpp
deleted file mode 100644
index 3e0eb66565c..00000000000
--- a/source/blender/compositor/operations/COM_MixDivideOperation.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixDivideOperation.h"
-
-MixDivideOperation::MixDivideOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixDivideOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
-
- if (inputColor2[0] != 0.0f)
- output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0];
- else
- output[0] = 0.0f;
- if (inputColor2[1] != 0.0f)
- output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1];
- else
- output[1] = 0.0f;
- if (inputColor2[2] != 0.0f)
- output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2];
- else
- output[2] = 0.0f;
-
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixDivideOperation.h b/source/blender/compositor/operations/COM_MixDivideOperation.h
deleted file mode 100644
index f543265075b..00000000000
--- a/source/blender/compositor/operations/COM_MixDivideOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixDivideOperation_h
-#define _COM_MixDivideOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixDivideOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixDivideOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixDodgeOperation.cpp b/source/blender/compositor/operations/COM_MixDodgeOperation.cpp
deleted file mode 100644
index acb39f665ff..00000000000
--- a/source/blender/compositor/operations/COM_MixDodgeOperation.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixDodgeOperation.h"
-
-MixDodgeOperation::MixDodgeOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixDodgeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
- float tmp;
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
-
- if (inputColor1[0] != 0.0f) {
- tmp = 1.0f - value * inputColor2[0];
- if (tmp <= 0.0f)
- output[0] = 1.0f;
- else {
- tmp = inputColor1[0] / tmp;
- if (tmp > 1.0f)
- output[0] = 1.0f;
- else
- output[0] = tmp;
- }
- }
- else
- output[0] = 0.0f;
-
- if (inputColor1[1] != 0.0f) {
- tmp = 1.0f - value * inputColor2[1];
- if (tmp <= 0.0f)
- output[1] = 1.0f;
- else {
- tmp = inputColor1[1] / tmp;
- if (tmp > 1.0f)
- output[1] = 1.0f;
- else
- output[1] = tmp;
- }
- }
- else
- output[1] = 0.0f;
-
- if (inputColor1[2] != 0.0f) {
- tmp = 1.0f - value * inputColor2[2];
- if (tmp <= 0.0f)
- output[2] = 1.0f;
- else {
- tmp = inputColor1[2] / tmp;
- if (tmp > 1.0f)
- output[2] = 1.0f;
- else
- output[2] = tmp;
- }
- }
- else
- output[2] = 0.0f;
-
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixDodgeOperation.h b/source/blender/compositor/operations/COM_MixDodgeOperation.h
deleted file mode 100644
index 9a285c675c5..00000000000
--- a/source/blender/compositor/operations/COM_MixDodgeOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixDodgeOperation_h
-#define _COM_MixDodgeOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixDodgeOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixDodgeOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixGlareOperation.cpp b/source/blender/compositor/operations/COM_MixGlareOperation.cpp
deleted file mode 100644
index 1c6555206da..00000000000
--- a/source/blender/compositor/operations/COM_MixGlareOperation.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011, Glareer 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixGlareOperation.h"
-
-MixGlareOperation::MixGlareOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixGlareOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
- float value;
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
- value = inputValue[0];
- float mf = 2.f - 2.f * fabsf(value - 0.5f);
-
- if (inputColor1[0] < 0.0f) inputColor1[0] = 0.0f;
- if (inputColor1[1] < 0.0f) inputColor1[1] = 0.0f;
- if (inputColor1[2] < 0.0f) inputColor1[2] = 0.0f;
-
- output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f);
- output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f);
- output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f);
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
diff --git a/source/blender/compositor/operations/COM_MixGlareOperation.h b/source/blender/compositor/operations/COM_MixGlareOperation.h
deleted file mode 100644
index 99d478e347d..00000000000
--- a/source/blender/compositor/operations/COM_MixGlareOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, Glareer 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixGlareOperation_h
-#define _COM_MixGlareOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixGlareOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixGlareOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixHueOperation.cpp b/source/blender/compositor/operations/COM_MixHueOperation.cpp
deleted file mode 100644
index 64c88592b93..00000000000
--- a/source/blender/compositor/operations/COM_MixHueOperation.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixHueOperation.h"
-
-extern "C" {
- #include "BLI_math.h"
-}
-
-MixHueOperation::MixHueOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixHueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
-
- float colH, colS, colV;
- rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
- if (colS != 0.0f) {
- float rH, rS, rV;
- float tmpr, tmpg, tmpb;
- rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
- hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
- output[0] = valuem * (inputColor1[0]) + value * tmpr;
- output[1] = valuem * (inputColor1[1]) + value * tmpg;
- output[2] = valuem * (inputColor1[2]) + value * tmpb;
- }
- else {
- copy_v3_v3(output, inputColor1);
- }
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
diff --git a/source/blender/compositor/operations/COM_MixHueOperation.h b/source/blender/compositor/operations/COM_MixHueOperation.h
deleted file mode 100644
index d9864bbe3dc..00000000000
--- a/source/blender/compositor/operations/COM_MixHueOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixHueOperation_h
-#define _COM_MixHueOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixHueOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixHueOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixLightenOperation.cpp b/source/blender/compositor/operations/COM_MixLightenOperation.cpp
deleted file mode 100644
index a468fb39442..00000000000
--- a/source/blender/compositor/operations/COM_MixLightenOperation.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixLightenOperation.h"
-
-MixLightenOperation::MixLightenOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixLightenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float tmp;
- tmp = value * inputColor2[0];
- if (tmp > inputColor1[0]) output[0] = tmp;
- else output[0] = inputColor1[0];
- tmp = value * inputColor2[1];
- if (tmp > inputColor1[1]) output[1] = tmp;
- else output[1] = inputColor1[1];
- tmp = value * inputColor2[2];
- if (tmp > inputColor1[2]) output[2] = tmp;
- else output[2] = inputColor1[2];
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixLightenOperation.h b/source/blender/compositor/operations/COM_MixLightenOperation.h
deleted file mode 100644
index 5f08a067e11..00000000000
--- a/source/blender/compositor/operations/COM_MixLightenOperation.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixLightenOperation_h
-#define _COM_MixLightenOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixLightenOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixLightenOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixLinearLightOperation.cpp b/source/blender/compositor/operations/COM_MixLinearLightOperation.cpp
deleted file mode 100644
index e1b5e040f0f..00000000000
--- a/source/blender/compositor/operations/COM_MixLinearLightOperation.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixLinearLightOperation.h"
-
-MixLinearLightOperation::MixLinearLightOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixLinearLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- if (inputColor2[0] > 0.5f)
- output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f));
- else
- output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f);
- if (inputColor2[1] > 0.5f)
- output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f));
- else
- output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f);
- if (inputColor2[2] > 0.5f)
- output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f));
- else
- output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f);
-
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
diff --git a/source/blender/compositor/operations/COM_MixLinearLightOperation.h b/source/blender/compositor/operations/COM_MixLinearLightOperation.h
deleted file mode 100644
index 35451a9f3db..00000000000
--- a/source/blender/compositor/operations/COM_MixLinearLightOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixLinearLightOperation_h
-#define _COM_MixLinearLightOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixLinearLightOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixLinearLightOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixMultiplyOperation.cpp b/source/blender/compositor/operations/COM_MixMultiplyOperation.cpp
deleted file mode 100644
index e53addb7041..00000000000
--- a/source/blender/compositor/operations/COM_MixMultiplyOperation.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixMultiplyOperation.h"
-
-MixMultiplyOperation::MixMultiplyOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixMultiplyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
- output[0] = inputColor1[0] * (valuem + value * inputColor2[0]);
- output[1] = inputColor1[1] * (valuem + value * inputColor2[1]);
- output[2] = inputColor1[2] * (valuem + value * inputColor2[2]);
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixMultiplyOperation.h b/source/blender/compositor/operations/COM_MixMultiplyOperation.h
deleted file mode 100644
index cdd56bd2f39..00000000000
--- a/source/blender/compositor/operations/COM_MixMultiplyOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixMultiplyOperation_h
-#define _COM_MixMultiplyOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixMultiplyOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixMultiplyOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp
new file mode 100644
index 00000000000..f094e93f147
--- /dev/null
+++ b/source/blender/compositor/operations/COM_MixOperation.cpp
@@ -0,0 +1,848 @@
+/*
+ * Copyright 2011, 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:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ */
+
+#include "COM_MixOperation.h"
+
+extern "C" {
+ #include "BLI_math.h"
+}
+
+/* ******** Mix Base Operation ******** */
+
+MixBaseOperation::MixBaseOperation() : NodeOperation()
+{
+ this->addInputSocket(COM_DT_VALUE);
+ this->addInputSocket(COM_DT_COLOR);
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+ this->m_inputValueOperation = NULL;
+ this->m_inputColor1Operation = NULL;
+ this->m_inputColor2Operation = NULL;
+ this->setUseValueAlphaMultiply(false);
+ this->setUseClamp(false);
+}
+
+void MixBaseOperation::initExecution()
+{
+ this->m_inputValueOperation = this->getInputSocketReader(0);
+ this->m_inputColor1Operation = this->getInputSocketReader(1);
+ this->m_inputColor2Operation = this->getInputSocketReader(2);
+}
+
+void MixBaseOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+ output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
+ output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
+ output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
+ output[3] = inputColor1[3];
+}
+
+void MixBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+ InputSocket *socket;
+ unsigned int tempPreferredResolution[2] = {0, 0};
+ unsigned int tempResolution[2];
+
+ socket = this->getInputSocket(1);
+ socket->determineResolution(tempResolution, tempPreferredResolution);
+ if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
+ this->setResolutionInputSocketIndex(1);
+ }
+ else {
+ socket = this->getInputSocket(2);
+ socket->determineResolution(tempResolution, tempPreferredResolution);
+ if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
+ this->setResolutionInputSocketIndex(2);
+ }
+ else {
+ this->setResolutionInputSocketIndex(0);
+ }
+ }
+ NodeOperation::determineResolution(resolution, preferredResolution);
+}
+
+void MixBaseOperation::deinitExecution()
+{
+ this->m_inputValueOperation = NULL;
+ this->m_inputColor1Operation = NULL;
+ this->m_inputColor2Operation = NULL;
+}
+
+/* ******** Mix Add Operation ******** */
+
+MixAddOperation::MixAddOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixAddOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ output[0] = inputColor1[0] + value * inputColor2[0];
+ output[1] = inputColor1[1] + value * inputColor2[1];
+ output[2] = inputColor1[2] + value * inputColor2[2];
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Blend Operation ******** */
+
+MixBlendOperation::MixBlendOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixBlendOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+ float value;
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+ value = inputValue[0];
+
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+ output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
+ output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
+ output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Burn Operation ******** */
+
+MixBurnOperation::MixBurnOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixBurnOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+ float tmp;
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+
+ tmp = valuem + value * inputColor2[0];
+ if (tmp <= 0.0f)
+ output[0] = 0.0f;
+ else {
+ tmp = 1.0f - (1.0f - inputColor1[0]) / tmp;
+ if (tmp < 0.0f)
+ output[0] = 0.0f;
+ else if (tmp > 1.0f)
+ output[0] = 1.0f;
+ else
+ output[0] = tmp;
+ }
+
+ tmp = valuem + value * inputColor2[1];
+ if (tmp <= 0.0f)
+ output[1] = 0.0f;
+ else {
+ tmp = 1.0f - (1.0f - inputColor1[1]) / tmp;
+ if (tmp < 0.0f)
+ output[1] = 0.0f;
+ else if (tmp > 1.0f)
+ output[1] = 1.0f;
+ else
+ output[1] = tmp;
+ }
+
+ tmp = valuem + value * inputColor2[2];
+ if (tmp <= 0.0f)
+ output[2] = 0.0f;
+ else {
+ tmp = 1.0f - (1.0f - inputColor1[2]) / tmp;
+ if (tmp < 0.0f)
+ output[2] = 0.0f;
+ else if (tmp > 1.0f)
+ output[2] = 1.0f;
+ else
+ output[2] = tmp;
+ }
+
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Color Operation ******** */
+
+MixColorOperation::MixColorOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+
+ float colH, colS, colV;
+ rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
+ if (colS != 0.0f) {
+ float rH, rS, rV;
+ float tmpr, tmpg, tmpb;
+ rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
+ hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
+ output[0] = (valuem * inputColor1[0]) + (value * tmpr);
+ output[1] = (valuem * inputColor1[1]) + (value * tmpg);
+ output[2] = (valuem * inputColor1[2]) + (value * tmpb);
+ }
+ else {
+ copy_v3_v3(output, inputColor1);
+ }
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Darken Operation ******** */
+
+MixDarkenOperation::MixDarkenOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixDarkenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+ float tmp;
+ tmp = inputColor2[0] + ((1.0f - inputColor2[0]) * valuem);
+ if (tmp < inputColor1[0]) output[0] = tmp;
+ else output[0] = inputColor1[0];
+ tmp = inputColor2[1] + ((1.0f - inputColor2[1]) * valuem);
+ if (tmp < inputColor1[1]) output[1] = tmp;
+ else output[1] = inputColor1[1];
+ tmp = inputColor2[2] + ((1.0f - inputColor2[2]) * valuem);
+ if (tmp < inputColor1[2]) output[2] = tmp;
+ else output[2] = inputColor1[2];
+
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Difference Operation ******** */
+
+MixDifferenceOperation::MixDifferenceOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixDifferenceOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+ output[0] = valuem * inputColor1[0] + value *fabsf(inputColor1[0] - inputColor2[0]);
+ output[1] = valuem * inputColor1[1] + value *fabsf(inputColor1[1] - inputColor2[1]);
+ output[2] = valuem * inputColor1[2] + value *fabsf(inputColor1[2] - inputColor2[2]);
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Difference Operation ******** */
+
+MixDivideOperation::MixDivideOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixDivideOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+
+ if (inputColor2[0] != 0.0f)
+ output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0];
+ else
+ output[0] = 0.0f;
+ if (inputColor2[1] != 0.0f)
+ output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1];
+ else
+ output[1] = 0.0f;
+ if (inputColor2[2] != 0.0f)
+ output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2];
+ else
+ output[2] = 0.0f;
+
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Dodge Operation ******** */
+
+MixDodgeOperation::MixDodgeOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixDodgeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+ float tmp;
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+
+ if (inputColor1[0] != 0.0f) {
+ tmp = 1.0f - value * inputColor2[0];
+ if (tmp <= 0.0f)
+ output[0] = 1.0f;
+ else {
+ tmp = inputColor1[0] / tmp;
+ if (tmp > 1.0f)
+ output[0] = 1.0f;
+ else
+ output[0] = tmp;
+ }
+ }
+ else
+ output[0] = 0.0f;
+
+ if (inputColor1[1] != 0.0f) {
+ tmp = 1.0f - value * inputColor2[1];
+ if (tmp <= 0.0f)
+ output[1] = 1.0f;
+ else {
+ tmp = inputColor1[1] / tmp;
+ if (tmp > 1.0f)
+ output[1] = 1.0f;
+ else
+ output[1] = tmp;
+ }
+ }
+ else
+ output[1] = 0.0f;
+
+ if (inputColor1[2] != 0.0f) {
+ tmp = 1.0f - value * inputColor2[2];
+ if (tmp <= 0.0f)
+ output[2] = 1.0f;
+ else {
+ tmp = inputColor1[2] / tmp;
+ if (tmp > 1.0f)
+ output[2] = 1.0f;
+ else
+ output[2] = tmp;
+ }
+ }
+ else
+ output[2] = 0.0f;
+
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Glare Operation ******** */
+
+MixGlareOperation::MixGlareOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixGlareOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+ float value;
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+ value = inputValue[0];
+ float mf = 2.f - 2.f * fabsf(value - 0.5f);
+
+ if (inputColor1[0] < 0.0f) inputColor1[0] = 0.0f;
+ if (inputColor1[1] < 0.0f) inputColor1[1] = 0.0f;
+ if (inputColor1[2] < 0.0f) inputColor1[2] = 0.0f;
+
+ output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f);
+ output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f);
+ output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f);
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Hue Operation ******** */
+
+MixHueOperation::MixHueOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixHueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+
+ float colH, colS, colV;
+ rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
+ if (colS != 0.0f) {
+ float rH, rS, rV;
+ float tmpr, tmpg, tmpb;
+ rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
+ hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
+ output[0] = valuem * (inputColor1[0]) + value * tmpr;
+ output[1] = valuem * (inputColor1[1]) + value * tmpg;
+ output[2] = valuem * (inputColor1[2]) + value * tmpb;
+ }
+ else {
+ copy_v3_v3(output, inputColor1);
+ }
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Lighten Operation ******** */
+
+MixLightenOperation::MixLightenOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixLightenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float tmp;
+ tmp = value * inputColor2[0];
+ if (tmp > inputColor1[0]) output[0] = tmp;
+ else output[0] = inputColor1[0];
+ tmp = value * inputColor2[1];
+ if (tmp > inputColor1[1]) output[1] = tmp;
+ else output[1] = inputColor1[1];
+ tmp = value * inputColor2[2];
+ if (tmp > inputColor1[2]) output[2] = tmp;
+ else output[2] = inputColor1[2];
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Linear Light Operation ******** */
+
+MixLinearLightOperation::MixLinearLightOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixLinearLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ if (inputColor2[0] > 0.5f)
+ output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f));
+ else
+ output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f);
+ if (inputColor2[1] > 0.5f)
+ output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f));
+ else
+ output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f);
+ if (inputColor2[2] > 0.5f)
+ output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f));
+ else
+ output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f);
+
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Multiply Operation ******** */
+
+MixMultiplyOperation::MixMultiplyOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixMultiplyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+ output[0] = inputColor1[0] * (valuem + value * inputColor2[0]);
+ output[1] = inputColor1[1] * (valuem + value * inputColor2[1]);
+ output[2] = inputColor1[2] * (valuem + value * inputColor2[2]);
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Ovelray Operation ******** */
+
+MixOverlayOperation::MixOverlayOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixOverlayOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+
+ float valuem = 1.0f - value;
+
+ if (inputColor1[0] < 0.5f) {
+ output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]);
+ }
+ else {
+ output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
+ }
+ if (inputColor1[1] < 0.5f) {
+ output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]);
+ }
+ else {
+ output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
+ }
+ if (inputColor1[2] < 0.5f) {
+ output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]);
+ }
+ else {
+ output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
+ }
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Saturation Operation ******** */
+
+MixSaturationOperation::MixSaturationOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixSaturationOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+
+ float rH, rS, rV;
+ rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
+ if (rS != 0.0f) {
+ float colH, colS, colV;
+ rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
+ hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]);
+ }
+ else {
+ copy_v3_v3(output, inputColor1);
+ }
+
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Screen Operation ******** */
+
+MixScreenOperation::MixScreenOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixScreenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+
+ output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
+ output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
+ output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Soft Light Operation ******** */
+
+MixSoftLightOperation::MixSoftLightOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixSoftLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) \
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+ float scr, scg, scb;
+
+ /* first calculate non-fac based Screen mix */
+ scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]);
+ scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]);
+ scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]);
+
+ output[0] = valuem * (inputColor1[0]) + value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) + (inputColor1[0] * scr));
+ output[1] = valuem * (inputColor1[1]) + value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) + (inputColor1[1] * scg));
+ output[2] = valuem * (inputColor1[2]) + value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) + (inputColor1[2] * scb));
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Subtract Operation ******** */
+
+MixSubtractOperation::MixSubtractOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixSubtractOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ output[0] = inputColor1[0] - value * (inputColor2[0]);
+ output[1] = inputColor1[1] - value * (inputColor2[1]);
+ output[2] = inputColor1[2] - value * (inputColor2[2]);
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
+
+/* ******** Mix Value Operation ******** */
+
+MixValueOperation::MixValueOperation() : MixBaseOperation()
+{
+ /* pass */
+}
+
+void MixValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float inputColor1[4];
+ float inputColor2[4];
+ float inputValue[4];
+
+ this->m_inputValueOperation->read(inputValue, x, y, sampler);
+ this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
+ this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
+
+ float value = inputValue[0];
+ if (this->useValueAlphaMultiply()) {
+ value *= inputColor2[3];
+ }
+ float valuem = 1.0f - value;
+
+ float rH, rS, rV;
+ float colH, colS, colV;
+ rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
+ rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
+ hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]);
+ output[3] = inputColor1[3];
+
+ clampIfNeeded(output);
+}
diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h
new file mode 100644
index 00000000000..93dbe6f36a6
--- /dev/null
+++ b/source/blender/compositor/operations/COM_MixOperation.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2011, 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:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ */
+
+#ifndef _COM_MixBaseOperation_h
+#define _COM_MixBaseOperation_h
+#include "COM_NodeOperation.h"
+
+
+/**
+ * All this programs converts an input color to an output value.
+ * it assumes we are in sRGB color space.
+ */
+
+class MixBaseOperation : public NodeOperation {
+protected:
+ /**
+ * Prefetched reference to the inputProgram
+ */
+ SocketReader *m_inputValueOperation;
+ SocketReader *m_inputColor1Operation;
+ SocketReader *m_inputColor2Operation;
+ bool m_valueAlphaMultiply;
+ bool m_useClamp;
+
+ inline void clampIfNeeded(float color[4])
+ {
+ if (m_useClamp) {
+ CLAMP(color[0], 0.0f, 1.0f);
+ CLAMP(color[1], 0.0f, 1.0f);
+ CLAMP(color[2], 0.0f, 1.0f);
+ CLAMP(color[3], 0.0f, 1.0f);
+ }
+ }
+
+public:
+ /**
+ * Default constructor
+ */
+ MixBaseOperation();
+
+ /**
+ * the inner loop of this program
+ */
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+ /**
+ * Initialize the execution
+ */
+ void initExecution();
+
+ /**
+ * Deinitialize the execution
+ */
+ void deinitExecution();
+
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
+
+ void setUseValueAlphaMultiply(const bool value) { this->m_valueAlphaMultiply = value; }
+ bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; }
+ void setUseClamp(bool value) { this->m_useClamp = value; }
+};
+
+class MixAddOperation : public MixBaseOperation {
+public:
+ MixAddOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixBlendOperation : public MixBaseOperation {
+public:
+ MixBlendOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixBurnOperation : public MixBaseOperation {
+public:
+ MixBurnOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixColorOperation : public MixBaseOperation {
+public:
+ MixColorOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixDarkenOperation : public MixBaseOperation {
+public:
+ MixDarkenOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixDifferenceOperation : public MixBaseOperation {
+public:
+ MixDifferenceOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixDivideOperation : public MixBaseOperation {
+public:
+ MixDivideOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixDodgeOperation : public MixBaseOperation {
+public:
+ MixDodgeOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixGlareOperation : public MixBaseOperation {
+public:
+ MixGlareOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixHueOperation : public MixBaseOperation {
+public:
+ MixHueOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixLightenOperation : public MixBaseOperation {
+public:
+ MixLightenOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixLinearLightOperation : public MixBaseOperation {
+public:
+ MixLinearLightOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixMultiplyOperation : public MixBaseOperation {
+public:
+ MixMultiplyOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixOverlayOperation : public MixBaseOperation {
+public:
+ MixOverlayOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixSaturationOperation : public MixBaseOperation {
+public:
+ MixSaturationOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixScreenOperation : public MixBaseOperation {
+public:
+ MixScreenOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixSoftLightOperation : public MixBaseOperation {
+public:
+ MixSoftLightOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixSubtractOperation : public MixBaseOperation {
+public:
+ MixSubtractOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class MixValueOperation : public MixBaseOperation {
+public:
+ MixValueOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_MixOverlayOperation.cpp b/source/blender/compositor/operations/COM_MixOverlayOperation.cpp
deleted file mode 100644
index d5e1c6d1167..00000000000
--- a/source/blender/compositor/operations/COM_MixOverlayOperation.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixOverlayOperation.h"
-
-MixOverlayOperation::MixOverlayOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixOverlayOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
-
- float valuem = 1.0f - value;
-
- if (inputColor1[0] < 0.5f) {
- output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]);
- }
- else {
- output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
- }
- if (inputColor1[1] < 0.5f) {
- output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]);
- }
- else {
- output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
- }
- if (inputColor1[2] < 0.5f) {
- output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]);
- }
- else {
- output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
- }
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixOverlayOperation.h b/source/blender/compositor/operations/COM_MixOverlayOperation.h
deleted file mode 100644
index 4f2c08ce95f..00000000000
--- a/source/blender/compositor/operations/COM_MixOverlayOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixOverlayOperation_h
-#define _COM_MixOverlayOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixOverlayOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixOverlayOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixSaturationOperation.cpp b/source/blender/compositor/operations/COM_MixSaturationOperation.cpp
deleted file mode 100644
index ca45a1c703a..00000000000
--- a/source/blender/compositor/operations/COM_MixSaturationOperation.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixSaturationOperation.h"
-
-extern "C" {
- #include "BLI_math.h"
-}
-
-MixSaturationOperation::MixSaturationOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixSaturationOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
-
- float rH, rS, rV;
- rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
- if (rS != 0.0f) {
- float colH, colS, colV;
- rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
- hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]);
- }
- else {
- copy_v3_v3(output, inputColor1);
- }
-
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
diff --git a/source/blender/compositor/operations/COM_MixSaturationOperation.h b/source/blender/compositor/operations/COM_MixSaturationOperation.h
deleted file mode 100644
index c690db38daf..00000000000
--- a/source/blender/compositor/operations/COM_MixSaturationOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixSaturationOperation_h
-#define _COM_MixSaturationOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixSaturationOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixSaturationOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixScreenOperation.cpp b/source/blender/compositor/operations/COM_MixScreenOperation.cpp
deleted file mode 100644
index 511768a49ad..00000000000
--- a/source/blender/compositor/operations/COM_MixScreenOperation.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixScreenOperation.h"
-
-MixScreenOperation::MixScreenOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixScreenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
-
- output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
- output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
- output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixScreenOperation.h b/source/blender/compositor/operations/COM_MixScreenOperation.h
deleted file mode 100644
index 5ba3cf769bb..00000000000
--- a/source/blender/compositor/operations/COM_MixScreenOperation.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixScreenOperation_h
-#define _COM_MixScreenOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixScreenOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixScreenOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixSoftLightOperation.cpp b/source/blender/compositor/operations/COM_MixSoftLightOperation.cpp
deleted file mode 100644
index 71d83ce54ea..00000000000
--- a/source/blender/compositor/operations/COM_MixSoftLightOperation.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixSoftLightOperation.h"
-
-MixSoftLightOperation::MixSoftLightOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixSoftLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) \
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
- float scr, scg, scb;
-
- /* first calculate non-fac based Screen mix */
- scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]);
- scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]);
- scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]);
-
- output[0] = valuem * (inputColor1[0]) + value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) + (inputColor1[0] * scr));
- output[1] = valuem * (inputColor1[1]) + value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) + (inputColor1[1] * scg));
- output[2] = valuem * (inputColor1[2]) + value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) + (inputColor1[2] * scb));
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixSoftLightOperation.h b/source/blender/compositor/operations/COM_MixSoftLightOperation.h
deleted file mode 100644
index 55f6a70791a..00000000000
--- a/source/blender/compositor/operations/COM_MixSoftLightOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixSoftLightOperation_h
-#define _COM_MixSoftLightOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixSoftLightOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixSoftLightOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixSubtractOperation.cpp b/source/blender/compositor/operations/COM_MixSubtractOperation.cpp
deleted file mode 100644
index e6efe0f62f3..00000000000
--- a/source/blender/compositor/operations/COM_MixSubtractOperation.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixSubtractOperation.h"
-
-MixSubtractOperation::MixSubtractOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixSubtractOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- output[0] = inputColor1[0] - value * (inputColor2[0]);
- output[1] = inputColor1[1] - value * (inputColor2[1]);
- output[2] = inputColor1[2] - value * (inputColor2[2]);
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
-
diff --git a/source/blender/compositor/operations/COM_MixSubtractOperation.h b/source/blender/compositor/operations/COM_MixSubtractOperation.h
deleted file mode 100644
index 046d8d4949b..00000000000
--- a/source/blender/compositor/operations/COM_MixSubtractOperation.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixSubtractOperation_h
-#define _COM_MixSubtractOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixSubtractOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixSubtractOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MixValueOperation.cpp b/source/blender/compositor/operations/COM_MixValueOperation.cpp
deleted file mode 100644
index 553041e39bf..00000000000
--- a/source/blender/compositor/operations/COM_MixValueOperation.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_MixValueOperation.h"
-
-extern "C" {
- #include "BLI_math.h"
-}
-
-MixValueOperation::MixValueOperation() : MixBaseOperation()
-{
- /* pass */
-}
-
-void MixValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float inputColor1[4];
- float inputColor2[4];
- float inputValue[4];
-
- this->m_inputValueOperation->read(inputValue, x, y, sampler);
- this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
- this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
-
- float value = inputValue[0];
- if (this->useValueAlphaMultiply()) {
- value *= inputColor2[3];
- }
- float valuem = 1.0f - value;
-
- float rH, rS, rV;
- float colH, colS, colV;
- rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
- rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
- hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]);
- output[3] = inputColor1[3];
-
- clampIfNeeded(output);
-}
diff --git a/source/blender/compositor/operations/COM_MixValueOperation.h b/source/blender/compositor/operations/COM_MixValueOperation.h
deleted file mode 100644
index 6c3f3ce8072..00000000000
--- a/source/blender/compositor/operations/COM_MixValueOperation.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_MixValueOperation_h
-#define _COM_MixValueOperation_h
-#include "COM_MixBaseOperation.h"
-
-
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class MixValueOperation : public MixBaseOperation {
-public:
- /**
- * Default constructor
- */
- MixValueOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-};
-#endif
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
index 1c9dd0f170e..e2a95b2e33b 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
@@ -27,16 +27,15 @@ extern "C" {
#include "IMB_imbuf_types.h"
}
-MultilayerBaseOperation::MultilayerBaseOperation(int pass) : BaseImageOperation()
+MultilayerBaseOperation::MultilayerBaseOperation(int passindex) : BaseImageOperation()
{
- this->m_passId = pass;
+ this->m_passId = passindex;
}
ImBuf *MultilayerBaseOperation::getImBuf()
{
- RenderPass *rpass;
- rpass = (RenderPass *)BLI_findlink(&this->m_renderlayer->passes, this->m_passId);
+ RenderPass *rpass = (RenderPass *)BLI_findlink(&this->m_renderlayer->passes, this->m_passId);
if (rpass) {
- this->m_imageUser->pass = this->m_passId;
+ this->m_imageUser->pass = m_passId;
BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser);
return BaseImageOperation::getImBuf();
}
@@ -47,7 +46,7 @@ void MultilayerColorOperation::executePixel(float output[4], float x, float y, P
{
int yi = y;
int xi = x;
- if (this->m_imageBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
zero_v4(output);
}
else {
@@ -66,7 +65,7 @@ void MultilayerColorOperation::executePixel(float output[4], float x, float y, P
}
else {
int offset = (yi * this->getWidth() + xi) * 3;
- copy_v3_v3(output, &this->m_imageBuffer[offset]);
+ copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
}
}
}
@@ -75,11 +74,11 @@ void MultilayerValueOperation::executePixel(float output[4], float x, float y, P
{
int yi = y;
int xi = x;
- if (this->m_imageBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
output[0] = 0.0f;
}
else {
- float result = this->m_imageBuffer[yi * this->getWidth() + xi];
+ float result = this->m_imageFloatBuffer[yi * this->getWidth() + xi];
output[0] = result;
}
}
@@ -88,11 +87,11 @@ void MultilayerVectorOperation::executePixel(float output[4], float x, float y,
{
int yi = y;
int xi = x;
- if (this->m_imageBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+ if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
output[0] = 0.0f;
}
else {
int offset = (yi * this->getWidth() + xi) * 3;
- copy_v3_v3(output, &this->m_imageBuffer[offset]);
+ copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
}
}
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
index 3c498e962b5..065bcc7da1e 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
@@ -37,13 +37,13 @@ public:
/**
* Constructor
*/
- MultilayerBaseOperation(int pass);
+ MultilayerBaseOperation(int passindex);
void setRenderLayer(RenderLayer *renderlayer) { this->m_renderlayer = renderlayer; }
};
class MultilayerColorOperation : public MultilayerBaseOperation {
public:
- MultilayerColorOperation(int pass) : MultilayerBaseOperation(pass) {
+ MultilayerColorOperation(int passindex) : MultilayerBaseOperation(passindex) {
this->addOutputSocket(COM_DT_COLOR);
}
void executePixel(float output[4], float x, float y, PixelSampler sampler);
@@ -51,7 +51,7 @@ public:
class MultilayerValueOperation : public MultilayerBaseOperation {
public:
- MultilayerValueOperation(int pass) : MultilayerBaseOperation(pass) {
+ MultilayerValueOperation(int passindex) : MultilayerBaseOperation(passindex) {
this->addOutputSocket(COM_DT_VALUE);
}
void executePixel(float output[4], float x, float y, PixelSampler sampler);
@@ -59,7 +59,7 @@ public:
class MultilayerVectorOperation : public MultilayerBaseOperation {
public:
- MultilayerVectorOperation(int pass) : MultilayerBaseOperation(pass) {
+ MultilayerVectorOperation(int passindex) : MultilayerBaseOperation(passindex) {
this->addOutputSocket(COM_DT_VECTOR);
}
void executePixel(float output[4], float x, float y, PixelSampler sampler);
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index 15e5ab947d4..a5be993f241 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -138,7 +138,7 @@ void OutputSingleLayerOperation::deinitExecution()
ibuf->mall |= IB_rectfloat;
ibuf->dither = this->m_rd->dither_intensity;
- IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, m_viewSettings, m_displaySettings,
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, m_viewSettings, m_displaySettings,
this->m_format);
BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format,
@@ -184,15 +184,21 @@ void OutputOpenExrMultiLayerOperation::add_layer(const char *name, DataType data
void OutputOpenExrMultiLayerOperation::initExecution()
{
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
- this->m_layers[i].imageInput = getInputSocketReader(i);
- this->m_layers[i].outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->m_layers[i].datatype);
+ SocketReader *reader = getInputSocketReader(i);
+ this->m_layers[i].imageInput = reader;
+ if (reader)
+ this->m_layers[i].outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->m_layers[i].datatype);
+ else
+ this->m_layers[i].outputBuffer = NULL;
}
}
void OutputOpenExrMultiLayerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
{
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
- write_buffer_rect(rect, this->m_tree, this->m_layers[i].imageInput, this->m_layers[i].outputBuffer, this->getWidth(), this->m_layers[i].datatype);
+ OutputOpenExrLayer &layer = this->m_layers[i];
+ if (layer.imageInput)
+ write_buffer_rect(rect, this->m_tree, layer.imageInput, layer.outputBuffer, this->getWidth(), layer.datatype);
}
}
@@ -210,6 +216,10 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
BLI_make_existing_file(filename);
for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
+ OutputOpenExrLayer &layer = this->m_layers[i];
+ if (!layer.imageInput)
+ continue; /* skip unconnected sockets */
+
char channelname[EXR_TOT_MAXNAME];
BLI_strncpy(channelname, this->m_layers[i].name, sizeof(channelname) - 2);
char *channelname_ext = channelname + strlen(channelname);
diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp
new file mode 100644
index 00000000000..51e803f696b
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2013, 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:
+ * Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackMaskOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+ #include "BKE_movieclip.h"
+ #include "BKE_node.h"
+ #include "BKE_tracking.h"
+}
+
+PlaneTrackCommonOperation::PlaneTrackCommonOperation() : NodeOperation()
+{
+ this->m_movieClip = NULL;
+ this->m_framenumber = 0;
+ this->m_trackingObjectName[0] = '\0';
+ this->m_planeTrackName[0] = '\0';
+}
+
+void PlaneTrackCommonOperation::initExecution()
+{
+ MovieTracking *tracking;
+ MovieTrackingObject *object;
+
+ memset(this->m_corners, 0, sizeof(this->m_corners));
+ memset(this->m_frameSpaceCorners, 0, sizeof(this->m_frameSpaceCorners));
+
+ if (!this->m_movieClip)
+ return;
+
+ tracking = &this->m_movieClip->tracking;
+
+ object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName);
+ if (object) {
+ MovieTrackingPlaneTrack *plane_track;
+
+ plane_track = BKE_tracking_plane_track_get_named(tracking, object, this->m_planeTrackName);
+
+ if (plane_track) {
+ MovieTrackingPlaneMarker *plane_marker;
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
+
+ plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+ memcpy(this->m_corners, plane_marker->corners, sizeof(this->m_corners));
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ this->m_frameSpaceCorners[i][0] = this->m_corners[i][0] * this->getWidth();
+ this->m_frameSpaceCorners[i][1] = this->m_corners[i][1] * this->getHeight();
+ }
+}
+
+void PlaneTrackCommonOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+ NodeOperation::determineResolution(resolution, preferredResolution);
+
+ resolution[0] = 0;
+ resolution[1] = 0;
+
+ if (this->m_movieClip) {
+ int width, height;
+ MovieClipUser user = {0};
+
+ BKE_movieclip_user_set_frame(&user, this->m_framenumber);
+ BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height);
+
+ resolution[0] = width;
+ resolution[1] = height;
+ }
+}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h
new file mode 100644
index 00000000000..705bdf4bd81
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h
@@ -0,0 +1,62 @@
+
+/*
+ * Copyright 2013, 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:
+ * Sergey Sharybin
+ */
+
+#ifndef _COM_PlaneTrackCommonOperation_h
+#define _COM_PlaneTrackCommonOperation_h
+
+#include <string.h>
+
+#include "COM_NodeOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackCommonOperation : public NodeOperation {
+protected:
+ MovieClip *m_movieClip;
+ int m_framenumber;
+ char m_trackingObjectName[64];
+ char m_planeTrackName[64];
+
+ float m_corners[4][2]; /* Corners coordinates in normalized space. */
+ float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
+
+ /**
+ * Determine the output resolution. The resolution is retrieved from the Renderer
+ */
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
+public:
+ PlaneTrackCommonOperation();
+
+ void setMovieClip(MovieClip *clip) {this->m_movieClip = clip;}
+ void setTrackingObject(char *object) { BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); }
+ void setPlaneTrackName(char *plane_track) { BLI_strncpy(this->m_planeTrackName, plane_track, sizeof(this->m_planeTrackName)); }
+ void setFramenumber(int framenumber) {this->m_framenumber = framenumber;}
+
+ void initExecution();
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp
new file mode 100644
index 00000000000..8aa1324d8e2
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013, 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:
+ * Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackMaskOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+ #include "BLI_jitter.h"
+
+ #include "BKE_movieclip.h"
+ #include "BKE_node.h"
+ #include "BKE_tracking.h"
+}
+
+PlaneTrackMaskOperation::PlaneTrackMaskOperation() : PlaneTrackCommonOperation()
+{
+ this->addOutputSocket(COM_DT_VALUE);
+
+ /* Currently hardcoded to 8 samples. */
+ this->m_osa = 8;
+}
+
+void PlaneTrackMaskOperation::initExecution()
+{
+ PlaneTrackCommonOperation::initExecution();
+
+ BLI_jitter_init(this->m_jitter[0], this->m_osa);
+}
+
+void PlaneTrackMaskOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float point[2];
+
+ int inside_counter = 0;
+ for (int sample = 0; sample < this->m_osa; sample++) {
+ point[0] = x + this->m_jitter[sample][0];
+ point[1] = y + this->m_jitter[sample][1];
+
+ if (isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) ||
+ isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3]))
+ {
+ inside_counter++;
+ }
+ }
+
+ output[0] = (float) inside_counter / this->m_osa;
+}
diff --git a/source/blender/compositor/operations/COM_SeparateChannelOperation.h b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h
index f964df5df02..db32f9830e0 100644
--- a/source/blender/compositor/operations/COM_SeparateChannelOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h
@@ -1,5 +1,6 @@
+
/*
- * Copyright 2011, Blender Foundation.
+ * Copyright 2013, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -15,28 +16,34 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
- * Monique Dewanchand
+ * Contributor:
+ * Sergey Sharybin
*/
-#ifndef _COM_SeparateChannelOperation_h_
-#define _COM_SeparateChannelOperation_h_
+#ifndef _COM_PlaneTrackMaskOperation_h
+#define _COM_PlaneTrackMaskOperation_h
+
+#include <string.h>
+
+#include "COM_PlaneTrackCommonOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
-#include "COM_NodeOperation.h"
+class PlaneTrackMaskOperation : public PlaneTrackCommonOperation {
+protected:
+ int m_osa;
+ float m_jitter[32][2];
-class SeparateChannelOperation : public NodeOperation {
-private:
- SocketReader *m_inputOperation;
- int m_channel;
public:
- SeparateChannelOperation();
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
-
+ PlaneTrackMaskOperation();
+
void initExecution();
- void deinitExecution();
-
- void setChannel(int channel) { this->m_channel = channel; }
+
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
};
#endif
diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
new file mode 100644
index 00000000000..df487a766f3
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2013, 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:
+ * Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackWarpImageOperation.h"
+#include "COM_ReadBufferOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+ #include "BLI_jitter.h"
+
+ #include "BKE_movieclip.h"
+ #include "BKE_node.h"
+ #include "BKE_tracking.h"
+}
+
+BLI_INLINE bool isPointInsideQuad(const float x, const float y, const float corners[4][2])
+{
+ float point[2];
+
+ point[0] = x;
+ point[1] = y;
+
+ return isect_point_tri_v2(point, corners[0], corners[1], corners[2]) ||
+ isect_point_tri_v2(point, corners[0], corners[2], corners[3]);
+}
+
+BLI_INLINE bool resolveUV(const float x, const float y, const float corners[4][2], float uv[2])
+{
+ float point[2];
+ bool inside;
+
+ inside = isPointInsideQuad(x, y, corners);
+
+ point[0] = x;
+ point[1] = y;
+
+ /* Use reverse bilinear to get UV coordinates within original frame */
+ resolve_quad_uv(uv, point, corners[0], corners[1], corners[2], corners[3]);
+
+ return inside;
+}
+
+BLI_INLINE void resolveUVAndDxDy(const float x, const float y, const float corners[4][2],
+ float *u_r, float *v_r, float *dx_r, float *dy_r)
+{
+ float inputUV[2];
+ float uv_a[2], uv_b[2];
+
+ float dx, dy;
+ float uv_l, uv_r;
+ float uv_u, uv_d;
+
+ bool ok1, ok2;
+
+ resolveUV(x, y, corners, inputUV);
+
+ /* adaptive sampling, red (U) channel */
+ ok1 = resolveUV(x - 1, y, corners, uv_a);
+ ok2 = resolveUV(x + 1, y, corners, uv_b);
+ uv_l = ok1 ? fabsf(inputUV[0] - uv_a[0]) : 0.0f;
+ uv_r = ok2 ? fabsf(inputUV[0] - uv_b[0]) : 0.0f;
+
+ dx = 0.5f * (uv_l + uv_r);
+
+ /* adaptive sampling, green (V) channel */
+ ok1 = resolveUV(x, y - 1, corners, uv_a);
+ ok2 = resolveUV(x, y + 1, corners, uv_b);
+ uv_u = ok1 ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
+ uv_d = ok2 ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
+
+ dy = 0.5f * (uv_u + uv_d);
+
+ *dx_r = dx;
+ *dy_r = dy;
+
+ *u_r = inputUV[0];
+ *v_r = inputUV[1];
+}
+
+PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonOperation()
+{
+ this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
+ this->addOutputSocket(COM_DT_COLOR);
+ this->m_pixelReader = NULL;
+ this->setComplex(true);
+
+ /* Currently hardcoded to 8 samples. */
+ this->m_osa = 8;
+}
+
+void PlaneTrackWarpImageOperation::initExecution()
+{
+ PlaneTrackCommonOperation::initExecution();
+
+ this->m_pixelReader = this->getInputSocketReader(0);
+
+ BLI_jitter_init(this->m_jitter[0], this->m_osa);
+}
+
+void PlaneTrackWarpImageOperation::deinitExecution()
+{
+ this->m_pixelReader = NULL;
+}
+
+void PlaneTrackWarpImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float color_accum[4];
+
+ zero_v4(color_accum);
+ for (int sample = 0; sample < this->m_osa; sample++) {
+ float current_x = x + this->m_jitter[sample][0],
+ current_y = y + this->m_jitter[sample][1];
+ if (isPointInsideQuad(current_x, current_y, this->m_frameSpaceCorners)) {
+ float current_color[4];
+ float u, v, dx, dy;
+
+ resolveUVAndDxDy(current_x, current_y, this->m_frameSpaceCorners, &u, &v, &dx, &dy);
+
+ u *= this->m_pixelReader->getWidth();
+ v *= this->m_pixelReader->getHeight();
+
+ this->m_pixelReader->read(current_color, u, v, dx, dy, COM_PS_NEAREST);
+ add_v4_v4(color_accum, current_color);
+ }
+ }
+
+ mul_v4_v4fl(output, color_accum, 1.0f / this->m_osa);
+}
+
+bool PlaneTrackWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ float frame_space_corners[4][2];
+
+ for (int i = 0; i < 4; i++) {
+ frame_space_corners[i][0] = this->m_corners[i][0] * this->getWidth();
+ frame_space_corners[i][1] = this->m_corners[i][1] * this->getHeight();
+ }
+
+ float UVs[4][2];
+
+ /* TODO(sergey): figure out proper way to do this. */
+ resolveUV(input->xmin - 2, input->ymin - 2, frame_space_corners, UVs[0]);
+ resolveUV(input->xmax + 2, input->ymin - 2, frame_space_corners, UVs[1]);
+ resolveUV(input->xmax + 2, input->ymax + 2, frame_space_corners, UVs[2]);
+ resolveUV(input->xmin - 2, input->ymax + 2, frame_space_corners, UVs[3]);
+
+ float min[2], max[2];
+ INIT_MINMAX2(min, max);
+ for (int i = 0; i < 4; i++) {
+ minmax_v2v2_v2(min, max, UVs[i]);
+ }
+
+ rcti newInput;
+
+ newInput.xmin = min[0] * readOperation->getWidth() - 1;
+ newInput.ymin = min[1] * readOperation->getHeight() - 1;
+ newInput.xmax = max[0] * readOperation->getWidth() + 1;
+ newInput.ymax = max[1] * readOperation->getHeight() + 1;
+
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
diff --git a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
index d0191f292d2..a92ff3f9ddf 100644
--- a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
@@ -1,5 +1,6 @@
+
/*
- * Copyright 2012, Blender Foundation.
+ * Copyright 2013, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -16,34 +17,37 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor:
- * Dalai Felinto
+ * Sergey Sharybin
*/
-#ifndef _COM_ConvertStraightToPremulOperation_h
-#define _COM_ConvertStraightToPremulOperation_h
-#include "COM_NodeOperation.h"
+#ifndef _COM_PlaneTrackWarpImageOperation_h
+#define _COM_PlaneTrackWarpImageOperation_h
+#include <string.h>
+
+#include "COM_PlaneTrackCommonOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackWarpImageOperation : public PlaneTrackCommonOperation {
+protected:
+ SocketReader *m_pixelReader;
+ int m_osa;
+ float m_jitter[32][2];
-/**
- * this program converts an input color to an output value.
- * it assumes we are in sRGB color space.
- */
-class ConvertStraightToPremulOperation : public NodeOperation {
-private:
- SocketReader *m_inputColor;
public:
- /**
- * Default constructor
- */
- ConvertStraightToPremulOperation();
-
- /**
- * the inner loop of this program
- */
- void executePixel(float output[4], float x, float y, PixelSampler sampler);
+ PlaneTrackWarpImageOperation();
void initExecution();
void deinitExecution();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+ bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
};
+
#endif
diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp
index 5cc02a1ed65..e8b900b9a85 100644
--- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp
@@ -55,11 +55,11 @@ void ProjectorLensDistortionOperation::executePixel(float output[4], int x, int
const float v = (y + 0.5f) / height;
const float u = (x + 0.5f) / width;
MemoryBuffer *inputBuffer = (MemoryBuffer *)data;
- inputBuffer->readCubic(inputValue, (u * width + this->m_kr2) - 0.5f, v * height - 0.5f);
+ inputBuffer->readBilinear(inputValue, (u * width + this->m_kr2) - 0.5f, v * height - 0.5f);
output[0] = inputValue[0];
inputBuffer->read(inputValue, x, y);
output[1] = inputValue[1];
- inputBuffer->readCubic(inputValue, (u * width - this->m_kr2) - 0.5f, v * height - 0.5f);
+ inputBuffer->readBilinear(inputValue, (u * width - this->m_kr2) - 0.5f, v * height - 0.5f);
output[2] = inputValue[2];
output[3] = 1.0f;
}
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
index 03d41edda64..3aeef6bf409 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
@@ -27,6 +27,7 @@
ReadBufferOperation::ReadBufferOperation() : NodeOperation()
{
this->addOutputSocket(COM_DT_COLOR);
+ this->m_single_value = false;
this->m_offset = 0;
this->m_buffer = NULL;
}
@@ -47,21 +48,48 @@ void ReadBufferOperation::determineResolution(unsigned int resolution[2], unsign
if (this->m_memoryProxy->getExecutor()) {
this->m_memoryProxy->getExecutor()->setResolution(resolution);
}
+
+ m_single_value = operation->isSingleValue();
}
}
void ReadBufferOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
- if (sampler == COM_PS_NEAREST) {
+ if (m_single_value) {
+ /* write buffer has a single value stored at (0,0) */
+ m_buffer->read(output, 0, 0);
+ }
+ else if (sampler == COM_PS_NEAREST) {
m_buffer->read(output, x, y);
}
else {
- m_buffer->readCubic(output, x, y);
+ m_buffer->readBilinear(output, x, y);
+ }
+}
+
+void ReadBufferOperation::executePixelExtend(float output[4], float x, float y, PixelSampler sampler,
+ MemoryBufferExtend extend_x, MemoryBufferExtend extend_y)
+{
+ if (m_single_value) {
+ /* write buffer has a single value stored at (0,0) */
+ m_buffer->read(output, 0, 0);
+ }
+ else if (sampler == COM_PS_NEAREST) {
+ m_buffer->read(output, x, y, extend_x, extend_y);
+ }
+ else {
+ m_buffer->readBilinear(output, x, y, extend_x, extend_y);
}
}
void ReadBufferOperation::executePixel(float output[4], float x, float y, float dx, float dy, PixelSampler sampler)
{
- m_buffer->readEWA(output, x, y, dx, dy, sampler);
+ if (m_single_value) {
+ /* write buffer has a single value stored at (0,0) */
+ m_buffer->read(output, 0, 0);
+ }
+ else {
+ m_buffer->readEWA(output, x, y, dx, dy, sampler);
+ }
}
bool ReadBufferOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h
index 7e3ac147ee3..7a67056eda6 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.h
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h
@@ -29,6 +29,7 @@
class ReadBufferOperation : public NodeOperation {
private:
MemoryProxy *m_memoryProxy;
+ bool m_single_value; /* single value stored in buffer, copied from associated write operation */
unsigned int m_offset;
MemoryBuffer *m_buffer;
public:
@@ -40,10 +41,12 @@ public:
void *initializeTileData(rcti *rect);
void executePixel(float output[4], float x, float y, PixelSampler sampler);
+ void executePixelExtend(float output[4], float x, float y, PixelSampler sampler,
+ MemoryBufferExtend extend_x, MemoryBufferExtend extend_y);
void executePixel(float output[4], float x, float y, float dx, float dy, PixelSampler sampler);
const bool isReadBufferOperation() const { return true; }
void setOffset(unsigned int offset) { this->m_offset = offset; }
- unsigned int getOffset() { return this->m_offset; }
+ unsigned int getOffset() const { return this->m_offset; }
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) { return memoryBuffers[this->m_offset]; }
void readResolutionFromWriteBuffer();
diff --git a/source/blender/compositor/operations/COM_RenderLayersAOOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersAOOperation.cpp
deleted file mode 100644
index bb165c2fe1c..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersAOOperation.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersAOOperation.h"
-
-RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
-
diff --git a/source/blender/compositor/operations/COM_RenderLayersAOOperation.h b/source/blender/compositor/operations/COM_RenderLayersAOOperation.h
deleted file mode 100644
index 71b0b885e81..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersAOOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersAOOperation_h
-#define _COM_RenderLayersAOOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersAOOperation : public RenderLayersBaseProg {
-public:
- RenderLayersAOOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.cpp b/source/blender/compositor/operations/COM_RenderLayersAlphaProg.cpp
deleted file mode 100644
index 74cb506d264..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersAlphaProg.h"
-
-RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
-{
- this->addOutputSocket(COM_DT_VALUE);
-}
-
-void RenderLayersAlphaProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- int ix = x;
- int iy = y;
- float *inputBuffer = this->getInputBuffer();
-
- if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
- output[0] = 0.0f;
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
- }
- else {
- unsigned int offset = (iy * this->getWidth() + ix) * 4;
- output[0] = inputBuffer[offset + 3];
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
- }
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
deleted file mode 100644
index b50dca33f3b..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersBaseProg.h"
-
-#include "BLI_listbase.h"
-#include "DNA_scene_types.h"
-
-extern "C" {
- #include "RE_pipeline.h"
- #include "RE_shader_ext.h"
- #include "RE_render_ext.h"
-}
-
-RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation()
-{
- this->m_renderpass = renderpass;
- this->setScene(NULL);
- this->m_inputBuffer = NULL;
- this->m_elementsize = elementsize;
- this->m_rd = NULL;
-}
-
-
-void RenderLayersBaseProg::initExecution()
-{
- Scene *scene = this->getScene();
- Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
- RenderResult *rr = NULL;
-
- if (re)
- rr = RE_AcquireResultRead(re);
-
- if (rr) {
- SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, getLayerId());
- if (srl) {
-
- RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
- if (rl && rl->rectf) {
- this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass);
-
- if (this->m_inputBuffer == NULL || this->m_renderpass == SCE_PASS_COMBINED) {
- this->m_inputBuffer = rl->rectf;
- }
- }
- }
- }
- if (re) {
- RE_ReleaseResult(re);
- re = NULL;
- }
-}
-
-void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
-{
- unsigned int offset;
- int ix, iy;
- int width = this->getWidth(), height = this->getHeight();
-
- switch (sampler) {
- case COM_PS_NEAREST:
- ix = x;
- iy = y;
- offset = (iy * width + ix) * this->m_elementsize;
-
- if (this->m_elementsize == 1)
- output[0] = this->m_inputBuffer[offset];
- else if (this->m_elementsize == 3)
- copy_v3_v3(output, &this->m_inputBuffer[offset]);
- else
- copy_v4_v4(output, &this->m_inputBuffer[offset]);
-
- break;
-
- case COM_PS_BILINEAR:
- BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
- break;
-
- case COM_PS_BICUBIC:
- BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
- break;
- }
-
- if (this->m_elementsize == 1) {
- output[1] = 0.0f;
- output[2] = 0.0f;
- output[3] = 0.0f;
- }
- else if (this->m_elementsize == 3) {
- output[3] = 1.0f;
- }
-}
-
-void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
-#if 0
- const RenderData *rd = this->m_rd;
-
- int dx = 0, dy = 0;
-
- if (rd->mode & R_BORDER && rd->mode & R_CROP) {
- /* see comment in executeRegion describing coordinate mapping,
- * here it simply goes other way around
- */
- int full_width = rd->xsch * rd->size / 100;
- int full_height = rd->ysch * rd->size / 100;
-
- dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f;
- dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f;
- }
-
- int ix = x - dx;
- int iy = y - dy;
-#else
- int ix = x;
- int iy = y;
-#endif
-
- if (this->m_inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
- zero_v4(output);
- }
- else {
- doInterpolation(output, ix, iy, sampler);
- }
-}
-
-void RenderLayersBaseProg::deinitExecution()
-{
- this->m_inputBuffer = NULL;
-}
-
-void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
-{
- Scene *sce = this->getScene();
- Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL;
- RenderResult *rr = NULL;
-
- resolution[0] = 0;
- resolution[1] = 0;
-
- if (re)
- rr = RE_AcquireResultRead(re);
-
- if (rr) {
- SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId());
- if (srl) {
- RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
- if (rl && rl->rectf) {
- resolution[0] = rl->rectx;
- resolution[1] = rl->recty;
- }
- }
- }
-
- if (re)
- RE_ReleaseResult(re);
-
-}
-
diff --git a/source/blender/compositor/operations/COM_RenderLayersColorOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersColorOperation.cpp
deleted file mode 100644
index 3083c37c2bb..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersColorOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersColorOperation.h"
-
-RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(SCE_PASS_RGBA, 4)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.cpp
deleted file mode 100644
index b056896994e..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersCyclesOperation.h"
-
-RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.h b/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.h
deleted file mode 100644
index baa53c7388b..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersCyclesOperation_h
-#define _COM_RenderLayersCyclesOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersCyclesOperation : public RenderLayersBaseProg {
-public:
- RenderLayersCyclesOperation(int pass);
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersDepthProg.cpp b/source/blender/compositor/operations/COM_RenderLayersDepthProg.cpp
deleted file mode 100644
index ae5fc3b2254..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersDepthProg.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersDepthProg.h"
-
-RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1)
-{
- this->addOutputSocket(COM_DT_VALUE);
-}
-
diff --git a/source/blender/compositor/operations/COM_RenderLayersDepthProg.h b/source/blender/compositor/operations/COM_RenderLayersDepthProg.h
deleted file mode 100644
index fdbe25c818e..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersDepthProg.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersDepthProg_h
-#define _COM_RenderLayersDepthProg_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersDepthProg : public RenderLayersBaseProg {
-public:
- RenderLayersDepthProg();
-
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.cpp
deleted file mode 100644
index 6baa25e5600..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersDiffuseOperation.h"
-
-RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.h b/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.h
deleted file mode 100644
index 8c20d6f497d..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersDiffuseOperation_h
-#define _COM_RenderLayersDiffuseOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersDiffuseOperation : public RenderLayersBaseProg {
-public:
- RenderLayersDiffuseOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersEmitOperation.cpp
deleted file mode 100644
index 1b03a4e169f..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersEmitOperation.h"
-
-RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.h b/source/blender/compositor/operations/COM_RenderLayersEmitOperation.h
deleted file mode 100644
index c003cb2f87b..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersEmitOperation_h
-#define _COM_RenderLayersEmitOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersEmitOperation : public RenderLayersBaseProg {
-public:
- RenderLayersEmitOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.cpp
deleted file mode 100644
index f4d6dc7353b..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersEnvironmentOperation.h"
-
-RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.h b/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.h
deleted file mode 100644
index b9310a1778b..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersEnvironmentOperation_h
-#define _COM_RenderLayersEnvironmentOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersEnvironmentOperation : public RenderLayersBaseProg {
-public:
- RenderLayersEnvironmentOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersImageProg.cpp b/source/blender/compositor/operations/COM_RenderLayersImageProg.cpp
deleted file mode 100644
index f21585844ff..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersImageProg.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersImageProg.h"
-
-RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersImageProg.h b/source/blender/compositor/operations/COM_RenderLayersImageProg.h
deleted file mode 100644
index 5fa74c8b21f..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersImageProg.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersColorProg_h
-#define _COM_RenderLayersColorProg_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-/// @todo rename to image operation
-class RenderLayersColorProg : public RenderLayersBaseProg {
-public:
- RenderLayersColorProg();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.cpp
deleted file mode 100644
index 4258cb94a26..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersIndirectOperation.h"
-
-RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.h b/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.h
deleted file mode 100644
index d64207a4355..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersIndirectOperation_h
-#define _COM_RenderLayersIndirectOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersIndirectOperation : public RenderLayersBaseProg {
-public:
- RenderLayersIndirectOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.cpp
deleted file mode 100644
index aab7e0089e4..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersMaterialIndexOperation.h"
-
-RenderLayersMaterialIndexOperation::RenderLayersMaterialIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXMA, 1)
-{
- this->addOutputSocket(COM_DT_VALUE);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.h b/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.h
deleted file mode 100644
index d06568f5a10..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersMaterialIndexOperation_h
-#define _COM_RenderLayersMaterialIndexOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersMaterialIndexOperation : public RenderLayersBaseProg {
-public:
- RenderLayersMaterialIndexOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersMistOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersMistOperation.cpp
deleted file mode 100644
index c64ddc6e9d8..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersMistOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersMistOperation.h"
-
-RenderLayersMistOperation::RenderLayersMistOperation() : RenderLayersBaseProg(SCE_PASS_MIST, 1)
-{
- this->addOutputSocket(COM_DT_VALUE);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersNormalOperation.cpp
deleted file mode 100644
index 9d8e7d6272c..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersNormalOperation.h"
-
-RenderLayersNormalOperation::RenderLayersNormalOperation() : RenderLayersBaseProg(SCE_PASS_NORMAL, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.h b/source/blender/compositor/operations/COM_RenderLayersNormalOperation.h
deleted file mode 100644
index 39b2040863a..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersNormalOperation_h
-#define _COM_RenderLayersNormalOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersNormalOperation : public RenderLayersBaseProg {
-public:
- RenderLayersNormalOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.cpp
deleted file mode 100644
index 430ea698263..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersObjectIndexOperation.h"
-
-RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXOB, 1)
-{
- this->addOutputSocket(COM_DT_VALUE);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.h b/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.h
deleted file mode 100644
index e8a1602cbfc..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersObjectIndexOperation_h
-#define _COM_RenderLayersObjectIndexOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersObjectIndexOperation : public RenderLayersBaseProg {
-public:
- RenderLayersObjectIndexOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
new file mode 100644
index 00000000000..ea6ad86d92c
--- /dev/null
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2011, 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:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ */
+
+#include "COM_RenderLayersProg.h"
+
+#include "BLI_listbase.h"
+#include "DNA_scene_types.h"
+
+extern "C" {
+ #include "RE_pipeline.h"
+ #include "RE_shader_ext.h"
+ #include "RE_render_ext.h"
+}
+
+/* ******** Render Layers Base Prog ******** */
+
+RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation()
+{
+ this->m_renderpass = renderpass;
+ this->setScene(NULL);
+ this->m_inputBuffer = NULL;
+ this->m_elementsize = elementsize;
+ this->m_rd = NULL;
+}
+
+
+void RenderLayersBaseProg::initExecution()
+{
+ Scene *scene = this->getScene();
+ Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
+ RenderResult *rr = NULL;
+
+ if (re)
+ rr = RE_AcquireResultRead(re);
+
+ if (rr) {
+ SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, getLayerId());
+ if (srl) {
+
+ RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
+ if (rl && rl->rectf) {
+ this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass);
+
+ if (this->m_inputBuffer == NULL || this->m_renderpass == SCE_PASS_COMBINED) {
+ this->m_inputBuffer = rl->rectf;
+ }
+ }
+ }
+ }
+ if (re) {
+ RE_ReleaseResult(re);
+ re = NULL;
+ }
+}
+
+void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
+{
+ unsigned int offset;
+ int ix, iy;
+ int width = this->getWidth(), height = this->getHeight();
+
+ switch (sampler) {
+ case COM_PS_NEAREST:
+ ix = x;
+ iy = y;
+ offset = (iy * width + ix) * this->m_elementsize;
+
+ if (this->m_elementsize == 1)
+ output[0] = this->m_inputBuffer[offset];
+ else if (this->m_elementsize == 3)
+ copy_v3_v3(output, &this->m_inputBuffer[offset]);
+ else
+ copy_v4_v4(output, &this->m_inputBuffer[offset]);
+
+ break;
+
+ case COM_PS_BILINEAR:
+ BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
+ break;
+
+ case COM_PS_BICUBIC:
+ BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y);
+ break;
+ }
+
+ if (this->m_elementsize == 1) {
+ output[1] = 0.0f;
+ output[2] = 0.0f;
+ output[3] = 0.0f;
+ }
+ else if (this->m_elementsize == 3) {
+ output[3] = 1.0f;
+ }
+}
+
+void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+#if 0
+ const RenderData *rd = this->m_rd;
+
+ int dx = 0, dy = 0;
+
+ if (rd->mode & R_BORDER && rd->mode & R_CROP) {
+ /* see comment in executeRegion describing coordinate mapping,
+ * here it simply goes other way around
+ */
+ int full_width = rd->xsch * rd->size / 100;
+ int full_height = rd->ysch * rd->size / 100;
+
+ dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f;
+ dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f;
+ }
+
+ int ix = x - dx;
+ int iy = y - dy;
+#else
+ int ix = x;
+ int iy = y;
+#endif
+
+ if (this->m_inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
+ zero_v4(output);
+ }
+ else {
+ doInterpolation(output, ix, iy, sampler);
+ }
+}
+
+void RenderLayersBaseProg::deinitExecution()
+{
+ this->m_inputBuffer = NULL;
+}
+
+void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+ Scene *sce = this->getScene();
+ Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL;
+ RenderResult *rr = NULL;
+
+ resolution[0] = 0;
+ resolution[1] = 0;
+
+ if (re)
+ rr = RE_AcquireResultRead(re);
+
+ if (rr) {
+ SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId());
+ if (srl) {
+ RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
+ if (rl && rl->rectf) {
+ resolution[0] = rl->rectx;
+ resolution[1] = rl->recty;
+ }
+ }
+ }
+
+ if (re)
+ RE_ReleaseResult(re);
+
+}
+
+/* ******** Render Layers AO Operation ******** */
+
+RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Alpha Operation ******** */
+
+RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
+{
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+void RenderLayersAlphaProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ int ix = x;
+ int iy = y;
+ float *inputBuffer = this->getInputBuffer();
+
+ if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
+ output[0] = 0.0f;
+ output[1] = 0.0f;
+ output[2] = 0.0f;
+ output[3] = 0.0f;
+ }
+ else {
+ unsigned int offset = (iy * this->getWidth() + ix) * 4;
+ output[0] = inputBuffer[offset + 3];
+ output[1] = 0.0f;
+ output[2] = 0.0f;
+ output[3] = 0.0f;
+ }
+}
+
+/* ******** Render Layers Color Operation ******** */
+
+RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(SCE_PASS_RGBA, 4)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Cycles Operation ******** */
+
+RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Depth Operation ******** */
+
+RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1)
+{
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+void RenderLayersDepthProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ int ix = x;
+ int iy = y;
+ float *inputBuffer = this->getInputBuffer();
+
+ if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
+ output[0] = 0.0f;
+ output[1] = 0.0f;
+ output[2] = 0.0f;
+ output[3] = 0.0f;
+ }
+ else {
+ unsigned int offset = (iy * this->getWidth() + ix);
+ output[0] = inputBuffer[offset];
+ output[1] = 0.0f;
+ output[2] = 0.0f;
+ output[3] = 0.0f;
+ }
+}
+
+/* ******** Render Layers Diffuse Operation ******** */
+
+RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Emit Operation ******** */
+
+RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Environment Operation ******** */
+
+RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Image Operation ******** */
+
+RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Indirect Operation ******** */
+
+RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Material Index Operation ******** */
+
+RenderLayersMaterialIndexOperation::RenderLayersMaterialIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXMA, 1)
+{
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+/* ******** Render Layers Mist Operation ******** */
+
+RenderLayersMistOperation::RenderLayersMistOperation() : RenderLayersBaseProg(SCE_PASS_MIST, 1)
+{
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+/* ******** Render Layers Normal Operation ******** */
+
+RenderLayersNormalOperation::RenderLayersNormalOperation() : RenderLayersBaseProg(SCE_PASS_NORMAL, 3)
+{
+ this->addOutputSocket(COM_DT_VECTOR);
+}
+
+/* ******** Render Layers Object Index Operation ******** */
+
+RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXOB, 1)
+{
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+/* ******** Render Layers Reflection Operation ******** */
+
+RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Refraction Operation ******** */
+
+RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Shadow Operation ******** */
+
+RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Specular Operation ******** */
+
+RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers Speed Operation ******** */
+
+RenderLayersSpeedOperation::RenderLayersSpeedOperation() : RenderLayersBaseProg(SCE_PASS_VECTOR, 4)
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+/* ******** Render Layers UV Operation ******** */
+
+RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PASS_UV, 3)
+{
+ this->addOutputSocket(COM_DT_VECTOR);
+}
diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index 84d6c1ee188..04861174387 100644
--- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -102,4 +102,107 @@ public:
void executePixel(float output[4], float x, float y, PixelSampler sampler);
};
+class RenderLayersAOOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersAOOperation();
+};
+
+class RenderLayersAlphaProg : public RenderLayersBaseProg {
+public:
+ RenderLayersAlphaProg();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class RenderLayersColorOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersColorOperation();
+};
+
+class RenderLayersCyclesOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersCyclesOperation(int pass);
+};
+
+class RenderLayersDepthProg : public RenderLayersBaseProg {
+public:
+ RenderLayersDepthProg();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+class RenderLayersDiffuseOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersDiffuseOperation();
+};
+
+class RenderLayersEmitOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersEmitOperation();
+};
+
+class RenderLayersEnvironmentOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersEnvironmentOperation();
+};
+
+/// @todo rename to image operation
+class RenderLayersColorProg : public RenderLayersBaseProg {
+public:
+ RenderLayersColorProg();
+};
+
+class RenderLayersIndirectOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersIndirectOperation();
+};
+
+class RenderLayersMaterialIndexOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersMaterialIndexOperation();
+};
+
+class RenderLayersMistOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersMistOperation();
+};
+
+class RenderLayersNormalOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersNormalOperation();
+};
+
+class RenderLayersObjectIndexOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersObjectIndexOperation();
+};
+
+class RenderLayersReflectionOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersReflectionOperation();
+};
+
+class RenderLayersRefractionOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersRefractionOperation();
+};
+
+class RenderLayersShadowOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersShadowOperation();
+};
+
+class RenderLayersSpecularOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersSpecularOperation();
+};
+
+class RenderLayersSpeedOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersSpeedOperation();
+};
+
+class RenderLayersUVOperation : public RenderLayersBaseProg {
+public:
+ RenderLayersUVOperation();
+};
+
#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.cpp
deleted file mode 100644
index 1fbd599235b..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersReflectionOperation.h"
-
-RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.h b/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.h
deleted file mode 100644
index 3dc7148930b..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersReflectionOperation_h
-#define _COM_RenderLayersReflectionOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersReflectionOperation : public RenderLayersBaseProg {
-public:
- RenderLayersReflectionOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.cpp
deleted file mode 100644
index 2ec9be46059..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersRefractionOperation.h"
-
-RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.h b/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.h
deleted file mode 100644
index 02ac7aa14f4..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersRefractionOperation_h
-#define _COM_RenderLayersRefractionOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersRefractionOperation : public RenderLayersBaseProg {
-public:
- RenderLayersRefractionOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersShadowOperation.cpp
deleted file mode 100644
index 7582e010e2c..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersShadowOperation.h"
-
-RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.h b/source/blender/compositor/operations/COM_RenderLayersShadowOperation.h
deleted file mode 100644
index af35915c2ee..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersShadowOperation_h
-#define _COM_RenderLayersShadowOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersShadowOperation : public RenderLayersBaseProg {
-public:
- RenderLayersShadowOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.cpp
deleted file mode 100644
index 60c1636dcda..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersSpecularOperation.h"
-
-RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.h b/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.h
deleted file mode 100644
index fc7d77976a3..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersSpecularOperation_h
-#define _COM_RenderLayersSpecularOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersSpecularOperation : public RenderLayersBaseProg {
-public:
- RenderLayersSpecularOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.cpp
deleted file mode 100644
index 5a0662d13eb..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersSpeedOperation.h"
-
-RenderLayersSpeedOperation::RenderLayersSpeedOperation() : RenderLayersBaseProg(SCE_PASS_VECTOR, 4)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.h b/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.h
deleted file mode 100644
index d341aa43950..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersSpeedOperation_h
-#define _COM_RenderLayersSpeedOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersSpeedOperation : public RenderLayersBaseProg {
-public:
- RenderLayersSpeedOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_RenderLayersUVOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersUVOperation.cpp
deleted file mode 100644
index b966f98632c..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersUVOperation.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_RenderLayersUVOperation.h"
-
-RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PASS_UV, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
diff --git a/source/blender/compositor/operations/COM_RenderLayersUVOperation.h b/source/blender/compositor/operations/COM_RenderLayersUVOperation.h
deleted file mode 100644
index 3068372a66c..00000000000
--- a/source/blender/compositor/operations/COM_RenderLayersUVOperation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#ifndef _COM_RenderLayersUVOperation_h
-#define _COM_RenderLayersUVOperation_h
-
-#include "COM_RenderLayersBaseProg.h"
-
-class RenderLayersUVOperation : public RenderLayersBaseProg {
-public:
- RenderLayersUVOperation();
-};
-
-#endif
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
index fb996f2abaf..d1060224444 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
@@ -103,7 +103,7 @@ void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y,
d = 1.0f / (1.0f + sqrtf(t));
const float nx = (u * d + 0.5f) * width - 0.5f;
const float ny = (v * d + 0.5f) * height - 0.5f;
- buffer->readCubic(color, nx, ny);
+ buffer->readBilinear(color, nx, ny);
tc[0] += (1.0f - tz) * color[0], tc[1] += tz * color[1];
dr++, dg++;
}
@@ -121,7 +121,7 @@ void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y,
d = 1.0f / (1.0f + sqrtf(t));
const float nx = (u * d + 0.5f) * width - 0.5f;
const float ny = (v * d + 0.5f) * height - 0.5f;
- buffer->readCubic(color, nx, ny);
+ buffer->readBilinear(color, nx, ny);
tc[1] += (1.0f - tz) * color[1], tc[2] += tz * color[2];
dg++, db++;
}
diff --git a/source/blender/compositor/operations/COM_SeparateChannelOperation.cpp b/source/blender/compositor/operations/COM_SeparateChannelOperation.cpp
deleted file mode 100644
index 9fc266cce86..00000000000
--- a/source/blender/compositor/operations/COM_SeparateChannelOperation.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011, 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:
- * Jeroen Bakker
- * Monique Dewanchand
- */
-
-#include "COM_SeparateChannelOperation.h"
-
-SeparateChannelOperation::SeparateChannelOperation() : NodeOperation()
-{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_VALUE);
- this->m_inputOperation = NULL;
-}
-void SeparateChannelOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void SeparateChannelOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
-}
-
-
-void SeparateChannelOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
-{
- float input[4];
- this->m_inputOperation->read(input, x, y, sampler);
- output[0] = input[this->m_channel];
-}
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.h b/source/blender/compositor/operations/COM_SetColorOperation.h
index 7895c34620b..8377decdd7b 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.h
+++ b/source/blender/compositor/operations/COM_SetColorOperation.h
@@ -58,7 +58,7 @@ public:
void executePixel(float output[4], float x, float y, PixelSampler sampler);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- const bool isSetOperation() const { return true; }
+ bool isSetOperation() const { return true; }
};
#endif
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.h b/source/blender/compositor/operations/COM_SetValueOperation.h
index 3ddc667bc7e..b88b85d66f2 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.h
+++ b/source/blender/compositor/operations/COM_SetValueOperation.h
@@ -49,6 +49,6 @@ public:
void executePixel(float output[4], float x, float y, PixelSampler sampler);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- const bool isSetOperation() const { return true; }
+ bool isSetOperation() const { return true; }
};
#endif
diff --git a/source/blender/compositor/operations/COM_SetVectorOperation.h b/source/blender/compositor/operations/COM_SetVectorOperation.h
index e9d6a163e9f..d15da58e58e 100644
--- a/source/blender/compositor/operations/COM_SetVectorOperation.h
+++ b/source/blender/compositor/operations/COM_SetVectorOperation.h
@@ -57,7 +57,7 @@ public:
void executePixel(float output[4], float x, float y, PixelSampler sampler);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- const bool isSetOperation() const { return true; }
+ bool isSetOperation() const { return true; }
void setVector(float vector[3]) {
setX(vector[0]);
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.h b/source/blender/compositor/operations/COM_TrackPositionOperation.h
index b5499ab76b7..7a4ce9f9213 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.h
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.h
@@ -72,7 +72,7 @@ public:
void executePixel(float output[4], float x, float y, PixelSampler sampler);
- const bool isSetOperation() const { return true; }
+ bool isSetOperation() const { return true; }
};
#endif
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp
index e9f083178e4..468aec64a56 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp
@@ -173,7 +173,7 @@ void ViewerOperation::updateImage(rcti *rect)
{
IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0,
this->m_viewSettings, this->m_displaySettings,
- rect->xmin, rect->ymin, rect->xmax, rect->ymax, FALSE);
+ rect->xmin, rect->ymin, rect->xmax, rect->ymax, false);
this->updateDraw();
}
diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp
index 68c3e74a237..ea19952f60c 100644
--- a/source/blender/compositor/operations/COM_WrapOperation.cpp
+++ b/source/blender/compositor/operations/COM_WrapOperation.cpp
@@ -23,21 +23,9 @@
#include "COM_WrapOperation.h"
-WrapOperation::WrapOperation() : NodeOperation()
+WrapOperation::WrapOperation() : ReadBufferOperation()
{
- this->addInputSocket(COM_DT_COLOR);
- this->addOutputSocket(COM_DT_COLOR);
- this->setResolutionInputSocketIndex(0);
- this->m_inputOperation = NULL;
-}
-void WrapOperation::initExecution()
-{
- this->m_inputOperation = this->getInputSocketReader(0);
-}
-
-void WrapOperation::deinitExecution()
-{
- this->m_inputOperation = NULL;
+ this->m_wrappingType = CMP_NODE_WRAP_NONE;
}
inline float WrapOperation::getWrappedOriginalXPos(float x)
@@ -59,6 +47,7 @@ void WrapOperation::executePixel(float output[4], float x, float y, PixelSampler
float nx, ny;
nx = x;
ny = y;
+ MemoryBufferExtend extend_x = COM_MB_CLIP, extend_y = COM_MB_CLIP;
switch (m_wrappingType) {
case CMP_NODE_WRAP_NONE:
//Intentionally empty, originalXPos and originalYPos have been set before
@@ -66,20 +55,23 @@ void WrapOperation::executePixel(float output[4], float x, float y, PixelSampler
case CMP_NODE_WRAP_X:
// wrap only on the x-axis
nx = this->getWrappedOriginalXPos(x);
+ extend_x = COM_MB_REPEAT;
break;
case CMP_NODE_WRAP_Y:
// wrap only on the y-axis
ny = this->getWrappedOriginalYPos(y);
+ extend_y = COM_MB_REPEAT;
break;
case CMP_NODE_WRAP_XY:
// wrap on both
nx = this->getWrappedOriginalXPos(x);
ny = this->getWrappedOriginalYPos(y);
+ extend_x = COM_MB_REPEAT;
+ extend_y = COM_MB_REPEAT;
break;
}
- this->m_inputOperation->read(output, nx, ny, sampler);
-
+ executePixelExtend(output, nx, ny, sampler, extend_x, extend_y);
}
bool WrapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
@@ -110,7 +102,7 @@ bool WrapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOper
}
}
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+ return ReadBufferOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
void WrapOperation::setWrapping(int wrapping_type)
diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h
index b84d85e7b5d..ddd5fa8032d 100644
--- a/source/blender/compositor/operations/COM_WrapOperation.h
+++ b/source/blender/compositor/operations/COM_WrapOperation.h
@@ -23,20 +23,16 @@
#ifndef _COM_WrapOperation_h_
#define _COM_WrapOperation_h_
-#include "COM_NodeOperation.h"
+#include "COM_ReadBufferOperation.h"
-class WrapOperation : public NodeOperation {
+class WrapOperation : public ReadBufferOperation {
private:
- SocketReader *m_inputOperation;
int m_wrappingType;
public:
WrapOperation();
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
void executePixel(float output[4], float x, float y, PixelSampler sampler);
- void initExecution();
- void deinitExecution();
-
void setWrapping(int wrapping_type);
float getWrappedOriginalXPos(float x);
float getWrappedOriginalYPos(float y);
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
index 17c8f4d9fd1..cf462607936 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
@@ -75,7 +75,6 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber)
for (x = x1; x < x2; x++) {
this->m_input->read(&(buffer[offset4]), x, y, data);
offset4 += COM_NUMBER_OF_CHANNELS;
-
}
if (isBreaked()) {
breaked = true;
@@ -174,6 +173,21 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti *rect,
delete clKernelsToCleanUp;
}
+void WriteBufferOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+ NodeOperation::determineResolution(resolution, preferredResolution);
+ /* make sure there is at least one pixel stored in case the input is a single value */
+ m_single_value = false;
+ if (resolution[0] == 0) {
+ resolution[0] = 1;
+ m_single_value = true;
+ }
+ if (resolution[1] == 0) {
+ resolution[1] = 1;
+ m_single_value = true;
+ }
+}
+
void WriteBufferOperation::readResolutionFromInputSocket()
{
NodeOperation *inputOperation = this->getInputOperation(0);
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h
index d89444045d4..157543fcb72 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.h
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h
@@ -32,6 +32,7 @@
*/
class WriteBufferOperation : public NodeOperation {
MemoryProxy *m_memoryProxy;
+ bool m_single_value; /* single value stored in buffer */
NodeOperation *m_input;
public:
WriteBufferOperation();
@@ -40,11 +41,13 @@ public:
MemoryProxy *getMemoryProxy() { return this->m_memoryProxy; }
void executePixel(float output[4], float x, float y, PixelSampler sampler);
const bool isWriteBufferOperation() const { return true; }
+ bool isSingleValue() const { return m_single_value; }
void executeRegion(rcti *rect, unsigned int tileNumber);
void initExecution();
void deinitExecution();
void executeOpenCLRegion(OpenCLDevice *device, rcti *rect, unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer);
+ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
void readResolutionFromInputSocket();
inline NodeOperation *getInput() {
return m_input;
diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.h b/source/blender/compositor/operations/COM_ZCombineOperation.h
index 4545775f26f..eeeb29d330f 100644
--- a/source/blender/compositor/operations/COM_ZCombineOperation.h
+++ b/source/blender/compositor/operations/COM_ZCombineOperation.h
@@ -22,7 +22,7 @@
#ifndef _COM_ZCombineOperation_h
#define _COM_ZCombineOperation_h
-#include "COM_MixBaseOperation.h"
+#include "COM_MixOperation.h"
/**
diff --git a/source/blender/datatoc/datatoc.c b/source/blender/datatoc/datatoc.c
index 236d9af8ef1..4e49a9a7694 100644
--- a/source/blender/datatoc/datatoc.c
+++ b/source/blender/datatoc/datatoc.c
@@ -25,6 +25,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/datatoc/datatoc.c
+ * \ingroup datatoc
+ */
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 845ad72d7aa..142342997be 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -1828,7 +1828,7 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *typ
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(mb->flag, type);
+ return GET_ACF_FLAG_PTR(mb->flag2, type);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
@@ -2781,6 +2781,9 @@ static void ANIM_init_channel_typeinfo_data(void)
if (ACF_INIT) {
ACF_INIT = 0;
+ /* NOTE: need to keep the order of these synchronized with the definition of
+ * channel types (eAnim_ChannelType) in ED_anim_api.h
+ */
animchannelTypeInfo[type++] = NULL; /* None */
animchannelTypeInfo[type++] = NULL; /* AnimData */
animchannelTypeInfo[type++] = NULL; /* Special */
@@ -2808,8 +2811,8 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSMESH; /* Mesh Channel */
animchannelTypeInfo[type++] = &ACF_DSTEX; /* Texture Channel */
animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
- animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
+ animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 91003674524..09b6e7d2206 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1541,10 +1541,18 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data,
static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
size_t items = 0;
for (srl = sce->r.layers.first; srl; srl = srl->next) {
- FreestyleLineSet *lineset;
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->linestyle) {
+ lineset->linestyle->id.flag |= LIB_DOIT;
+ }
+ }
+ }
+
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
/* skip render layers without Freestyle enabled */
if (!(srl->layflag & SCE_LAY_FRS))
@@ -1555,6 +1563,13 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data
FreestyleLineStyle *linestyle = lineset->linestyle;
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
+
+ if ((linestyle == NULL) ||
+ !(linestyle->id.flag & LIB_DOIT))
+ {
+ continue;
+ }
+ linestyle->id.flag &= ~LIB_DOIT;
/* add scene-level animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
@@ -2533,13 +2548,13 @@ static size_t animdata_filter_remove_invalid(ListBase *anim_data)
static size_t animdata_filter_remove_duplis(ListBase *anim_data)
{
bAnimListElem *ale, *next;
- GHash *gh;
+ GSet *gs;
size_t items = 0;
/* build new hashtable to efficiently store and retrieve which entries have been
* encountered already while searching
*/
- gh = BLI_ghash_ptr_new("animdata_filter_duplis_remove gh");
+ gs = BLI_gset_ptr_new(__func__);
/* loop through items, removing them from the list if a similar item occurs already */
for (ale = anim_data->first; ale; ale = next) {
@@ -2549,9 +2564,8 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
* - just use ale->data for now, though it would be nicer to involve
* ale->type in combination too to capture corner cases (where same data performs differently)
*/
- if (BLI_ghash_haskey(gh, ale->data) == 0) {
+ if (BLI_gset_reinsert(gs, ale->data, NULL)) {
/* this entry is 'unique' and can be kept */
- BLI_ghash_insert(gh, ale->data, NULL);
items++;
}
else {
@@ -2561,7 +2575,7 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data)
}
/* free the hash... */
- BLI_ghash_free(gh, NULL, NULL);
+ BLI_gset_free(gs, NULL);
/* return the number of items still in the list */
return items;
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 21941c7ed62..d3e6d8f474f 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -132,7 +132,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
propname = RNA_property_ui_name(prop);
/* Array Index - only if applicable */
- if (RNA_property_array_length(&ptr, prop)) {
+ if (RNA_property_array_check(prop)) {
char c = RNA_property_array_item_char(prop, fcu->array_index);
/* we need to write the index to a temp buffer (in py syntax) */
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index df93da8b7c1..826e204d981 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -75,7 +75,8 @@ void free_anim_drivers_copybuf(void);
* for the given Animation Data block. This assumes that all the destinations are valid.
*
* - add: 0 - don't add anything if not found,
- * 1 - add new Driver FCurve,
+ * 1 - add new Driver FCurve (with keyframes for visual tweaking),
+ * 2 - add new Driver FCurve (with generator, for script backwards compatability)
* -1 - add new Driver FCurve without driver stuff (for pasting)
*/
FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add)
@@ -114,11 +115,38 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
/* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
if (add > 0) {
+ BezTriple *bezt;
+ size_t i;
+
/* add some new driver data */
fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
+ fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG;
- /* add simple generator modifier for driver so that there is some visible representation */
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
+ /* F-Modifier or Keyframes? */
+ // FIXME: replace these magic numbers with defines
+ if (add == 2) {
+ /* Python API Backwards compatability hack:
+ * Create FModifier so that old scripts won't break
+ * for now before 2.7 series -- (September 4, 2013)
+ */
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
+ }
+ else {
+ /* add 2 keyframes so that user has something to work with
+ * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
+ * which can be easily tweaked from there.
+ */
+ insert_vert_fcurve(fcu, 0.0f, 0.0f, INSERTKEY_FAST);
+ insert_vert_fcurve(fcu, 1.0f, 1.0f, INSERTKEY_FAST);
+
+ /* configure this curve to extrapolate */
+ for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) {
+ bezt->h1 = bezt->h2 = HD_VECT;
+ }
+
+ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+ calchandles_fcurve(fcu);
+ }
}
/* just add F-Curve to end of driver list */
@@ -166,8 +194,10 @@ short ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int ar
/* will only loop once unless the array index was -1 */
for (; array_index < array_index_max; array_index++) {
+ short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
+
/* create F-Curve with Driver */
- fcu = verify_driver_fcurve(id, rna_path, array_index, 1);
+ fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode);
if (fcu && fcu->driver) {
ChannelDriver *driver = fcu->driver;
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index decbc351cad..71717284d8e 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -396,7 +396,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
int filter;
/* when not in graph view, don't use handles */
SpaceIpo *sipo = (ac->spacetype == SPACE_IPO) ? (SpaceIpo *)ac->sl : NULL;
- const short use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : FALSE;
+ const bool use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : false;
/* filter animation data */
filter = ANIMFILTER_DATA_VISIBLE;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 63acc5a943c..6b9200afb75 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -61,6 +61,7 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_main.h"
+#include "BKE_idcode.h"
#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_context.h"
@@ -141,9 +142,18 @@ bAction *verify_adt_action(ID *id, short add)
/* init action if none available yet */
/* TODO: need some wizardry to handle NLA stuff correct */
if ((adt->action == NULL) && (add)) {
+ /* init action name from name of ID block */
char actname[sizeof(id->name) - 2];
BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
+
+ /* create action */
adt->action = add_empty_action(G.main, actname);
+
+ /* set ID-type from ID-block that this is going to be assigned to
+ * so that users can't accidentally break actions by assigning them
+ * to the wrong places
+ */
+ adt->action->idroot = GS(id->name);
}
/* return the action */
@@ -256,7 +266,7 @@ int insert_bezt_fcurve(FCurve *fcu, BezTriple *bezt, short flag)
dst->f1 = bezt->f1;
dst->f2 = bezt->f2;
dst->f3 = bezt->f3;
-
+
/* TODO: perform some other operations? */
}
}
@@ -508,19 +518,19 @@ static float setting_get_rna_value(PointerRNA *ptr, PropertyRNA *prop, int index
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
value = (float)RNA_property_boolean_get_index(ptr, prop, index);
else
value = (float)RNA_property_boolean_get(ptr, prop);
break;
case PROP_INT:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
value = (float)RNA_property_int_get_index(ptr, prop, index);
else
value = (float)RNA_property_int_get(ptr, prop);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(ptr, prop))
+ if (RNA_property_array_check(prop))
value = RNA_property_float_get_index(ptr, prop, index);
else
value = RNA_property_float_get(ptr, prop);
@@ -996,6 +1006,34 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
* The flag argument is used for special settings that alter the behavior of
* the keyframe deletion. These include the quick refresh options.
*/
+
+
+
+/**
+ * \note caller needs to run #BKE_nla_tweakedit_remap to get NLA relative frame.
+ * caller should also check #BKE_fcurve_is_protected before keying.
+ */
+static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
+{
+ bool found;
+ int i;
+
+ /* try to find index of beztriple to get rid of */
+ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
+ if (found) {
+ /* delete the key at the index (will sanity check + do recalc afterwards) */
+ delete_fcurve_key(fcu, i, 1);
+
+ /* Only delete curve too if it won't be doing anything anymore */
+ if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
+ ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
+
+ /* return success */
+ return true;
+ }
+ return false;
+}
+
short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag))
{
AnimData *adt = BKE_animdata_from_id(id);
@@ -1055,32 +1093,20 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
/* will only loop once unless the array index was -1 */
for (; array_index < array_index_max; array_index++) {
FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
- bool found;
- int i;
-
+
/* check if F-Curve exists and/or whether it can be edited */
if (fcu == NULL)
continue;
-
- if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
- if (G.debug & G_DEBUG)
- printf("WARNING: not deleting keyframe for locked F-Curve\n");
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(reports, RPT_WARNING,
+ "not deleting keyframe for locked F-Curve '%s' for %s '%s'",
+ fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2);
continue;
}
-
- /* try to find index of beztriple to get rid of */
- i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found);
- if (found) {
- /* delete the key at the index (will sanity check + do recalc afterwards) */
- delete_fcurve_key(fcu, i, 1);
-
- /* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
- ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
-
- /* return success */
- ret++;
- }
+
+ ret += delete_keyframe_fcurve(adt, fcu, cfra);
+
}
/* return success/failure */
@@ -1158,7 +1184,7 @@ static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const cha
if (fcu == NULL)
continue;
- if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
+ if (BKE_fcurve_is_protected(fcu)) {
if (G.debug & G_DEBUG)
printf("WARNING: not deleting keyframe for locked F-Curve\n");
continue;
@@ -1537,14 +1563,22 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
AnimData *adt = ob->adt;
bAction *act = adt->action;
FCurve *fcu, *fcn;
+ const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
for (fcu = act->curves.first; fcu; fcu = fcn) {
fcn = fcu->next;
-
+
+ if (BKE_fcurve_is_protected(fcu)) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "not deleting keyframe for locked F-Curve '%s', object '%s'",
+ fcu->rna_path, id->name + 2);
+ continue;
+ }
+
/* delete keyframes on current frame
* WARNING: this can delete the next F-Curve, hence the "fcn" copying
*/
- success += delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
+ success += delete_keyframe_fcurve(adt, fcu, cfra_unmap);
}
}
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 1ee2dc80a97..8745d571a28 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -182,16 +182,22 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
if (ob->pose) {
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
if (pchan) {
+ GHash *gh = ob->pose->chanhash;
+
+ /* remove the old hash entry, and replace with the new name */
+ if (gh) {
+ BLI_assert(BLI_ghash_haskey(gh, pchan->name));
+ BLI_ghash_remove(gh, pchan->name, NULL, NULL);
+ }
+
BLI_strncpy(pchan->name, newname, MAXBONENAME);
-
- if (ob->pose->chanhash) {
- GHash *gh = ob->pose->chanhash;
-
- /* remove the old hash entry, and replace with the new name */
- BLI_ghash_remove(gh, oldname, NULL, NULL);
+
+ if (gh) {
BLI_ghash_insert(gh, pchan->name, pchan);
}
}
+
+ BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true);
}
/* Update any object constraints to use the new bone name */
@@ -294,9 +300,13 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
/* since we renamed stuff... */
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
+ /* copied from #rna_Bone_update_renamed */
+ /* redraw view */
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ /* update animation channels */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, ob->data);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 22bd22c8561..0301db4b4cf 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -255,7 +255,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
bDeformGroup *dgroup;
bPoseChannel *pchan;
Mesh *mesh;
- Mat4 *bbone = NULL;
+ Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
float (*root)[3], (*tip)[3], (*verts)[3];
int *selected;
int numbones, vertsfilled = 0, i, j, segments = 0;
@@ -309,7 +309,8 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
if (bone->segments > 1) {
segments = bone->segments;
- bbone = b_bone_spline_setup(pchan, 1);
+ b_bone_spline_setup(pchan, 1, bbone_array);
+ bbone = bbone_array;
}
}
}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 4991ef63cf5..76cd12f12f8 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -488,7 +488,6 @@ void ED_armature_from_edit(Object *obedit)
/* don't change active selection, this messes up separate which uses
* editmode toggle and can separate active bone which is de-selected originally */
/* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
- arm->act_edbone = NULL;
arm->act_bone = newBone;
}
newBone->roll = 0.0f;
@@ -575,6 +574,7 @@ void ED_armature_edit_free(struct Object *ob)
}
MEM_freeN(arm->edbo);
arm->edbo = NULL;
+ arm->act_edbone = NULL;
}
}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 76068c122bf..16d7f9c9420 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -281,7 +281,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys)
sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea");
- sys->edgehash = BLI_edgehash_new();
+ sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface));
for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index e84008c3d15..31ff1e161e8 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -148,36 +148,6 @@ static short pose_has_protected_selected(Object *ob, short warn)
}
#endif
-/* only for real IK, not for auto-IK */
-static int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
-{
- bConstraint *con;
- Bone *bone;
-
- /* No need to check if constraint is active (has influence),
- * since all constraints with CONSTRAINT_IK_AUTO are active */
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = con->data;
- if (data->rootbone == 0 || data->rootbone > level) {
- if ((data->flag & CONSTRAINT_IK_AUTO) == 0)
- return 1;
- }
- }
- }
- for (bone = pchan->bone->childbase.first; bone; bone = bone->next) {
- pchan = BKE_pose_channel_find_name(ob->pose, bone->name);
- if (pchan && pose_channel_in_IK_chain(ob, pchan, level + 1))
- return 1;
- }
- return 0;
-}
-
-int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
-{
- return pose_channel_in_IK_chain(ob, pchan, 0);
-}
-
/* ********************************************** */
/* Motion Paths */
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index ec1662c7fa6..d0e1b15064a 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -602,7 +602,7 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
pose_slide_refresh(C, pso);
/* set cursor to indicate modal */
- WM_cursor_modal(win, BC_EW_SCROLLCURSOR);
+ WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR);
/* header print */
pose_slide_draw_status(pso);
@@ -624,7 +624,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
/* return to normal cursor and header status */
ED_area_headerprint(pso->sa, NULL);
- WM_cursor_restore(win);
+ WM_cursor_modal_restore(win);
/* insert keyframes as required... */
pose_slide_autoKeyframe(C, pso);
@@ -639,7 +639,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
/* return to normal cursor and header status */
ED_area_headerprint(pso->sa, NULL);
- WM_cursor_restore(win);
+ WM_cursor_modal_restore(win);
/* reset transforms back to original state */
pose_slide_reset(pso);
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index f66fb38a2a6..3a09f531d44 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -198,7 +198,7 @@ ReebGraph *newReebGraph(void)
rg = MEM_callocN(sizeof(ReebGraph), "reeb graph");
rg->totnodes = 0;
- rg->emap = BLI_edgehash_new();
+ rg->emap = BLI_edgehash_new(__func__);
rg->free_arc = REEB_freeArc;
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 4f34bd19b5b..0b449c4334d 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC_SYS
set(SRC
curve_ops.c
editcurve.c
+ editcurve_add.c
editfont.c
lorem.c
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index d197697e60b..da8f86580f6 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -33,6 +33,9 @@
#define __CURVE_INTERN_H__
/* internal exports only */
+struct ListBase;
+struct EditNurb;
+struct Object;
struct wmOperatorType;
/* lorem.c */
@@ -71,11 +74,13 @@ void FONT_OT_unlink(struct wmOperatorType *ot);
void FONT_OT_textbox_add(struct wmOperatorType *ot);
void FONT_OT_textbox_remove(struct wmOperatorType *ot);
+
/* editcurve.c */
void CURVE_OT_hide(struct wmOperatorType *ot);
void CURVE_OT_reveal(struct wmOperatorType *ot);
void CURVE_OT_separate(struct wmOperatorType *ot);
+void CURVE_OT_split(struct wmOperatorType *ot);
void CURVE_OT_duplicate(struct wmOperatorType *ot);
void CURVE_OT_delete(struct wmOperatorType *ot);
@@ -92,19 +97,6 @@ void CURVE_OT_smooth_weight(struct wmOperatorType *ot);
void CURVE_OT_smooth_radius(struct wmOperatorType *ot);
void CURVE_OT_smooth_tilt(struct wmOperatorType *ot);
-void CURVE_OT_primitive_bezier_curve_add(struct wmOperatorType *ot);
-void CURVE_OT_primitive_bezier_circle_add(struct wmOperatorType *ot);
-void CURVE_OT_primitive_nurbs_curve_add(struct wmOperatorType *ot);
-void CURVE_OT_primitive_nurbs_circle_add(struct wmOperatorType *ot);
-void CURVE_OT_primitive_nurbs_path_add(struct wmOperatorType *ot);
-
-void SURFACE_OT_primitive_nurbs_surface_curve_add(struct wmOperatorType *ot);
-void SURFACE_OT_primitive_nurbs_surface_circle_add(struct wmOperatorType *ot);
-void SURFACE_OT_primitive_nurbs_surface_surface_add(struct wmOperatorType *ot);
-void SURFACE_OT_primitive_nurbs_surface_cylinder_add(struct wmOperatorType *ot);
-void SURFACE_OT_primitive_nurbs_surface_sphere_add(struct wmOperatorType *ot);
-void SURFACE_OT_primitive_nurbs_surface_torus_add(struct wmOperatorType *ot);
-
void CURVE_OT_de_select_first(struct wmOperatorType *ot);
void CURVE_OT_de_select_last(struct wmOperatorType *ot);
void CURVE_OT_select_all(struct wmOperatorType *ot);
@@ -126,5 +118,24 @@ void CURVE_OT_vertex_add(struct wmOperatorType *ot);
void CURVE_OT_extrude(struct wmOperatorType *ot);
void CURVE_OT_cyclic_toggle(struct wmOperatorType *ot);
-#endif /* ED_UTIL_INTERN_H */
+/* helper functions */
+void ed_editnurb_translate_flag(struct ListBase *editnurb, short flag, const float vec[3]);
+bool ed_editnurb_extrude_flag(struct EditNurb *editnurb, short flag);
+bool ed_editnurb_spin(float viewmat[4][4], struct Object *obedit, const float axis[3], const float cent[3]);
+
+
+/* editcurve_add.c */
+void CURVE_OT_primitive_bezier_curve_add(struct wmOperatorType *ot);
+void CURVE_OT_primitive_bezier_circle_add(struct wmOperatorType *ot);
+void CURVE_OT_primitive_nurbs_curve_add(struct wmOperatorType *ot);
+void CURVE_OT_primitive_nurbs_circle_add(struct wmOperatorType *ot);
+void CURVE_OT_primitive_nurbs_path_add(struct wmOperatorType *ot);
+
+void SURFACE_OT_primitive_nurbs_surface_curve_add(struct wmOperatorType *ot);
+void SURFACE_OT_primitive_nurbs_surface_circle_add(struct wmOperatorType *ot);
+void SURFACE_OT_primitive_nurbs_surface_surface_add(struct wmOperatorType *ot);
+void SURFACE_OT_primitive_nurbs_surface_cylinder_add(struct wmOperatorType *ot);
+void SURFACE_OT_primitive_nurbs_surface_sphere_add(struct wmOperatorType *ot);
+void SURFACE_OT_primitive_nurbs_surface_torus_add(struct wmOperatorType *ot);
+#endif /* __CURVE_INTERN_H__ */
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 2452a5d1a4b..1cf194e02c4 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -87,6 +87,7 @@ void ED_operatortypes_curve(void)
WM_operatortype_append(CURVE_OT_reveal);
WM_operatortype_append(CURVE_OT_separate);
+ WM_operatortype_append(CURVE_OT_split);
WM_operatortype_append(CURVE_OT_duplicate);
WM_operatortype_append(CURVE_OT_delete);
@@ -244,6 +245,7 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", TRUE);
WM_keymap_add_item(keymap, "CURVE_OT_separate", PKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CURVE_OT_split", YKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_extrude_move", EKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CURVE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "CURVE_OT_make_segment", FKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 660f8098a38..2dc32f711b4 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -29,16 +29,6 @@
* \ingroup edcurve
*/
-#include <math.h>
-#include <string.h>
-
-#ifndef WIN32
-#include <unistd.h>
-#else
-#include <io.h>
-#endif
-#include <stdlib.h>
-
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -49,9 +39,7 @@
#include "BLI_blenlib.h"
#include "BLI_bitmap.h"
#include "BLI_math.h"
-#include "BLI_dynstr.h"
#include "BLI_rand.h"
-#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLF_translation.h"
@@ -62,7 +50,6 @@
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_key.h"
-#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_animsys.h"
@@ -106,16 +93,25 @@ typedef struct {
Nurb *orig_nu;
} CVKeyIndex;
-void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus);
-static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus);
+typedef enum eVisible_Types {
+ HIDDEN = true,
+ VISIBLE = false,
+} eVisible_Types;
-/* still need to eradicate a few :( */
-#define CALLOC_STRUCT_N(x, y, name) (x *)MEM_callocN((y) * sizeof(x), name)
+typedef enum eEndPoint_Types {
+ FIRST = true,
+ LAST = false,
+} eEndPoint_Types;
-static float nurbcircle[8][2] = {
- {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0},
- {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0}
-};
+typedef enum eCurveElem_Types {
+ CURVE_VERTEX = 0,
+ CURVE_SEGMENT,
+} eCurveElem_Types;
+
+void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
+static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus);
+static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
+static int curve_delete_selected(Object *obedit, const eCurveElem_Types type, const bool split);
ListBase *object_editcurve_get(Object *ob)
{
@@ -149,69 +145,59 @@ static Nurb *get_actNurb(Object *obedit)
/* ******************* SELECTION FUNCTIONS ********************* */
-#define HIDDEN 1
-#define VISIBLE 0
-
-#define FIRST 1
-#define LAST 0
-
/* returns 1 in case (de)selection was successful */
-static short select_beztriple(BezTriple *bezt, short selstatus, short flag, short hidden)
+static bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
{
- if (bezt) {
- if ((bezt->hide == 0) || (hidden == 1)) {
- if (selstatus == 1) { /* selects */
- bezt->f1 |= flag;
- bezt->f2 |= flag;
- bezt->f3 |= flag;
- return 1;
- }
- else { /* deselects */
- bezt->f1 &= ~flag;
- bezt->f2 &= ~flag;
- bezt->f3 &= ~flag;
- return 1;
- }
+ if ((bezt->hide == 0) || (hidden == HIDDEN)) {
+ if (selstatus == SELECT) { /* selects */
+ bezt->f1 |= flag;
+ bezt->f2 |= flag;
+ bezt->f3 |= flag;
+ return true;
+ }
+ else { /* deselects */
+ bezt->f1 &= ~flag;
+ bezt->f2 &= ~flag;
+ bezt->f3 &= ~flag;
+ return true;
}
}
- return 0;
+ return false;
}
/* returns 1 in case (de)selection was successful */
-static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden)
+static bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
{
- if (bp) {
- if ((bp->hide == 0) || (hidden == 1)) {
- if (selstatus == 1) {
- bp->f1 |= flag;
- return 1;
- }
- else {
- bp->f1 &= ~flag;
- return 1;
- }
+ if ((bp->hide == 0) || (hidden == 1)) {
+ if (selstatus == SELECT) {
+ bp->f1 |= flag;
+ return true;
+ }
+ else {
+ bp->f1 &= ~flag;
+ return true;
}
}
- return 0;
+ return false;
}
-static short swap_selection_beztriple(BezTriple *bezt)
+static bool swap_selection_beztriple(BezTriple *bezt)
{
if (bezt->f2 & SELECT)
- return select_beztriple(bezt, DESELECT, 1, VISIBLE);
+ return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
else
- return select_beztriple(bezt, SELECT, 1, VISIBLE);
+ return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
}
-static short swap_selection_bpoint(BPoint *bp)
+static bool swap_selection_bpoint(BPoint *bp)
{
if (bp->f1 & SELECT)
- return select_bpoint(bp, DESELECT, 1, VISIBLE);
+ return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
else
- return select_bpoint(bp, SELECT, 1, VISIBLE);
+ return select_bpoint(bp, SELECT, SELECT, VISIBLE);
}
int isNurbsel(Nurb *nu)
@@ -361,7 +347,7 @@ static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, void *cv)
static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, void *cv)
{
- return BLI_ghash_pop(editnurb->keyindex, cv, NULL);
+ return BLI_ghash_popkey(editnurb->keyindex, cv, NULL);
}
static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, BezTriple *bezt)
@@ -674,7 +660,7 @@ static GHash *dupli_keyIndexHash(GHash *keyindex)
GHash *gh;
GHashIterator *hashIter;
- gh = BLI_ghash_ptr_new("dupli_keyIndex gh");
+ gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_size(keyindex));
for (hashIter = BLI_ghashIterator_new(keyindex);
BLI_ghashIterator_done(hashIter) == false;
@@ -1463,6 +1449,49 @@ void CURVE_OT_separate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/******************** split operator ***********************/
+
+static int curve_split_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ ListBase newnurb = {NULL, NULL};
+
+ adduplicateflagNurb(obedit, &newnurb, SELECT, true);
+
+ if (newnurb.first != NULL) {
+ curve_delete_selected(obedit, CURVE_SEGMENT, true);
+ BLI_movelisttolist(editnurb, &newnurb);
+
+ if (ED_curve_updateAnimPaths(obedit->data))
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Cannot split current selection");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void CURVE_OT_split(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Split";
+ ot->idname = "CURVE_OT_split";
+ ot->description = "Split off selected points from connected unselected points";
+
+ /* api callbacks */
+ ot->exec = curve_split_exec;
+ ot->poll = ED_operator_editcurve;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ******************* FLAGS ********************* */
static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
@@ -1510,34 +1539,7 @@ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
return 0;
}
-static void setflagsNurb(ListBase *editnurb, short flag)
-{
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- int a;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- a = nu->pntsu;
- bezt = nu->bezt;
- while (a--) {
- bezt->f1 = bezt->f2 = bezt->f3 = flag;
- bezt++;
- }
- }
- else {
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- bp->f1 = flag;
- bp++;
- }
- }
- }
-}
-
-static void rotateflagNurb(ListBase *editnurb, short flag, float *cent, float rotmat[3][3])
+static void rotateflagNurb(ListBase *editnurb, short flag, const float cent[3], float rotmat[3][3])
{
/* all verts with (flag & 'flag') rotate */
Nurb *nu;
@@ -1561,7 +1563,7 @@ static void rotateflagNurb(ListBase *editnurb, short flag, float *cent, float ro
}
}
-static void translateflagNurb(ListBase *editnurb, short flag, const float vec[3])
+void ed_editnurb_translate_flag(ListBase *editnurb, short flag, const float vec[3])
{
/* all verts with ('flag' & flag) translate */
Nurb *nu;
@@ -1614,9 +1616,8 @@ static void weightflagNurb(ListBase *editnurb, short flag, float w)
}
}
-static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag)
+static int deleteflagNurb(Object *obedit, short flag)
{
- Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu, *next;
@@ -1744,18 +1745,16 @@ static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag)
nu = next;
}
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
-
return OPERATOR_FINISHED;
}
/* only for OB_SURF */
-static short extrudeflagNurb(EditNurb *editnurb, int flag)
+bool ed_editnurb_extrude_flag(EditNurb *editnurb, short flag)
{
Nurb *nu;
BPoint *bp, *bpn, *newbp;
- int ok = 0, a, u, v, len;
+ int a, u, v, len;
+ bool ok = false;
nu = editnurb->nurbs.first;
while (nu) {
@@ -1774,7 +1773,7 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag)
a--;
}
if (a == 0) {
- ok = 1;
+ ok = true;
newbp = (BPoint *)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1");
ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
bp = newbp + nu->pntsu;
@@ -1808,7 +1807,7 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag)
}
if (u == 0 || u == nu->pntsv - 1) { /* row in u-direction selected */
- ok = 1;
+ ok = true;
newbp = (BPoint *)MEM_mallocN(nu->pntsu * (nu->pntsv + 1) *
sizeof(BPoint), "extrudeNurb1");
if (u == 0) {
@@ -1836,7 +1835,7 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag)
BKE_nurb_knot_calc_v(nu);
}
else if (v == 0 || v == nu->pntsu - 1) { /* column in v-direction selected */
- ok = 1;
+ ok = true;
bpn = newbp = (BPoint *)MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), "extrudeNurb1");
bp = nu->bp;
@@ -1869,40 +1868,54 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag)
return ok;
}
-static void adduplicateflagNurb(Object *obedit, short flag)
+static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
+ const short flag, const bool split)
{
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu, *newnu;
+ Nurb *nu, *newnu, *startnu;
BezTriple *bezt, *bezt1;
BPoint *bp, *bp1;
Curve *cu = (Curve *)obedit->data;
- int a, b, starta, enda, newu, newv;
+ int a, b, starta, enda, diffa, newu, newv;
char *usel;
cu->lastsel = NULL;
nu = editnurb->last;
while (nu) {
+ startnu = NULL;
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
for (a = 0; a < nu->pntsu; a++) {
enda = -1;
starta = a;
while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) {
- select_beztriple(bezt, DESELECT, flag, HIDDEN);
+ if (!split) select_beztriple(bezt, DESELECT, flag, HIDDEN);
enda = a;
if (a >= nu->pntsu - 1) break;
a++;
bezt++;
}
if (enda >= starta) {
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN");
- memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(editnurb, newnu);
- set_actNurb(obedit, newnu);
- newnu->pntsu = enda - starta + 1;
- newnu->bezt = (BezTriple *)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN");
- memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple));
+ diffa = enda - starta + 1;
+
+ if (startnu != NULL && enda == nu->pntsu - 1) {
+ /* end point of cyclic spline selected, so merge end points with start points */
+ bezt1 = (BezTriple *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BezTriple), "adduplicateN");
+ memcpy(bezt1, &nu->bezt[starta], diffa * sizeof(BezTriple));
+ memcpy(&bezt1[diffa], startnu->bezt, startnu->pntsu * sizeof(BezTriple));
+
+ MEM_freeN(startnu->bezt);
+ startnu->bezt = bezt1;
+ startnu->pntsu += diffa;
+ newnu = startnu;
+ }
+ else {
+ newnu = ED_curve_nurbcpy(nu, diffa);
+ BLI_addtail(newnurb, newnu);
+ set_actNurb(obedit, newnu);
+ memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple));
+ }
b = newnu->pntsu;
bezt1 = newnu->bezt;
@@ -1914,6 +1927,7 @@ static void adduplicateflagNurb(Object *obedit, short flag)
if (nu->flagu & CU_NURB_CYCLIC) {
if (starta != 0 || enda != nu->pntsu - 1) {
newnu->flagu &= ~CU_NURB_CYCLIC;
+ if (starta == 0) startnu = newnu;
}
}
}
@@ -1926,20 +1940,32 @@ static void adduplicateflagNurb(Object *obedit, short flag)
enda = -1;
starta = a;
while (bp->f1 & flag) {
- select_bpoint(bp, DESELECT, flag, HIDDEN);
+ if (!split) select_bpoint(bp, DESELECT, flag, HIDDEN);
enda = a;
if (a >= nu->pntsu - 1) break;
a++;
bp++;
}
if (enda >= starta) {
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN3");
- memcpy(newnu, nu, sizeof(Nurb));
- set_actNurb(obedit, newnu);
- BLI_addtail(editnurb, newnu);
- newnu->pntsu = enda - starta + 1;
- newnu->bp = (BPoint *)MEM_mallocN((enda - starta + 1) * sizeof(BPoint), "adduplicateN4");
- memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint));
+ diffa = enda - starta + 1;
+
+ if (startnu != NULL && enda == nu->pntsu - 1) {
+ /* end point of cyclic spline selected, so merge end points with start points */
+ bp1 = (BPoint *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BPoint), "adduplicateN2");
+ memcpy(bp1, &nu->bp[starta], diffa * sizeof(BPoint));
+ memcpy(&bp1[diffa], startnu->bp, startnu->pntsu * sizeof(BPoint));
+
+ MEM_freeN(startnu->bp);
+ startnu->bp = bp1;
+ startnu->pntsu += diffa;
+ newnu = startnu;
+ }
+ else {
+ newnu = ED_curve_nurbcpy(nu, diffa);
+ BLI_addtail(newnurb, newnu);
+ set_actNurb(obedit, newnu);
+ memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint));
+ }
b = newnu->pntsu;
bp1 = newnu->bp;
@@ -1951,12 +1977,9 @@ static void adduplicateflagNurb(Object *obedit, short flag)
if (nu->flagu & CU_NURB_CYCLIC) {
if (starta != 0 || enda != nu->pntsu - 1) {
newnu->flagu &= ~CU_NURB_CYCLIC;
+ if (starta == 0) startnu = newnu;
}
}
-
- /* knots */
- newnu->knotsu = NULL;
- BKE_nurb_knot_calc_u(newnu);
}
bp++;
}
@@ -1964,7 +1987,7 @@ static void adduplicateflagNurb(Object *obedit, short flag)
else {
/* a rectangular area in nurb has to be selected */
if (isNurbsel(nu)) {
- usel = MEM_callocN(nu->pntsu, "adduplicateN4");
+ usel = MEM_callocN(nu->pntsu, "adduplicateN3");
bp = nu->bp;
for (a = 0; a < nu->pntsv; a++) {
for (b = 0; b < nu->pntsu; b++, bp++) {
@@ -1993,13 +2016,13 @@ static void adduplicateflagNurb(Object *obedit, short flag)
if (newu == 1) SWAP(int, newu, newv);
- newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN5");
+ newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN4");
memcpy(newnu, nu, sizeof(Nurb));
- BLI_addtail(editnurb, newnu);
+ BLI_addtail(newnurb, newnu);
set_actNurb(obedit, newnu);
newnu->pntsu = newu;
newnu->pntsv = newv;
- newnu->bp = (BPoint *)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6");
+ newnu->bp = (BPoint *)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN5");
BKE_nurb_order_clamp_u(newnu);
BKE_nurb_order_clamp_v(newnu);
@@ -2040,6 +2063,22 @@ static void adduplicateflagNurb(Object *obedit, short flag)
nu = nu->prev;
}
+ for (nu = newnurb->first; nu; nu = nu->next) {
+ /* knots done after duplicate as pntsu may change */
+ if (nu->pntsv == 1) {
+ nu->knotsu = NULL;
+ BKE_nurb_knot_calc_u(nu);
+ }
+
+ if (split) {
+ if (nu->type == CU_BEZIER) {
+ /* recalc first and last */
+ BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]);
+ BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]);
+ }
+ }
+ }
+
/* actnu changed */
}
@@ -2513,7 +2552,8 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot)
/* next == -1 -> select previous */
/* cont == 1 -> select continuously */
/* selstatus, inverts behavior */
-static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus)
+static void select_adjacent_cp(ListBase *editnurb, short next,
+ const bool cont, const bool selstatus)
{
Nurb *nu;
BezTriple *bezt;
@@ -2531,10 +2571,10 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
if (next < 0) bezt = &nu->bezt[a - 1];
while (a--) {
if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == 0))) {
+ if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
bezt += next;
- if (!(bezt->f2 & SELECT) || (selstatus == 0)) {
- short sel = select_beztriple(bezt, selstatus, 1, VISIBLE);
+ if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
if ((sel == 1) && (cont == 0)) lastsel = true;
}
}
@@ -2552,10 +2592,10 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
if (next < 0) bp = &nu->bp[a - 1];
while (a--) {
if (a - abs(next) < 0) break;
- if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == 0))) {
+ if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
bp += next;
- if (!(bp->f1 & SELECT) || (selstatus == 0)) {
- short sel = select_bpoint(bp, selstatus, 1, VISIBLE);
+ if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
+ short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
if ((sel == 1) && (cont == 0)) lastsel = true;
}
}
@@ -2577,7 +2617,7 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
* doswap: defines if selection state of each first/last control point is swapped
* selstatus: selection status in case doswap is false
*/
-void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus)
+void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
{
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu;
@@ -2596,7 +2636,7 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
a = nu->pntsu;
/* which point? */
- if (selfirst == 0) { /* select last */
+ if (selfirst == LAST) { /* select last */
bezt = &nu->bezt[a - 1];
}
else { /* select first */
@@ -2604,18 +2644,18 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
}
while (a--) {
- short sel;
+ bool sel;
if (doswap) sel = swap_selection_beztriple(bezt);
- else sel = select_beztriple(bezt, selstatus, 1, VISIBLE);
+ else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
- if (sel == 1) break;
+ if (sel == true) break;
}
}
else {
a = nu->pntsu * nu->pntsv;
/* which point? */
- if (selfirst == 0) { /* select last */
+ if (selfirst == LAST) { /* select last */
bp = &nu->bp[a - 1];
}
else { /* select first */
@@ -2624,11 +2664,11 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
while (a--) {
if (bp->hide == 0) {
- short sel;
+ bool sel;
if (doswap) sel = swap_selection_bpoint(bp);
- else sel = select_bpoint(bp, selstatus, 1, VISIBLE);
+ else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
- if (sel == 1) break;
+ if (sel == true) break;
}
}
}
@@ -2639,7 +2679,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
- selectend_nurb(obedit, FIRST, 1, DESELECT);
+ selectend_nurb(obedit, FIRST, true, DESELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -2664,7 +2704,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
- selectend_nurb(obedit, LAST, 1, DESELECT);
+ selectend_nurb(obedit, LAST, true, DESELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -2789,11 +2829,11 @@ static int hide_exec(bContext *C, wmOperator *op)
sel = 0;
while (a--) {
if (invert == 0 && BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
bezt->hide = 1;
}
else if (invert && !BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
bezt->hide = 1;
}
if (bezt->hide) sel++;
@@ -2807,11 +2847,11 @@ static int hide_exec(bContext *C, wmOperator *op)
sel = 0;
while (a--) {
if (invert == 0 && (bp->f1 & SELECT)) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
bp->hide = 1;
}
else if (invert && (bp->f1 & SELECT) == 0) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
bp->hide = 1;
}
if (bp->hide) sel++;
@@ -2863,7 +2903,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu;
while (a--) {
if (bezt->hide) {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
bezt->hide = 0;
}
bezt++;
@@ -2874,7 +2914,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu * nu->pntsv;
while (a--) {
if (bp->hide) {
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
bp->hide = 0;
}
bp++;
@@ -3840,7 +3880,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu
for (u = 0; u < nu1->pntsu; u++, bp++) {
if (u < origu) {
*bp = *bp1; bp1++;
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
}
else {
*bp = *bp2; bp2++;
@@ -4148,7 +4188,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
if (extend) {
if (bezt) {
if (hand == 1) {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
cu->lastsel = bezt;
}
else {
@@ -4160,13 +4200,13 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
else {
cu->lastsel = bp;
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
}
}
else if (deselect) {
if (bezt) {
if (hand == 1) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
if (bezt == cu->lastsel) cu->lastsel = NULL;
}
else if (hand == 0) {
@@ -4177,7 +4217,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
}
else {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
if (cu->lastsel == bp) cu->lastsel = NULL;
}
}
@@ -4185,11 +4225,11 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
if (bezt) {
if (hand == 1) {
if (bezt->f2 & SELECT) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
if (bezt == cu->lastsel) cu->lastsel = NULL;
}
else {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
cu->lastsel = bezt;
}
}
@@ -4202,22 +4242,22 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
else {
if (bp->f1 & SELECT) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
if (cu->lastsel == bp) cu->lastsel = NULL;
}
else {
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
cu->lastsel = bp;
}
}
}
else {
- setflagsNurb(editnurb, 0);
+ BKE_nurbList_flag_set(editnurb, 0);
if (bezt) {
if (hand == 1) {
- select_beztriple(bezt, SELECT, 1, HIDDEN);
+ select_beztriple(bezt, SELECT, SELECT, HIDDEN);
cu->lastsel = bezt;
}
else {
@@ -4229,7 +4269,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
}
else {
cu->lastsel = bp;
- select_bpoint(bp, SELECT, 1, HIDDEN);
+ select_bpoint(bp, SELECT, SELECT, HIDDEN);
}
}
@@ -4248,7 +4288,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool
/* 'cent' is in object space and 'dvec' in worldspace.
*/
-static int spin_nurb(float viewmat[4][4], Object *obedit, float *axis, float *cent)
+bool ed_editnurb_spin(float viewmat[4][4], Object *obedit, const float axis[3], const float cent[3])
{
Curve *cu = (Curve *)obedit->data;
ListBase *editnurb = object_editcurve_get(obedit);
@@ -4256,7 +4296,8 @@ static int spin_nurb(float viewmat[4][4], Object *obedit, float *axis, float *ce
float si, phi, n[3], q[4], cmat[3][3], tmat[3][3], imat[3][3];
float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3];
float persmat[3][3], persinv[3][3];
- short a, ok, changed = 0;
+ bool ok, changed = false;
+ int a;
copy_m3_m4(persmat, viewmat);
invert_m3_m3(persinv, persmat);
@@ -4295,19 +4336,19 @@ static int spin_nurb(float viewmat[4][4], Object *obedit, float *axis, float *ce
mul_m3_m3m3(tmat, persinv, cmat);
mul_m3_m3m3(scalemat2, imat, tmat);
- ok = 1;
+ ok = true;
for (a = 0; a < 7; a++) {
- ok = extrudeflagNurb(cu->editnurb, 1);
+ ok = ed_editnurb_extrude_flag(cu->editnurb, 1);
- if (ok == 0)
+ if (ok == false)
return changed;
- changed = 1;
+ changed = true;
rotateflagNurb(editnurb, SELECT, cent, rotmat);
- if ((a & SELECT) == 0) {
+ if ((a & 1) == 0) {
rotateflagNurb(editnurb, SELECT, cent, scalemat1);
weightflagNurb(editnurb, SELECT, 0.25 * M_SQRT2);
}
@@ -4347,7 +4388,7 @@ static int spin_exec(bContext *C, wmOperator *op)
else
unit_m4(viewmat);
- if (!spin_nurb(viewmat, obedit, axis, cent)) {
+ if (!ed_editnurb_spin(viewmat, obedit, axis, cent)) {
BKE_report(op->reports, RPT_ERROR, "Cannot spin");
return OPERATOR_CANCELLED;
}
@@ -4762,7 +4803,7 @@ static int extrude_exec(bContext *C, wmOperator *UNUSED(op))
addvert_Nurb(C, 'e', NULL);
}
else {
- if (extrudeflagNurb(editnurb, 1)) { /* '1'= flag */
+ if (ed_editnurb_extrude_flag(editnurb, 1)) { /* '1'= flag */
if (ED_curve_updateAnimPaths(obedit->data))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
@@ -4944,7 +4985,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
- select_beztriple(bezt, SELECT, 1, VISIBLE);
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
bezt++;
}
break;
@@ -4960,7 +5001,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a--) {
- select_bpoint(bp, SELECT, 1, VISIBLE);
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
bp++;
}
break;
@@ -5021,8 +5062,8 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
- if (deselect) select_beztriple(bezt, DESELECT, 1, VISIBLE);
- else select_beztriple(bezt, SELECT, 1, VISIBLE);
+ if (deselect) select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
+ else select_beztriple(bezt, SELECT, SELECT, VISIBLE);
bezt++;
}
}
@@ -5030,8 +5071,8 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
while (a--) {
- if (deselect) select_bpoint(bp, DESELECT, 1, VISIBLE);
- else select_bpoint(bp, SELECT, 1, VISIBLE);
+ if (deselect) select_bpoint(bp, DESELECT, SELECT, VISIBLE);
+ else select_bpoint(bp, SELECT, SELECT, VISIBLE);
bp++;
}
}
@@ -5095,7 +5136,7 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
if (ok) {
if (last == cu->lastsel) {
direction = 1 - direction;
- setflagsNurb(editnurb, 0);
+ BKE_nurbList_flag_set(editnurb, 0);
}
last = cu->lastsel;
@@ -5103,10 +5144,10 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
for (a = 0; a < nu->pntsv; a++) {
for (b = 0; b < nu->pntsu; b++, bp++) {
if (direction) {
- if (a == v) select_bpoint(bp, SELECT, 1, VISIBLE);
+ if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE);
}
else {
- if (b == u) select_bpoint(bp, SELECT, 1, VISIBLE);
+ if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
}
}
}
@@ -5217,14 +5258,14 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
/* upper control point */
if (a % nu->pntsu != 0) {
tempbp = bp - 1;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
}
/* left control point. select only if it is not selected already */
if (a - nu->pntsu > 0) {
sel = 0;
tempbp = bp + nu->pntsu;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
/* make sure selected bpoint is discarded */
if (sel == 1) BLI_BITMAP_SET(selbpoints, a - nu->pntsu);
}
@@ -5232,14 +5273,14 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
/* right control point */
if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
tempbp = bp - nu->pntsu;
- if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
}
/* lower control point. skip next bp in case selection was made */
if (a % nu->pntsu != 1) {
sel = 0;
tempbp = bp + 1;
- if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, 1, VISIBLE);
+ if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
if (sel) {
bp++;
a--;
@@ -5341,7 +5382,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
if (sel != 4) {
- select_bpoint(bp, DESELECT, 1, VISIBLE);
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
BLI_BITMAP_SET(selbpoints, a);
}
}
@@ -5387,7 +5428,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
if (sel != 2) {
- select_beztriple(bezt, DESELECT, 1, VISIBLE);
+ select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
lastsel = true;
}
else {
@@ -5429,7 +5470,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
if (sel != 2) {
- select_bpoint(bp, DESELECT, 1, VISIBLE);
+ select_bpoint(bp, DESELECT, SELECT, VISIBLE);
lastsel = true;
}
else {
@@ -5481,7 +5522,7 @@ static void selectrandom_curve(ListBase *editnurb, float randfac)
a = nu->pntsu;
while (a--) {
if (BLI_frand() < randfac)
- select_beztriple(bezt, SELECT, 1, VISIBLE);
+ select_beztriple(bezt, SELECT, SELECT, VISIBLE);
bezt++;
}
}
@@ -5491,7 +5532,7 @@ static void selectrandom_curve(ListBase *editnurb, float randfac)
while (a--) {
if (BLI_frand() < randfac)
- select_bpoint(bp, SELECT, 1, VISIBLE);
+ select_bpoint(bp, SELECT, SELECT, VISIBLE);
bp++;
}
}
@@ -5534,15 +5575,13 @@ void CURVE_OT_select_random(wmOperatorType *ot)
/********************* every nth number of point *******************/
-static int point_on_nurb(Nurb *nu, void *point)
+static bool point_in_nurb(Nurb *nu, void *point)
{
if (nu->bezt) {
- BezTriple *bezt = (BezTriple *)point;
- return bezt >= nu->bezt && bezt < &nu->bezt[nu->pntsu];
+ return ARRAY_HAS_ITEM((BezTriple *)point, nu->bezt, nu->pntsu);
}
else {
- BPoint *bp = (BPoint *)point;
- return bp >= nu->bp && bp < &nu->bp[nu->pntsu * nu->pntsv];
+ return ARRAY_HAS_ITEM((BPoint *)point, nu->bp, nu->pntsu);
}
}
@@ -5555,7 +5594,7 @@ static Nurb *get_lastsel_nurb(Curve *cu)
return NULL;
while (nu) {
- if (point_on_nurb(nu, cu->lastsel))
+ if (point_in_nurb(nu, cu->lastsel))
return nu;
nu = nu->next;
@@ -5574,7 +5613,7 @@ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth)
while (a--) {
if (abs(start - a) % nth) {
- select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
}
bezt--;
@@ -5597,7 +5636,7 @@ static void select_nth_bp(Nurb *nu, BPoint *bp, int nth)
while (a--) {
dist = abs(pnt - startpnt) + abs(row - startrow);
if (dist % nth) {
- select_bpoint(bp, DESELECT, 1, HIDDEN);
+ select_bpoint(bp, DESELECT, SELECT, HIDDEN);
}
pnt--;
@@ -5672,9 +5711,14 @@ void CURVE_OT_select_nth(wmOperatorType *ot)
static int duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
+ ListBase newnurb = {NULL, NULL};
- adduplicateflagNurb(obedit, 1);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ adduplicateflagNurb(obedit, &newnurb, SELECT, false);
+
+ if (newnurb.first != NULL) {
+ BLI_movelisttolist(object_editcurve_get(obedit), &newnurb);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
return OPERATOR_FINISHED;
}
@@ -5696,37 +5740,31 @@ void CURVE_OT_duplicate(wmOperatorType *ot)
/********************** delete operator *********************/
-static int delete_exec(bContext *C, wmOperator *op)
+static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bool split)
{
- Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
ListBase *nubase = &editnurb->nurbs;
- Nurb *nu, *nu1;
+ Nurb *nu, *nu1, *startnu;
BezTriple *bezt, *bezt1, *bezt2;
BPoint *bp, *bp1, *bp2;
- int a, cut = 0, type = RNA_enum_get(op->ptr, "type");
+ int a, b, starta, enda, cut = 0;
int nuindex = 0;
+ ListBase newnurb = {NULL, NULL};
if (obedit->type == OB_SURF) {
- if (type == 0) {
- deleteflagNurb(C, op, 1);
+ if (type == CURVE_VERTEX) {
+ return deleteflagNurb(obedit, SELECT);
}
else {
keyIndex_delNurbList(editnurb, nubase);
BKE_nurbList_free(nubase);
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ return OPERATOR_FINISHED;
}
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
-
- return OPERATOR_FINISHED;
}
- if (type == 0) {
+ if (type == CURVE_VERTEX) {
/* first loop, can we remove entire pieces? */
Nurb *next;
nu = nubase->first;
@@ -5861,204 +5899,343 @@ static int delete_exec(bContext *C, wmOperator *op)
nu = next;
}
}
- else if (type == 1) { /* erase segment */
- /* find the 2 selected points */
- bezt1 = bezt2 = NULL;
- bp1 = bp2 = NULL;
- nu1 = NULL;
- nuindex = 0;
+ else if (type == CURVE_SEGMENT) {
for (nu = nubase->first; nu; nu = nu->next) {
+ startnu = nu1 = NULL;
+ starta = enda = cut = -1;
+
if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- for (a = 0; a < nu->pntsu - 1; a++) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
- bezt1 = bezt;
- bezt2 = bezt + 1;
- if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) {
- /* pass */
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (!BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ enda = a;
+ if (starta == -1) starta = a;
+ if (a < nu->pntsu - 1) continue;
+ }
+ else if (a < nu->pntsu - 1 && !BEZSELECTED_HIDDENHANDLES(cu, bezt + 1)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsu - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC;
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+
+ nu1 = ED_curve_nurbcpy(nu, cut);
+ }
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut);
+ starta = nu->pntsu - 1;
+ cut = 1;
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
+
+ if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1;
+ }
}
- else { /* maybe do not make cyclic */
- if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) {
- bezt2 = bezt + (nu->pntsu - 1);
- if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) {
- nu->flagu &= ~CU_NURB_CYCLIC;
- BKE_nurb_handles_calc(nu);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ else if (enda == nu->pntsu - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt1) &&
+ BEZSELECTED_HIDDENHANDLES(cu, bezt2))
+ {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1);
+ }
+ else if (startnu != NULL) {
+ /* if startnu exists it is a cyclic spline, start and end should be connected */
+ bezt1 = (BezTriple *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BezTriple), "delNurb3");
+ ED_curve_beztcpy(editnurb, bezt1, &nu->bezt[starta], cut);
+ ED_curve_beztcpy(editnurb, &bezt1[cut], nu->bezt, startnu->pntsu);
+
+ MEM_freeN(startnu->bezt);
+ startnu->bezt = bezt1;
+ startnu->pntsu += cut;
+
+ if (split) {
+ for (b = 0; b < startnu->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, DESELECT, SELECT, true);
+ }
}
+
+ BKE_nurb_handles_calc(startnu);
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
}
+ }
+ else {
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
- return OPERATOR_FINISHED;
+ nu1 = ED_curve_nurbcpy(nu, cut);
}
- cut = a;
- nu1 = nu;
- break;
+
+ if (nu1 != NULL) {
+ ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut);
+
+ if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
+
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bezt1 = nu1->bezt; b < nu1->pntsu; b++, bezt1++) {
+ select_beztriple(bezt1, DESELECT, SELECT, true);
+ }
+ }
+
+ BLI_addtail(&newnurb, nu1);
+ BKE_nurb_handles_calc(nu1);
+ nu1 = NULL;
+ }
+ starta = enda = -1;
+ }
+ }
+
+ if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bezt1 = nu->bezt;
+ bezt2 = &nu->bezt[1];
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
+ }
+
+ bezt1 = &nu->bezt[nu->pntsu - 1];
+ bezt2 = &nu->bezt[nu->pntsu - 2];
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1);
+ BLI_addtail(&newnurb, nu1);
}
- bezt++;
}
}
else if (nu->pntsv == 1) {
- bp = nu->bp;
- for (a = 0; a < nu->pntsu - 1; a++) {
- if (bp->f1 & SELECT) {
- bp1 = bp;
- bp2 = bp + 1;
- if (bp2->f1 & SELECT) {
- /* pass */
+ for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ if (!(bp->f1 & SELECT)) {
+ enda = a;
+ if (starta == -1) starta = a;
+ if (a < nu->pntsu - 1) continue;
+ }
+ else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) {
+ /* if just single selected point then continue */
+ continue;
+ }
+
+ if (starta >= 0) {
+ /* got selected segment, now check where and copy */
+ if (starta <= 1 && a == nu->pntsu - 1) {
+ /* copying all points in spline */
+ if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC;
+
+ starta = 0;
+ enda = a;
+ cut = enda - starta + 1;
+
+ nu1 = ED_curve_nurbcpy(nu, cut);
+ }
+ else if (starta == 0) {
+ /* if start of curve copy next end point */
+ enda++;
+ cut = enda - starta + 1;
+
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[1], nu->bp, cut);
+ starta = nu->pntsu - 1;
+ cut = 1;
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
+
+ if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1;
+ }
}
- else { /* maybe do not make cyclic */
- if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) {
- bp2 = bp + (nu->pntsu - 1);
- if (bp2->f1 & SELECT) {
- nu->flagu &= ~CU_NURB_CYCLIC;
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ else if (enda == nu->pntsu - 1) {
+ /* if end of curve copy previous start point */
+ starta--;
+ cut = enda - starta + 1;
+
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
+
+ if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ /* check if need to join start of spline to end */
+ nu1 = ED_curve_nurbcpy(nu, cut + 1);
+ ED_curve_bpcpy(editnurb, &nu1->bp[cut], nu->bp, 1);
+ }
+ else if (startnu != NULL) {
+ /* if startnu exists it is a cyclic spline, start and end should be connected */
+ bp1 = (BPoint *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BPoint), "delNurb4");
+ ED_curve_bpcpy(editnurb, bp1, &nu->bp[starta], cut);
+ ED_curve_bpcpy(editnurb, &bp1[cut], nu->bp, startnu->pntsu);
+
+ MEM_freeN(startnu->bp);
+ startnu->bp = bp1;
+ startnu->pntsu += cut;
+
+ if (split) {
+ for (b = 0; b < startnu->pntsu; b++, bp1++) {
+ select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
+ }
}
+
+ BKE_nurb_order_clamp_u(startnu);
+ BKE_nurb_knot_calc_u(startnu);
+ }
+ else {
+ nu1 = ED_curve_nurbcpy(nu, cut);
}
+ }
+ else {
+ /* mid spline selection, copy adjacent start and end */
+ starta--;
+ enda++;
+ cut = enda - starta + 1;
- return OPERATOR_FINISHED;
+ nu1 = ED_curve_nurbcpy(nu, cut);
}
- cut = a;
- nu1 = nu;
- break;
- }
- bp++;
- }
- }
- if (nu1) break;
- nuindex++;
- }
- if (nu1) {
- if (bezt1) {
- if (nu1->pntsu == 2) { /* remove completely */
- if (cu->actnu == nuindex)
- cu->actnu = -1;
- BLI_remlink(nubase, nu);
- BKE_nurb_free(nu); nu = NULL;
- }
- else if (nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */
- bezt = (BezTriple *)MEM_mallocN((cut + 1) * sizeof(BezTriple), "delNurb1");
- ED_curve_beztcpy(editnurb, bezt, nu1->bezt, cut + 1);
- a = nu1->pntsu - cut - 1;
- ED_curve_beztcpy(editnurb, nu1->bezt, bezt2, a);
- ED_curve_beztcpy(editnurb, &nu1->bezt[a], bezt, cut + 1);
+ if (nu1 != NULL) {
+ ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta], cut);
- nu1->flagu &= ~CU_NURB_CYCLIC;
- MEM_freeN(bezt);
- BKE_nurb_handles_calc(nu);
- }
- else { /* add new curve */
+ if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC;
-/* seems to be an error here... but where? (a can become zero) */
+ if (split) {
+ /* deselect for split operator */
+ for (b = 0, bp1 = nu1->bp; b < nu1->pntsu; b++, bp1++) {
+ select_bpoint(bp1, DESELECT, SELECT, HIDDEN);
+ }
+ }
- nu = (Nurb *)MEM_mallocN(sizeof(Nurb), "delNurb2");
- memcpy(nu, nu1, sizeof(Nurb));
- BLI_addtail(nubase, nu);
- nu->bezt = (BezTriple *)MEM_mallocN((cut + 1) * sizeof(BezTriple), "delNurb3");
- ED_curve_beztcpy(editnurb, nu->bezt, nu1->bezt, cut + 1);
- a = nu1->pntsu - cut - 1;
+ BLI_addtail(&newnurb, nu1);
+ nu1->knotsu = NULL;
+ BKE_nurb_order_clamp_u(nu1);
+ BKE_nurb_knot_calc_u(nu1);
+ nu1 = NULL;
+ }
+ starta = enda = -1;
+ }
+ }
- bezt = (BezTriple *)MEM_mallocN(a * sizeof(BezTriple), "delNurb4");
- ED_curve_beztcpy(editnurb, bezt, &nu1->bezt[cut + 1], a);
- MEM_freeN(nu1->bezt);
- nu1->bezt = bezt;
- nu1->pntsu = a;
- nu->pntsu = cut + 1;
-
-
- BKE_nurb_handles_calc(nu);
- BKE_nurb_handles_calc(nu1);
- }
- }
- else if (bp1) {
- if (nu1->pntsu == 2) { /* remove completely */
- if (cu->actnu == nuindex)
- cu->actnu = -1;
-
- BLI_remlink(nubase, nu);
- BKE_nurb_free(nu); nu = NULL;
- }
- else if (nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */
- bp = (BPoint *)MEM_mallocN((cut + 1) * sizeof(BPoint), "delNurb5");
- ED_curve_bpcpy(editnurb, bp, nu1->bp, cut + 1);
- a = nu1->pntsu - cut - 1;
- ED_curve_bpcpy(editnurb, nu1->bp, bp2, a);
- ED_curve_bpcpy(editnurb, &nu1->bp[a], bp, cut + 1);
-
- nu1->flagu &= ~CU_NURB_CYCLIC;
- MEM_freeN(bp);
- }
- else { /* add new curve */
- nu = (Nurb *)MEM_mallocN(sizeof(Nurb), "delNurb6");
- memcpy(nu, nu1, sizeof(Nurb));
- BLI_addtail(nubase, nu);
- nu->bp = (BPoint *)MEM_mallocN((cut + 1) * sizeof(BPoint), "delNurb7");
- ED_curve_bpcpy(editnurb, nu->bp, nu1->bp, cut + 1);
- a = nu1->pntsu - cut - 1;
- bp = (BPoint *)MEM_mallocN(a * sizeof(BPoint), "delNurb8");
- ED_curve_bpcpy(editnurb, bp, &nu1->bp[cut + 1], a);
- MEM_freeN(nu1->bp);
- nu1->bp = bp;
- nu1->pntsu = a;
- nu1->knotsu = NULL;
- nu->pntsu = cut + 1;
-
- BKE_nurb_order_clamp_u(nu);
- BKE_nurb_knot_calc_u(nu);
+ if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) {
+ /* start and points copied if connecting segment was deleted and not cylic spline */
+ bp1 = nu->bp;
+ bp2 = &nu->bp[1];
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1);
+ BLI_addtail(&newnurb, nu1);
+ nu1->knotsu = NULL;
+ }
- BKE_nurb_order_clamp_u(nu1);
- BKE_nurb_knot_calc_u(nu1);
+ bp1 = &nu->bp[nu->pntsu - 1];
+ bp2 = &nu->bp[nu->pntsu - 2];
+ if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) {
+ nu1 = ED_curve_nurbcpy(nu, 1);
+ ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1);
+ BLI_addtail(&newnurb, nu1);
+ nu1->knotsu = NULL;
+ }
}
}
}
- }
- else if (type == 2) {
- cu->actnu = -1;
- keyIndex_delNurbList(editnurb, nubase);
+
BKE_nurbList_free(nubase);
+ BLI_movelisttolist(nubase, &newnurb);
+ }
+ else {
+ BLI_assert(0);
}
- if (ED_curve_updateAnimPaths(obedit->data))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
-
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
-
return OPERATOR_FINISHED;
}
-static int delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int curve_delete_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
- uiPopupMenu *pup;
- uiLayout *layout;
+ eCurveElem_Types type = RNA_enum_get(op->ptr, "type");
+ int retval = curve_delete_selected(obedit, type, false);
+
+ if (retval == OPERATOR_FINISHED) {
+ if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+
+ return retval;
+ }
+
+ return retval;
+}
+
+static EnumPropertyItem curve_delete_type_items[] = {
+ {CURVE_VERTEX, "VERT", 0, "Vertices", ""},
+ {CURVE_SEGMENT, "SEGMENT", 0, "Segments", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem *rna_curve_delete_type_itemf(bContext *C, PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), int *free)
+{
+ Object *obedit;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+
+ if (!C) /* needed for docs and i18n tools */
+ return curve_delete_type_items;
+
+ obedit = CTX_data_edit_object(C);
if (obedit->type == OB_SURF) {
- pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
- uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 0);
- uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 2);
- uiPupMenuEnd(C, pup);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
}
else {
- pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE);
- layout = uiPupMenuLayout(pup);
- uiItemsEnumO(layout, op->type->idname, "type");
- uiPupMenuEnd(C, pup);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX);
+ RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT);
}
- return OPERATOR_CANCELLED;
+ RNA_enum_item_end(&item, &totitem);
+ *free = true;
+
+ return item;
}
void CURVE_OT_delete(wmOperatorType *ot)
{
- static EnumPropertyItem type_items[] = {
- {0, "SELECTED", 0, "Select", ""},
- {1, "SEGMENT", 0, "Segment", ""},
- {2, "ALL", 0, "All", ""},
- {0, NULL, 0, NULL, NULL}
- };
+ PropertyRNA *prop;
/* identifiers */
ot->name = "Delete";
@@ -6066,15 +6243,18 @@ void CURVE_OT_delete(wmOperatorType *ot)
ot->idname = "CURVE_OT_delete";
/* api callbacks */
- ot->exec = delete_exec;
- ot->invoke = delete_invoke;
+ ot->exec = curve_delete_exec;
+ ot->invoke = WM_menu_invoke;
ot->poll = ED_operator_editsurfcurve;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Which elements to delete");
+ prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete");
+ RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf);
+
+ ot->prop = prop;
}
/********************** shade smooth/flat operator *********************/
@@ -6230,729 +6410,6 @@ int join_curve_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/************ add primitive, used by object/ module ****************/
-
-static const char *get_curve_defname(int type)
-{
- int stype = type & CU_PRIMITIVE;
-
- if ((type & CU_TYPE) == CU_BEZIER) {
- switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "BezierCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "BezierCircle");
- case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "CurvePath");
- default:
- return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Curve");
- }
- }
- else {
- switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCircle");
- case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsPath");
- default:
- return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Curve");
- }
- }
-}
-
-static const char *get_surf_defname(int type)
-{
- int stype = type & CU_PRIMITIVE;
-
- switch (stype) {
- case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfCurve");
- case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfCircle");
- case CU_PRIM_PATCH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfPatch");
- case CU_PRIM_SPHERE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfSphere");
- case CU_PRIM_DONUT: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfTorus");
- default:
- return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Surface");
- }
-}
-
-
-Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
-{
- static int xzproj = 0; /* this function calls itself... */
- ListBase *editnurb = object_editcurve_get(obedit);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
- Nurb *nu = NULL;
- BezTriple *bezt;
- BPoint *bp;
- Curve *cu = (Curve *)obedit->data;
- float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
- float umat[4][4] = MAT4_UNITY, viewmat[4][4] = MAT4_UNITY;
- float fac;
- int a, b;
- const float grid = v3d ? v3d->grid : 1.0f;
- const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
- const int stype = (type & CU_PRIMITIVE);
- const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */
-
- if (rv3d) {
- copy_m4_m4(viewmat, rv3d->viewmat);
- copy_v3_v3(zvec, rv3d->viewinv[2]);
- }
-
- setflagsNurb(editnurb, 0);
-
- /* these types call this function to return a Nurb */
- if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
- nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim");
- nu->type = cutype;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- }
-
- switch (stype) {
- case CU_PRIM_CURVE: /* curve */
- nu->resolu = cu->resolu;
- if (cutype == CU_BEZIER) {
- if (!force_3d) nu->flag |= CU_2D;
- nu->pntsu = 2;
- nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
- bezt = nu->bezt;
- bezt->h1 = bezt->h2 = HD_ALIGN;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->radius = 1.0;
-
- bezt->vec[1][0] += -grid;
- bezt->vec[0][0] += -1.5f * grid;
- bezt->vec[0][1] += -0.5f * grid;
- bezt->vec[2][0] += -0.5f * grid;
- bezt->vec[2][1] += 0.5f * grid;
- for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_ALIGN;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->radius = bezt->weight = 1.0;
-
- bezt->vec[0][0] = 0;
- bezt->vec[0][1] = 0;
- bezt->vec[1][0] = grid;
- bezt->vec[1][1] = 0;
- bezt->vec[2][0] = grid * 2;
- bezt->vec[2][1] = 0;
- for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
-
- BKE_nurb_handles_calc(nu);
- }
- else {
-
- nu->pntsu = 4;
- nu->pntsv = 1;
- nu->orderu = 4;
- nu->bp = CALLOC_STRUCT_N(BPoint, 4, "addNurbprim3");
-
- bp = nu->bp;
- for (a = 0; a < 4; a++, bp++) {
- bp->vec[3] = 1.0;
- bp->f1 = SELECT;
- bp->radius = bp->weight = 1.0;
- }
-
- bp = nu->bp;
- bp->vec[0] += -1.5f * grid;
- bp++;
- bp->vec[0] += -grid;
- bp->vec[1] += grid;
- bp++;
- bp->vec[0] += grid;
- bp->vec[1] += grid;
- bp++;
- bp->vec[0] += 1.5f * grid;
-
- bp = nu->bp;
- for (a = 0; a < 4; a++, bp++) mul_m4_v3(mat, bp->vec);
-
- if (cutype == CU_NURBS) {
- nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
- BKE_nurb_knot_calc_u(nu);
- }
-
- }
- break;
- case CU_PRIM_PATH: /* 5 point path */
- nu->pntsu = 5;
- nu->pntsv = 1;
- nu->orderu = 5;
- nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
- nu->resolu = cu->resolu;
- nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim3");
-
- bp = nu->bp;
- for (a = 0; a < 5; a++, bp++) {
- bp->vec[3] = 1.0;
- bp->f1 = SELECT;
- bp->radius = bp->weight = 1.0;
- }
-
- bp = nu->bp;
- bp->vec[0] += -2.0f * grid;
- bp++;
- bp->vec[0] += -grid;
- bp++; bp++;
- bp->vec[0] += grid;
- bp++;
- bp->vec[0] += 2.0f * grid;
-
- bp = nu->bp;
- for (a = 0; a < 5; a++, bp++) mul_m4_v3(mat, bp->vec);
-
- if (cutype == CU_NURBS) {
- nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
- BKE_nurb_knot_calc_u(nu);
- }
-
- break;
- case CU_PRIM_CIRCLE: /* circle */
- nu->resolu = cu->resolu;
-
- if (cutype == CU_BEZIER) {
- if (!force_3d) nu->flag |= CU_2D;
- nu->pntsu = 4;
- nu->bezt = CALLOC_STRUCT_N(BezTriple, 4, "addNurbprim1");
- nu->flagu = CU_NURB_CYCLIC;
- bezt = nu->bezt;
-
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][0] += -grid;
- for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
- bezt->radius = bezt->weight = 1.0;
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][1] += grid;
- for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
- bezt->radius = bezt->weight = 1.0;
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][0] += grid;
- for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
- bezt->radius = bezt->weight = 1.0;
-
- bezt++;
- bezt->h1 = bezt->h2 = HD_AUTO;
- bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
- bezt->vec[1][1] += -grid;
- for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
- bezt->radius = bezt->weight = 1.0;
-
- BKE_nurb_handles_calc(nu);
- }
- else if (cutype == CU_NURBS) { /* nurb */
- nu->pntsu = 8;
- nu->pntsv = 1;
- nu->orderu = 4;
- nu->bp = CALLOC_STRUCT_N(BPoint, 8, "addNurbprim6");
- nu->flagu = CU_NURB_CYCLIC;
- bp = nu->bp;
-
- for (a = 0; a < 8; a++) {
- bp->f1 = SELECT;
- if (xzproj == 0) {
- bp->vec[0] += nurbcircle[a][0] * grid;
- bp->vec[1] += nurbcircle[a][1] * grid;
- }
- else {
- bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
- bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
- }
- if (a & 1) bp->vec[3] = 0.25 * M_SQRT2;
- else bp->vec[3] = 1.0;
- mul_m4_v3(mat, bp->vec);
- bp->radius = bp->weight = 1.0;
-
- bp++;
- }
-
- BKE_nurb_knot_calc_u(nu);
- }
- break;
- case CU_PRIM_PATCH: /* 4x4 patch */
- if (cutype == CU_NURBS) { /* nurb */
-
- nu->pntsu = 4;
- nu->pntsv = 4;
- nu->orderu = 4;
- nu->orderv = 4;
- nu->flag = CU_SMOOTH;
- nu->bp = CALLOC_STRUCT_N(BPoint, 4 * 4, "addNurbprim6");
- nu->flagu = 0;
- nu->flagv = 0;
- bp = nu->bp;
-
- for (a = 0; a < 4; a++) {
- for (b = 0; b < 4; b++) {
- bp->f1 = SELECT;
- fac = (float)a - 1.5f;
- bp->vec[0] += fac * grid;
- fac = (float)b - 1.5f;
- bp->vec[1] += fac * grid;
- if ((a == 1 || a == 2) && (b == 1 || b == 2)) {
- bp->vec[2] += grid;
- }
- mul_m4_v3(mat, bp->vec);
- bp->vec[3] = 1.0;
- bp++;
- }
- }
-
- BKE_nurb_knot_calc_u(nu);
- BKE_nurb_knot_calc_v(nu);
- }
- break;
- case CU_PRIM_TUBE: /* Cylinder */
- if (cutype == CU_NURBS) {
- nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
- nu->resolu = cu->resolu;
- nu->flag = CU_SMOOTH;
- BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
- vec[0] = vec[1] = 0.0;
- vec[2] = -grid;
-
- mul_mat3_m4_v3(mat, vec);
-
- translateflagNurb(editnurb, 1, vec);
- extrudeflagNurb(cu->editnurb, 1);
- mul_v3_fl(vec, -2.0f);
- translateflagNurb(editnurb, 1, vec);
-
- BLI_remlink(editnurb, nu);
-
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a-- > 0) {
- bp->f1 |= SELECT;
- bp++;
- }
- }
- break;
- case CU_PRIM_SPHERE: /* sphere */
- if (cutype == CU_NURBS) {
- float tmp_cent[3] = {0.f, 0.f, 0.f};
- float tmp_vec[3] = {0.f, 0.f, 1.f};
-
- nu->pntsu = 5;
- nu->pntsv = 1;
- nu->orderu = 3;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- nu->flag = CU_SMOOTH;
- nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim6");
- nu->flagu = 0;
- bp = nu->bp;
-
- for (a = 0; a < 5; a++) {
- bp->f1 = SELECT;
- bp->vec[0] += nurbcircle[a][0] * grid;
- bp->vec[2] += nurbcircle[a][1] * grid;
- if (a & 1) bp->vec[3] = 0.5 * M_SQRT2;
- else bp->vec[3] = 1.0;
- mul_m4_v3(mat, bp->vec);
- bp++;
- }
- nu->flagu = CU_NURB_BEZIER;
- BKE_nurb_knot_calc_u(nu);
-
- BLI_addtail(editnurb, nu); /* temporal for spin */
-
- if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) spin_nurb(umat, obedit, tmp_vec, tmp_cent);
- else if ((U.flag & USER_ADD_VIEWALIGNED)) spin_nurb(viewmat, obedit, zvec, mat[3]);
- else spin_nurb(umat, obedit, tmp_vec, mat[3]);
-
- BKE_nurb_knot_calc_v(nu);
-
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a-- > 0) {
- bp->f1 |= SELECT;
- bp++;
- }
- BLI_remlink(editnurb, nu);
- }
- break;
- case CU_PRIM_DONUT: /* torus */
- if (cutype == CU_NURBS) {
- float tmp_cent[3] = {0.f, 0.f, 0.f};
- float tmp_vec[3] = {0.f, 0.f, 1.f};
-
- xzproj = 1;
- nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
- xzproj = 0;
- nu->resolu = cu->resolu;
- nu->resolv = cu->resolv;
- nu->flag = CU_SMOOTH;
- BLI_addtail(editnurb, nu); /* temporal for spin */
-
- /* same as above */
- if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) spin_nurb(umat, obedit, tmp_vec, tmp_cent);
- else if ((U.flag & USER_ADD_VIEWALIGNED)) spin_nurb(viewmat, obedit, zvec, mat[3]);
- else spin_nurb(umat, obedit, tmp_vec, mat[3]);
-
-
- BLI_remlink(editnurb, nu);
-
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a-- > 0) {
- bp->f1 |= SELECT;
- bp++;
- }
-
- }
- break;
-
- default: /* should never happen */
- BLI_assert(!"invalid nurbs type");
- return NULL;
- }
-
- BLI_assert(nu != NULL);
-
- if (nu) { /* should always be set */
- nu->flag |= CU_SMOOTH;
-
- BKE_nurb_test2D(nu);
- }
-
- return nu;
-}
-
-static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
-{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb;
- Nurb *nu;
- bool newob = false;
- bool enter_editmode, is_view_aligned;
- unsigned int layer;
- float loc[3], rot[3];
- float mat[4][4];
-
- if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, &is_view_aligned))
- return OPERATOR_CANCELLED;
-
- if (!isSurf) { /* adding curve */
- if (obedit == NULL || obedit->type != OB_CURVE) {
- Curve *cu;
-
- obedit = ED_object_add_type(C, OB_CURVE, loc, rot, TRUE, layer);
- newob = true;
-
- cu = (Curve *)obedit->data;
- cu->flag |= CU_DEFORM_FILL;
-
- if (type & CU_PRIM_PATH)
- cu->flag |= CU_PATH | CU_3D;
- }
- else {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
- }
- }
- else { /* adding surface */
- if (obedit == NULL || obedit->type != OB_SURF) {
- obedit = ED_object_add_type(C, OB_SURF, loc, rot, TRUE, layer);
- newob = true;
- }
- else {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
- }
- }
-
- /* rename here, the undo stack checks name for valid undo pushes */
- if (newob) {
- if (obedit->type == OB_CURVE) {
- rename_id((ID *)obedit, get_curve_defname(type));
- rename_id((ID *)obedit->data, get_curve_defname(type));
- }
- else {
- rename_id((ID *)obedit, get_surf_defname(type));
- rename_id((ID *)obedit->data, get_surf_defname(type));
- }
- }
-
- /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
- if (newob && enter_editmode)
- ED_undo_push(C, "Enter Editmode");
-
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, TRUE);
-
- nu = add_nurbs_primitive(C, obedit, mat, type, newob);
- editnurb = object_editcurve_get(obedit);
- BLI_addtail(editnurb, nu);
-
- /* userdef */
- if (newob && !enter_editmode) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-static int curve_prim_add(bContext *C, wmOperator *op, int type)
-{
- return curvesurf_prim_add(C, op, type, 0);
-}
-
-static int surf_prim_add(bContext *C, wmOperator *op, int type)
-{
- return curvesurf_prim_add(C, op, type, 1);
-}
-
-/* ******************** Curves ******************* */
-
-static int add_primitive_bezier_exec(bContext *C, wmOperator *op)
-{
- return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE);
-}
-
-void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Bezier";
- ot->description = "Construct a Bezier Curve";
- ot->idname = "CURVE_OT_primitive_bezier_curve_add";
-
- /* api callbacks */
- ot->exec = add_primitive_bezier_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op)
-{
- return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE);
-}
-
-void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Bezier Circle";
- ot->description = "Construct a Bezier Circle";
- ot->idname = "CURVE_OT_primitive_bezier_circle_add";
-
- /* api callbacks */
- ot->exec = add_primitive_bezier_circle_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op)
-{
- return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE);
-}
-
-void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Nurbs Curve";
- ot->description = "Construct a Nurbs Curve";
- ot->idname = "CURVE_OT_primitive_nurbs_curve_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_curve_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op)
-{
- return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE);
-}
-
-void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Nurbs Circle";
- ot->description = "Construct a Nurbs Circle";
- ot->idname = "CURVE_OT_primitive_nurbs_circle_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_circle_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_curve_path_exec(bContext *C, wmOperator *op)
-{
- return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH);
-}
-
-void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Path";
- ot->description = "Construct a Path";
- ot->idname = "CURVE_OT_primitive_nurbs_path_add";
-
- /* api callbacks */
- ot->exec = add_primitive_curve_path_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-/* **************** NURBS surfaces ********************** */
-static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op)
-{
- return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS);
-}
-
-void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Surface Curve";
- ot->description = "Construct a Nurbs surface Curve";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_curve_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op)
-{
- return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS);
-}
-
-void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Surface Circle";
- ot->description = "Construct a Nurbs surface Circle";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_circle_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op)
-{
- return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS);
-}
-
-void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Surface Patch";
- ot->description = "Construct a Nurbs surface Patch";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_surface_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op)
-{
- return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS);
-}
-
-void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Surface Cylinder";
- ot->description = "Construct a Nurbs surface Cylinder";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_cylinder_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op)
-{
- return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS);
-}
-
-void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Surface Sphere";
- ot->description = "Construct a Nurbs surface Sphere";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_sphere_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
-
-static int add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op)
-{
- return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS);
-}
-
-void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Surface Torus";
- ot->description = "Construct a Nurbs surface Torus";
- ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add";
-
- /* api callbacks */
- ot->exec = add_primitive_nurbs_surface_torus_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ED_object_add_generic_props(ot, TRUE);
-}
/***************** clear tilt operator ********************/
@@ -7158,6 +6615,22 @@ void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count)
keyIndex_updateBP(editnurb, src, dst, count);
}
+Nurb *ED_curve_nurbcpy(Nurb *src, int count)
+{
+ Nurb *newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "copyNurb");
+ memcpy(newnu, src, sizeof(Nurb));
+ newnu->pntsu = count;
+
+ if (src->bezt) {
+ newnu->bezt = (BezTriple *)MEM_mallocN(count * sizeof(BezTriple), "copyNurb2");
+ }
+ else {
+ newnu->bp = (BPoint *)MEM_mallocN(count * sizeof(BPoint), "copyNurb3");
+ }
+
+ return newnu;
+}
+
int ED_curve_actSelection(Curve *cu, float center[3])
{
Nurb *nu = get_lastsel_nurb(cu);
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
new file mode 100644
index 00000000000..0bcb550b930
--- /dev/null
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -0,0 +1,812 @@
+/*
+ * ***** 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/editors/curve/editcurve_add.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_math.h"
+
+#include "BLF_translation.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_library.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+#include "ED_view3d.h"
+#include "ED_curve.h"
+
+#include "curve_intern.h"
+
+static float nurbcircle[8][2] = {
+ {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0},
+ {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0}
+};
+
+/************ add primitive, used by object/ module ****************/
+
+static const char *get_curve_defname(int type)
+{
+ int stype = type & CU_PRIMITIVE;
+
+ if ((type & CU_TYPE) == CU_BEZIER) {
+ switch (stype) {
+ case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "BezierCurve");
+ case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "BezierCircle");
+ case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "CurvePath");
+ default:
+ return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Curve");
+ }
+ }
+ else {
+ switch (stype) {
+ case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCurve");
+ case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsCircle");
+ case CU_PRIM_PATH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "NurbsPath");
+ default:
+ return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Curve");
+ }
+ }
+}
+
+static const char *get_surf_defname(int type)
+{
+ int stype = type & CU_PRIMITIVE;
+
+ switch (stype) {
+ case CU_PRIM_CURVE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfCurve");
+ case CU_PRIM_CIRCLE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfCircle");
+ case CU_PRIM_PATCH: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfPatch");
+ case CU_PRIM_SPHERE: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfSphere");
+ case CU_PRIM_DONUT: return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "SurfTorus");
+ default:
+ return CTX_DATA_(BLF_I18NCONTEXT_ID_CURVE, "Surface");
+ }
+}
+
+
+Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
+{
+ static int xzproj = 0; /* this function calls itself... */
+ ListBase *editnurb = object_editcurve_get(obedit);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+ Nurb *nu = NULL;
+ BezTriple *bezt;
+ BPoint *bp;
+ Curve *cu = (Curve *)obedit->data;
+ float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
+ float umat[4][4] = MAT4_UNITY, viewmat[4][4] = MAT4_UNITY;
+ float fac;
+ int a, b;
+ const float grid = v3d ? v3d->grid : 1.0f;
+ const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
+ const int stype = (type & CU_PRIMITIVE);
+ const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */
+
+ if (rv3d) {
+ copy_m4_m4(viewmat, rv3d->viewmat);
+ copy_v3_v3(zvec, rv3d->viewinv[2]);
+ }
+
+ BKE_nurbList_flag_set(editnurb, 0);
+
+ /* these types call this function to return a Nurb */
+ if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim");
+ nu->type = cutype;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ }
+
+ switch (stype) {
+ case CU_PRIM_CURVE: /* curve */
+ nu->resolu = cu->resolu;
+ if (cutype == CU_BEZIER) {
+ if (!force_3d) nu->flag |= CU_2D;
+ nu->pntsu = 2;
+ nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
+ bezt = nu->bezt;
+ bezt->h1 = bezt->h2 = HD_ALIGN;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->radius = 1.0;
+
+ bezt->vec[1][0] += -grid;
+ bezt->vec[0][0] += -1.5f * grid;
+ bezt->vec[0][1] += -0.5f * grid;
+ bezt->vec[2][0] += -0.5f * grid;
+ bezt->vec[2][1] += 0.5f * grid;
+ for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_ALIGN;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt->vec[0][0] = 0;
+ bezt->vec[0][1] = 0;
+ bezt->vec[1][0] = grid;
+ bezt->vec[1][1] = 0;
+ bezt->vec[2][0] = grid * 2;
+ bezt->vec[2][1] = 0;
+ for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
+
+ BKE_nurb_handles_calc(nu);
+ }
+ else {
+
+ nu->pntsu = 4;
+ nu->pntsv = 1;
+ nu->orderu = 4;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3");
+
+ bp = nu->bp;
+ for (a = 0; a < 4; a++, bp++) {
+ bp->vec[3] = 1.0;
+ bp->f1 = SELECT;
+ bp->radius = bp->weight = 1.0;
+ }
+
+ bp = nu->bp;
+ bp->vec[0] += -1.5f * grid;
+ bp++;
+ bp->vec[0] += -grid;
+ bp->vec[1] += grid;
+ bp++;
+ bp->vec[0] += grid;
+ bp->vec[1] += grid;
+ bp++;
+ bp->vec[0] += 1.5f * grid;
+
+ bp = nu->bp;
+ for (a = 0; a < 4; a++, bp++) mul_m4_v3(mat, bp->vec);
+
+ if (cutype == CU_NURBS) {
+ nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
+ BKE_nurb_knot_calc_u(nu);
+ }
+
+ }
+ break;
+ case CU_PRIM_PATH: /* 5 point path */
+ nu->pntsu = 5;
+ nu->pntsv = 1;
+ nu->orderu = 5;
+ nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
+ nu->resolu = cu->resolu;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3");
+
+ bp = nu->bp;
+ for (a = 0; a < 5; a++, bp++) {
+ bp->vec[3] = 1.0;
+ bp->f1 = SELECT;
+ bp->radius = bp->weight = 1.0;
+ }
+
+ bp = nu->bp;
+ bp->vec[0] += -2.0f * grid;
+ bp++;
+ bp->vec[0] += -grid;
+ bp++; bp++;
+ bp->vec[0] += grid;
+ bp++;
+ bp->vec[0] += 2.0f * grid;
+
+ bp = nu->bp;
+ for (a = 0; a < 5; a++, bp++) mul_m4_v3(mat, bp->vec);
+
+ if (cutype == CU_NURBS) {
+ nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
+ BKE_nurb_knot_calc_u(nu);
+ }
+
+ break;
+ case CU_PRIM_CIRCLE: /* circle */
+ nu->resolu = cu->resolu;
+
+ if (cutype == CU_BEZIER) {
+ if (!force_3d) nu->flag |= CU_2D;
+ nu->pntsu = 4;
+ nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1");
+ nu->flagu = CU_NURB_CYCLIC;
+ bezt = nu->bezt;
+
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][0] += -grid;
+ for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][1] += grid;
+ for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][0] += grid;
+ for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ bezt++;
+ bezt->h1 = bezt->h2 = HD_AUTO;
+ bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
+ bezt->vec[1][1] += -grid;
+ for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
+ bezt->radius = bezt->weight = 1.0;
+
+ BKE_nurb_handles_calc(nu);
+ }
+ else if (cutype == CU_NURBS) { /* nurb */
+ nu->pntsu = 8;
+ nu->pntsv = 1;
+ nu->orderu = 4;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6");
+ nu->flagu = CU_NURB_CYCLIC;
+ bp = nu->bp;
+
+ for (a = 0; a < 8; a++) {
+ bp->f1 = SELECT;
+ if (xzproj == 0) {
+ bp->vec[0] += nurbcircle[a][0] * grid;
+ bp->vec[1] += nurbcircle[a][1] * grid;
+ }
+ else {
+ bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
+ bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
+ }
+ if (a & 1) bp->vec[3] = 0.25 * M_SQRT2;
+ else bp->vec[3] = 1.0;
+ mul_m4_v3(mat, bp->vec);
+ bp->radius = bp->weight = 1.0;
+
+ bp++;
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+ }
+ break;
+ case CU_PRIM_PATCH: /* 4x4 patch */
+ if (cutype == CU_NURBS) { /* nurb */
+
+ nu->pntsu = 4;
+ nu->pntsv = 4;
+ nu->orderu = 4;
+ nu->orderv = 4;
+ nu->flag = CU_SMOOTH;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6");
+ nu->flagu = 0;
+ nu->flagv = 0;
+ bp = nu->bp;
+
+ for (a = 0; a < 4; a++) {
+ for (b = 0; b < 4; b++) {
+ bp->f1 = SELECT;
+ fac = (float)a - 1.5f;
+ bp->vec[0] += fac * grid;
+ fac = (float)b - 1.5f;
+ bp->vec[1] += fac * grid;
+ if ((a == 1 || a == 2) && (b == 1 || b == 2)) {
+ bp->vec[2] += grid;
+ }
+ mul_m4_v3(mat, bp->vec);
+ bp->vec[3] = 1.0;
+ bp++;
+ }
+ }
+
+ BKE_nurb_knot_calc_u(nu);
+ BKE_nurb_knot_calc_v(nu);
+ }
+ break;
+ case CU_PRIM_TUBE: /* Cylinder */
+ if (cutype == CU_NURBS) {
+ nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
+ nu->resolu = cu->resolu;
+ nu->flag = CU_SMOOTH;
+ BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
+ vec[0] = vec[1] = 0.0;
+ vec[2] = -grid;
+
+ mul_mat3_m4_v3(mat, vec);
+
+ ed_editnurb_translate_flag(editnurb, 1, vec);
+ ed_editnurb_extrude_flag(cu->editnurb, 1);
+ mul_v3_fl(vec, -2.0f);
+ ed_editnurb_translate_flag(editnurb, 1, vec);
+
+ BLI_remlink(editnurb, nu);
+
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a-- > 0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+ }
+ break;
+ case CU_PRIM_SPHERE: /* sphere */
+ if (cutype == CU_NURBS) {
+ float tmp_cent[3] = {0.f, 0.f, 0.f};
+ float tmp_vec[3] = {0.f, 0.f, 1.f};
+
+ nu->pntsu = 5;
+ nu->pntsv = 1;
+ nu->orderu = 3;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->flag = CU_SMOOTH;
+ nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6");
+ nu->flagu = 0;
+ bp = nu->bp;
+
+ for (a = 0; a < 5; a++) {
+ bp->f1 = SELECT;
+ bp->vec[0] += nurbcircle[a][0] * grid;
+ bp->vec[2] += nurbcircle[a][1] * grid;
+ if (a & 1) bp->vec[3] = 0.5 * M_SQRT2;
+ else bp->vec[3] = 1.0;
+ mul_m4_v3(mat, bp->vec);
+ bp++;
+ }
+ nu->flagu = CU_NURB_BEZIER;
+ BKE_nurb_knot_calc_u(nu);
+
+ BLI_addtail(editnurb, nu); /* temporal for spin */
+
+ if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
+ ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
+ else if ((U.flag & USER_ADD_VIEWALIGNED))
+ ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
+ else
+ ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);
+
+ BKE_nurb_knot_calc_v(nu);
+
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a-- > 0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+ BLI_remlink(editnurb, nu);
+ }
+ break;
+ case CU_PRIM_DONUT: /* torus */
+ if (cutype == CU_NURBS) {
+ float tmp_cent[3] = {0.f, 0.f, 0.f};
+ float tmp_vec[3] = {0.f, 0.f, 1.f};
+
+ xzproj = 1;
+ nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
+ xzproj = 0;
+ nu->resolu = cu->resolu;
+ nu->resolv = cu->resolv;
+ nu->flag = CU_SMOOTH;
+ BLI_addtail(editnurb, nu); /* temporal for spin */
+
+ /* same as above */
+ if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
+ ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
+ else if ((U.flag & USER_ADD_VIEWALIGNED))
+ ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
+ else
+ ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);
+
+
+ BLI_remlink(editnurb, nu);
+
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a-- > 0) {
+ bp->f1 |= SELECT;
+ bp++;
+ }
+
+ }
+ break;
+
+ default: /* should never happen */
+ BLI_assert(!"invalid nurbs type");
+ return NULL;
+ }
+
+ BLI_assert(nu != NULL);
+
+ if (nu) { /* should always be set */
+ nu->flag |= CU_SMOOTH;
+
+ BKE_nurb_test2D(nu);
+ }
+
+ return nu;
+}
+
+static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *editnurb;
+ Nurb *nu;
+ bool newob = false;
+ bool enter_editmode, is_view_aligned;
+ unsigned int layer;
+ float dia;
+ float loc[3], rot[3];
+ float mat[4][4];
+
+ WM_operator_view3d_unit_defaults(C, op);
+
+ if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, &is_view_aligned))
+ return OPERATOR_CANCELLED;
+
+ if (!isSurf) { /* adding curve */
+ if (obedit == NULL || obedit->type != OB_CURVE) {
+ Curve *cu;
+
+ obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer);
+ newob = true;
+
+ cu = (Curve *)obedit->data;
+ cu->flag |= CU_DEFORM_FILL;
+
+ if (type & CU_PRIM_PATH)
+ cu->flag |= CU_PATH | CU_3D;
+ }
+ else {
+ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ }
+ }
+ else { /* adding surface */
+ if (obedit == NULL || obedit->type != OB_SURF) {
+ obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer);
+ newob = true;
+ }
+ else {
+ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ }
+ }
+
+ /* rename here, the undo stack checks name for valid undo pushes */
+ if (newob) {
+ if (obedit->type == OB_CURVE) {
+ rename_id((ID *)obedit, get_curve_defname(type));
+ rename_id((ID *)obedit->data, get_curve_defname(type));
+ }
+ else {
+ rename_id((ID *)obedit, get_surf_defname(type));
+ rename_id((ID *)obedit->data, get_surf_defname(type));
+ }
+ }
+
+ /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
+ if (newob && enter_editmode)
+ ED_undo_push(C, "Enter Editmode");
+
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ dia = RNA_float_get(op->ptr, "radius");
+ mat[0][0] *= dia;
+ mat[1][1] *= dia;
+ mat[2][2] *= dia;
+
+ nu = add_nurbs_primitive(C, obedit, mat, type, newob);
+ editnurb = object_editcurve_get(obedit);
+ BLI_addtail(editnurb, nu);
+
+ /* userdef */
+ if (newob && !enter_editmode) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int curve_prim_add(bContext *C, wmOperator *op, int type)
+{
+ return curvesurf_prim_add(C, op, type, 0);
+}
+
+static int surf_prim_add(bContext *C, wmOperator *op, int type)
+{
+ return curvesurf_prim_add(C, op, type, 1);
+}
+
+/* ******************** Curves ******************* */
+
+static int add_primitive_bezier_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE);
+}
+
+void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Bezier";
+ ot->description = "Construct a Bezier Curve";
+ ot->idname = "CURVE_OT_primitive_bezier_curve_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_bezier_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE);
+}
+
+void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Bezier Circle";
+ ot->description = "Construct a Bezier Circle";
+ ot->idname = "CURVE_OT_primitive_bezier_circle_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_bezier_circle_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE);
+}
+
+void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Nurbs Curve";
+ ot->description = "Construct a Nurbs Curve";
+ ot->idname = "CURVE_OT_primitive_nurbs_curve_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_curve_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE);
+}
+
+void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Nurbs Circle";
+ ot->description = "Construct a Nurbs Circle";
+ ot->idname = "CURVE_OT_primitive_nurbs_circle_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_circle_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_curve_path_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH);
+}
+
+void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Path";
+ ot->description = "Construct a Path";
+ ot->idname = "CURVE_OT_primitive_nurbs_path_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_curve_path_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+/* **************** NURBS surfaces ********************** */
+static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Surface Curve";
+ ot->description = "Construct a Nurbs surface Curve";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_curve_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Surface Circle";
+ ot->description = "Construct a Nurbs surface Circle";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_circle_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Surface Patch";
+ ot->description = "Construct a Nurbs surface Patch";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_surface_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Surface Cylinder";
+ ot->description = "Construct a Nurbs surface Cylinder";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_cylinder_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Surface Sphere";
+ ot->description = "Construct a Nurbs surface Sphere";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_sphere_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
+static int add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Surface Torus";
+ ot->description = "Construct a Nurbs surface Torus";
+ ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add";
+
+ /* api callbacks */
+ ot->exec = add_primitive_nurbs_surface_torus_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index b9759e16f20..ac9c338e431 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -981,7 +981,7 @@ void FONT_OT_move_select(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Move Select";
- ot->description = "Make selection from current cursor position to new cursor position type";
+ ot->description = "Move the cursor while selecting";
ot->idname = "FONT_OT_move_select";
/* api callbacks */
diff --git a/source/blender/editors/curve/lorem.c b/source/blender/editors/curve/lorem.c
index 52f5101f58a..59bf3f50dbc 100644
--- a/source/blender/editors/curve/lorem.c
+++ b/source/blender/editors/curve/lorem.c
@@ -23,6 +23,7 @@
*/
+#include "BLI_sys_types.h"
#include "curve_intern.h"
const char ED_lorem[] = {
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 8d108644470..6adc500baa4 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -47,8 +47,18 @@ if(WITH_BLENDER)
# images
data_to_c_simple(../../../../release/datafiles/splash.png SRC)
+ # XXX These are handy, but give nasty "false changes" in svn :/
+ #svg_to_png(../../../../release/datafiles/blender_icons.svg
+ #../../../../release/datafiles/blender_icons16.png
+ #90 SRC)
data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC)
+ #svg_to_png(../../../../release/datafiles/blender_icons.svg
+ #../../../../release/datafiles/blender_icons32.png
+ #180 SRC)
data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC)
+ #svg_to_png(../../../../release/datafiles/prvicons.svg
+ #../../../../release/datafiles/prvicons.png
+ #90 SRC)
data_to_c_simple(../../../../release/datafiles/prvicons.png SRC)
# brushes
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 99157b074fd..c5dc8654e9d 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -106,8 +106,8 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr)
/* TODO: we can include other data-types such as bones later if need be... */
- /* just in case no active object */
- if (ob) {
+ /* just in case no active/selected object */
+ if (ob && (ob->flag & SELECT)) {
/* for now, as long as there's an object, default to using that in 3D-View */
if (ptr) RNA_id_pointer_create(&ob->id, ptr);
return &ob->gpd;
@@ -192,7 +192,14 @@ bGPdata *gpencil_data_get_active(const bContext *C)
/* needed for offscreen rendering */
bGPdata *gpencil_data_get_active_v3d(Scene *scene)
{
- bGPdata *gpd = scene->basact ? scene->basact->object->gpd : NULL;
+ Base *base = scene->basact;
+ bGPdata *gpd = NULL;
+ /* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
+ * to be consistent with gpencil_data_get_active's behavior.
+ */
+ if (base && (scene->lay & base->lay) && (base->object->flag & SELECT)) {
+ gpd = base->object->gpd;
+ }
return gpd ? gpd : scene->gpd;
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 4c5727f16ed..255f0b7cfba 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1431,7 +1431,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
gpencil_undo_finish();
/* restore cursor to indicate end of drawing */
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
/* don't assume that operator data exists at all */
if (p) {
@@ -1679,7 +1679,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
/* loop over the stroke RNA elements recorded (i.e. progress of mouse movement),
* setting the relevant values in context at each step, then applying
*/
- RNA_BEGIN(op->ptr, itemptr, "stroke")
+ RNA_BEGIN (op->ptr, itemptr, "stroke")
{
float mousef[2];
@@ -1764,9 +1764,9 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* set cursor */
if (p->paintmode == GP_PAINTMODE_ERASER)
- WM_cursor_modal(win, BC_CROSSCURSOR); /* XXX need a better cursor */
+ WM_cursor_modal_set(win, BC_CROSSCURSOR); /* XXX need a better cursor */
else
- WM_cursor_modal(win, BC_PAINTBRUSHCURSOR);
+ WM_cursor_modal_set(win, BC_PAINTBRUSHCURSOR);
/* special hack: if there was an initial event, then we were invoked via a hotkey, and
* painting should start immediately. Otherwise, this was called from a toolbar, in which
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 352a74cf172..dd1995a5428 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -221,8 +221,5 @@ void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter,
/* Draw imbuf on a screen, preferably using GLSL display transform */
void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter);
-/* Transform buffer from role to scene linear space using GLSL OCIO conversion */
-int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role);
-
#endif /* __BIF_GLUTIL_H__ */
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 1de1731b515..61f9cec15d9 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -233,29 +233,29 @@ typedef enum eAnimFilter_Flags {
/* Dopesheet only */
/* 'Scene' channels */
-#define SEL_SCEC(sce) (CHECK_TYPE_INLINE(sce, Scene), ((sce->flag & SCE_DS_SELECTED)))
-#define EXPANDED_SCEC(sce) (CHECK_TYPE_INLINE(sce, Scene), ((sce->flag & SCE_DS_COLLAPSED) == 0))
+#define SEL_SCEC(sce) (CHECK_TYPE_INLINE(sce, Scene *), ((sce->flag & SCE_DS_SELECTED)))
+#define EXPANDED_SCEC(sce) (CHECK_TYPE_INLINE(sce, Scene *), ((sce->flag & SCE_DS_COLLAPSED) == 0))
/* 'Sub-Scene' channels (flags stored in Data block) */
-#define FILTER_WOR_SCED(wo) (CHECK_TYPE_INLINE(wo, World), (wo->flag & WO_DS_EXPAND))
+#define FILTER_WOR_SCED(wo) (CHECK_TYPE_INLINE(wo, World *), (wo->flag & WO_DS_EXPAND))
#define FILTER_LS_SCED(linestyle) ((linestyle->flag & LS_DS_EXPAND))
/* 'Object' channels */
-#define SEL_OBJC(base) (CHECK_TYPE_INLINE(base, Base), ((base->flag & SELECT)))
-#define EXPANDED_OBJC(ob) (CHECK_TYPE_INLINE(ob, Object), ((ob->nlaflag & OB_ADS_COLLAPSED) == 0))
+#define SEL_OBJC(base) (CHECK_TYPE_INLINE(base, Base *), ((base->flag & SELECT)))
+#define EXPANDED_OBJC(ob) (CHECK_TYPE_INLINE(ob, Object *), ((ob->nlaflag & OB_ADS_COLLAPSED) == 0))
/* 'Sub-object' channels (flags stored in Data block) */
-#define FILTER_SKE_OBJD(key) (CHECK_TYPE_INLINE(key, Key), ((key->flag & KEY_DS_EXPAND)))
-#define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material), ((ma->flag & MA_DS_EXPAND)))
-#define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Lamp), ((la->flag & LA_DS_EXPAND)))
-#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera), ((ca->flag & CAM_DS_EXPAND)))
-#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve), ((cu->flag & CU_DS_EXPAND)))
-#define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings), ((part->flag & PART_DS_EXPAND)))
-#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall), ((mb->flag2 & MB_DS_EXPAND)))
-#define FILTER_ARM_OBJD(arm) (CHECK_TYPE_INLINE(arm, bArmature), ((arm->flag & ARM_DS_EXPAND)))
-#define FILTER_MESH_OBJD(me) (CHECK_TYPE_INLINE(me, Mesh), ((me->flag & ME_DS_EXPAND)))
-#define FILTER_LATTICE_OBJD(lt) (CHECK_TYPE_INLINE(lt, Lattice), ((lt->flag & LT_DS_EXPAND)))
-#define FILTER_SPK_OBJD(spk) (CHECK_TYPE_INLINE(spk, Speaker), ((spk->flag & SPK_DS_EXPAND)))
+#define FILTER_SKE_OBJD(key) (CHECK_TYPE_INLINE(key, Key *), ((key->flag & KEY_DS_EXPAND)))
+#define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material *), ((ma->flag & MA_DS_EXPAND)))
+#define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Lamp *), ((la->flag & LA_DS_EXPAND)))
+#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera *), ((ca->flag & CAM_DS_EXPAND)))
+#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve *), ((cu->flag & CU_DS_EXPAND)))
+#define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings *), ((part->flag & PART_DS_EXPAND)))
+#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall *), ((mb->flag2 & MB_DS_EXPAND)))
+#define FILTER_ARM_OBJD(arm) (CHECK_TYPE_INLINE(arm, bArmature *), ((arm->flag & ARM_DS_EXPAND)))
+#define FILTER_MESH_OBJD(me) (CHECK_TYPE_INLINE(me, Mesh *), ((me->flag & ME_DS_EXPAND)))
+#define FILTER_LATTICE_OBJD(lt) (CHECK_TYPE_INLINE(lt, Lattice *), ((lt->flag & LT_DS_EXPAND)))
+#define FILTER_SPK_OBJD(spk) (CHECK_TYPE_INLINE(spk, Speaker *), ((spk->flag & SPK_DS_EXPAND)))
/* Variable use expanders */
-#define FILTER_NTREE_DATA(ntree) (CHECK_TYPE_INLINE(ntree, bNodeTree), ((ntree->flag & NTREE_DS_EXPAND)))
-#define FILTER_TEX_DATA(tex) (CHECK_TYPE_INLINE(tex, Tex), ((tex->flag & TEX_DS_EXPAND)))
+#define FILTER_NTREE_DATA(ntree) (CHECK_TYPE_INLINE(ntree, bNodeTree *), ((ntree->flag & NTREE_DS_EXPAND)))
+#define FILTER_TEX_DATA(tex) (CHECK_TYPE_INLINE(tex, Tex *), ((tex->flag & TEX_DS_EXPAND)))
/* 'Sub-object/Action' channels (flags stored in Action) */
#define SEL_ACTC(actc) ((actc->flag & ACT_SELECTED))
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index fab179da7bc..225d8a0e5a3 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -94,15 +94,15 @@ typedef struct EditBone {
/* useful macros */
#define EBONE_VISIBLE(arm, ebone) ( \
- CHECK_TYPE_INLINE(arm, bArmature), \
- CHECK_TYPE_INLINE(ebone, EditBone), \
+ CHECK_TYPE_INLINE(arm, bArmature *), \
+ CHECK_TYPE_INLINE(ebone, EditBone *), \
(((arm)->layer & (ebone)->layer) && !((ebone)->flag & BONE_HIDDEN_A)) \
)
#define EBONE_SELECTABLE(arm, ebone) (EBONE_VISIBLE(arm, ebone) && !(ebone->flag & BONE_UNSELECTABLE))
#define EBONE_EDITABLE(ebone) ( \
- CHECK_TYPE_INLINE(ebone, EditBone), \
+ CHECK_TYPE_INLINE(ebone, EditBone *), \
(((ebone)->flag & BONE_SELECTED) && !((ebone)->flag & BONE_EDITMODE_LOCKED)) \
)
@@ -167,7 +167,6 @@ void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag);
/* poseobject.c */
void ED_armature_exit_posemode(struct bContext *C, struct Base *base);
void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
-int ED_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
void ED_pose_deselectall(struct Object *ob, int test);
void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob);
struct Object *ED_pose_object_from_context(struct bContext *C);
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 541956136bd..27e62928f1b 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -63,18 +63,18 @@ int ED_space_clip_get_clip_frame_number(struct SpaceClip *sc);
struct ImBuf *ED_space_clip_get_buffer(struct SpaceClip *sc);
struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc, float loc[2], float *scale, float *angle);
-int ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]);
+bool ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]);
void ED_clip_update_frame(const struct Main *mainp, int cfra);
-int ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, int fit);
+bool ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, bool fit);
void ED_clip_point_undistorted_pos(struct SpaceClip *sc, const float co[2], float r_co[2]);
void ED_clip_point_stable_pos(struct SpaceClip *sc, struct ARegion *ar, float x, float y, float *xr, float *yr);
void ED_clip_point_stable_pos__reverse(struct SpaceClip *sc, struct ARegion *ar, const float co[2], float r_co[2]);
void ED_clip_mouse_pos(struct SpaceClip *sc, struct ARegion *ar, const int mval[2], float co[2]);
-int ED_space_clip_check_show_trackedit(struct SpaceClip *sc);
-int ED_space_clip_check_show_maskedit(struct SpaceClip *sc);
+bool ED_space_clip_check_show_trackedit(struct SpaceClip *sc);
+bool ED_space_clip_check_show_maskedit(struct SpaceClip *sc);
struct MovieClip *ED_space_clip_get_clip(struct SpaceClip *sc);
void ED_space_clip_set_clip(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip);
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 1d26204095c..571788f4f8f 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -83,6 +83,7 @@ int CU_select_nth(struct Object *obedit, int nth);
void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, struct BezTriple *src, int count);
void ED_curve_bpcpy(struct EditNurb *editnurb, struct BPoint *dst, struct BPoint *src, int count);
+struct Nurb *ED_curve_nurbcpy(struct Nurb *src, int count);
int ED_curve_updateAnimPaths(struct Curve *cu);
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 95fad17274e..dc40efc748b 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -222,6 +222,7 @@ short ANIM_keyingset_context_ok_poll(struct bContext *C, struct KeyingSet *ks);
/* Flags for use by driver creation calls */
typedef enum eCreateDriverFlags {
CREATEDRIVER_WITH_DEFAULT_DVAR = (1 << 0), /* create drivers with a default variable for nicer UI */
+ CREATEDRIVER_WITH_FMODIFIER = (1 << 1), /* create drivers with Generator FModifier (for backwards compat) */
} eCreateDriverFlags;
/* -------- */
diff --git a/source/blender/editors/include/ED_lattice.h b/source/blender/editors/include/ED_lattice.h
index 15e5c3dba8f..6fe1524cb6d 100644
--- a/source/blender/editors/include/ED_lattice.h
+++ b/source/blender/editors/include/ED_lattice.h
@@ -28,8 +28,13 @@
* \ingroup editors
*/
+#ifndef __ED_LATTICE_H__
+#define __ED_LATTICE_H__
+
struct Object;
void free_editLatt(struct Object *ob);
void make_editLatt(struct Object *obedit);
void load_editLatt(struct Object *obedit);
+
+#endif /* __ED_LATTICE_H__ */
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index 420ab24e5e9..3e2dbe255df 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -48,6 +48,8 @@ void ED_mask_point_pos(struct ScrArea *sa, struct ARegion *ar, float x, float y,
void ED_mask_point_pos__reverse(struct ScrArea *sa, struct ARegion *ar,
float x, float y, float *xr, float *yr);
+void ED_mask_cursor_location_get(struct ScrArea *sa, float cursor[2]);
+
void ED_operatortypes_mask(void);
void ED_keymap_mask(struct wmKeyConfig *keyconf);
void ED_operatormacros_mask(void);
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index da96aba011e..1842b84a3f5 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -39,7 +39,7 @@ struct wmKeyConfig;
void ED_operatortypes_metaball(void);
void ED_keymap_metaball(struct wmKeyConfig *keyconf);
-struct MetaElem *add_metaball_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], float dia, int type, int newname);
+struct MetaElem *add_metaball_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], float dia, int type);
bool mouse_mball(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index f24f9098fcd..b7fd181883b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -242,8 +242,18 @@ void ED_vgroup_clear(struct Object *ob);
void ED_vgroup_select_by_name(struct Object *ob, const char *name);
bool ED_vgroup_data_create(struct ID *id);
void ED_vgroup_data_clamp_range(struct ID *id, const int total);
-bool ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
-bool ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from);
+bool ED_vgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
+bool ED_vgroup_array_copy(struct Object *ob, struct Object *ob_from);
+bool ED_vgroup_parray_alloc(struct ID *id, struct MDeformVert ***dvert_arr, int *dvert_tot,
+ const bool use_vert_sel);
+void ED_vgroup_parray_mirror_sync(struct Object *ob,
+ struct MDeformVert **dvert_array, const int dvert_tot,
+ const bool *vgroup_validmap, const int vgroup_tot);
+void ED_vgroup_parray_mirror_assign(struct Object *ob,
+ struct MDeformVert **dvert_array, const int dvert_tot);
+void ED_vgroup_parray_remove_zero(struct 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_mirror(struct Object *ob,
const bool mirror_weights, const bool flip_vgroups,
const bool all_vgroups, const bool use_topology,
@@ -317,6 +327,8 @@ struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh
int index, const bool use_topology);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
+int ED_mesh_mirror_get_vert(struct Object *ob, int index);
+
bool ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf);
bool ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
bool ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 90b131e5acc..eae2141e527 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -92,7 +92,7 @@ typedef enum eParentType {
PAR_PATH_CONST,
PAR_LATTICE,
PAR_VERTEX,
- PAR_TRIA
+ PAR_VERTEX_TRI
} eParentType;
#ifdef __RNA_TYPES_H__
@@ -101,7 +101,7 @@ extern struct EnumPropertyItem prop_make_parent_types[];
#endif
int ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob,
- struct Object *par, int partype, int xmirror, int keep_transform);
+ struct Object *par, int partype, bool xmirror, bool keep_transform, const int vert_par[3]);
void ED_object_parent_clear(struct Object *ob, int type);
struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
@@ -123,6 +123,7 @@ struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, st
void ED_object_parent(struct Object *ob, struct Object *parent, 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 */
@@ -140,14 +141,15 @@ void ED_object_rotation_from_view(struct bContext *C, float rot[3]);
void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]);
float ED_object_new_primitive_matrix(struct bContext *C, struct Object *editob,
const float loc[3], const float rot[3], float primmat[4][4],
- int apply_diameter);
+ bool apply_diameter);
-void ED_object_add_generic_props(struct wmOperatorType *ot, int do_editmode);
-int ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, float loc[3], float rot[3],
- bool *enter_editmode, unsigned int *layer, bool *is_view_aligned);
+void ED_object_add_unit_props(struct wmOperatorType *ot);
+void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode);
+bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, float loc[3], float rot[3],
+ bool *enter_editmode, unsigned int *layer, bool *is_view_aligned);
struct Object *ED_object_add_type(struct bContext *C, int type, const float loc[3], const float rot[3],
- int enter_editmode, unsigned int layer);
+ bool enter_editmode, unsigned int layer);
void ED_object_single_users(struct Main *bmain, struct Scene *scene, bool full, bool copy_groups);
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
@@ -206,6 +208,8 @@ void ED_object_select_linked_by_id(struct bContext *C, struct ID *id);
bool *ED_vgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type,
int *r_vgroup_tot, int *r_subset_count);
+void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
+ int *r_vgroup_subset_map);
struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
const struct bContext *C,
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index bdfbbbb9c74..518bee665ae 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -40,6 +40,7 @@ struct Scene;
struct ScrArea;
struct RegionView3D;
struct RenderEngine;
+struct View3D;
/* render_ops.c */
@@ -51,6 +52,7 @@ void ED_render_id_flush_update(struct Main *bmain, struct ID *id);
void ED_render_engine_changed(struct Main *bmain);
void ED_render_engine_area_exit(struct ScrArea *sa);
void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated);
+void ED_render_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
void ED_viewport_render_kill_jobs(const struct bContext *C, bool free_database);
diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h
index 9f42fd042c3..2b02606c6d9 100644
--- a/source/blender/editors/include/ED_screen_types.h
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -79,7 +79,7 @@ typedef enum {
AE_RIGHT_TO_TOPLEFT, /* Region located on the left, _right_ edge is action zone. Region minimized to the top left */
AE_LEFT_TO_TOPRIGHT, /* Region located on the right, _left_ edge is action zone. Region minimized to the top right */
AE_TOP_TO_BOTTOMRIGHT, /* Region located at the bottom, _top_ edge is action zone. Region minimized to the bottom right */
- AE_BOTTOM_TO_TOPLEFT /* Region located at the top, _bottom_edge is action zone. Region minimized to the top left */
+ AE_BOTTOM_TO_TOPLEFT /* Region located at the top, _bottom_ edge is action zone. Region minimized to the top left */
} AZEdge;
/* for editing areas/regions */
@@ -87,10 +87,8 @@ typedef struct AZone {
struct AZone *next, *prev;
ARegion *ar;
int type;
- /* region-azone, which of the edges */
+ /* region-azone, which of the edges (only for AZONE_REGION) */
AZEdge edge;
- /* internal */
- short do_draw;
/* for draw */
short x1, y1, x2, y2;
/* for clip */
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 67f790f0b46..7f642db9fbd 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -78,9 +78,9 @@ void undo_editmode_push(struct bContext *C, const char *name,
void undo_editmode_clear(void);
/* crazyspace.c */
-float *crazyspace_get_mapped_editverts(struct Scene *scene, struct Object *obedit);
-void crazyspace_set_quats_editmesh(struct BMEditMesh *em, float *origcos, float *mappedcos, float *quats);
-void crazyspace_set_quats_mesh(struct Mesh *me, float *origcos, float *mappedcos, float *quats);
+float (*crazyspace_get_mapped_editverts(struct Scene *scene, struct Object *obedit))[3];
+void crazyspace_set_quats_editmesh(struct BMEditMesh *em, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]);
+void crazyspace_set_quats_mesh(struct Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]);
int sculpt_get_first_deform_matrices(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
void crazyspace_build_sculpt(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index ffc9e6651bc..735227ae9b5 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -102,7 +102,7 @@ void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit);
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel);
/* uvedit_draw.c */
-void draw_image_cursor(struct SpaceImage *sima, struct ARegion *ar);
+void draw_image_cursor(struct ARegion *ar, const float cursor[2]);
void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
/* uvedit_buttons.c */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index ef50a21c900..86abf29c308 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -248,7 +248,9 @@ unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2
unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y);
/* draws and does a 4x4 sample */
-bool ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, const int mval[2], float mouse_worldloc[3], bool alphaoverride);
+bool ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
+ const int mval[2], float mouse_worldloc[3],
+ bool alphaoverride, const float fallback_depth_pt[3]);
/* only draw so ED_view3d_autodist_simple can be called many times after */
void ED_view3d_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode);
@@ -334,4 +336,7 @@ void ED_view3d_operator_properties_viewmat_set(struct bContext *C, struct wmOper
void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx, int *winy, float persmat[4][4]);
#endif
+/* render */
+void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 3929cf9788c..f8e1bbb2413 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -49,9 +49,7 @@ DEF_ICON(RADIOBUT_OFF)
DEF_ICON(RADIOBUT_ON)
DEF_ICON(MENU_PANEL)
DEF_ICON(BLENDER)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK003)
-#endif
+DEF_ICON(GRIP)
DEF_ICON(DOT)
#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK004)
@@ -75,9 +73,9 @@ DEF_ICON(VIEWZOOM)
DEF_ICON(ZOOMIN)
DEF_ICON(ZOOMOUT)
DEF_ICON(PANEL_CLOSE)
-DEF_ICON(COPY_ID) //ICON_BLANK009
+DEF_ICON(COPY_ID)
DEF_ICON(EYEDROPPER)
-DEF_ICON(LINK_AREA) //ICON_BLANK010
+DEF_ICON(LINK_AREA)
DEF_ICON(AUTO)
DEF_ICON(CHECKBOX_DEHLT)
DEF_ICON(CHECKBOX_HLT)
@@ -138,7 +136,7 @@ DEF_ICON(SCRIPT)
DEF_ICON(PARTICLES)
DEF_ICON(PHYSICS)
DEF_ICON(SPEAKER)
-DEF_ICON(TEXTURE_SHADED) //ICON_BLANK041
+DEF_ICON(TEXTURE_SHADED)
#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK042)
DEF_ICON(BLANK043)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 9a9cab9b46c..38aad640ee1 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -32,6 +32,7 @@
#ifndef __UI_INTERFACE_H__
#define __UI_INTERFACE_H__
+#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h" /* size_t */
#include "RNA_types.h"
#include "DNA_userdef_types.h"
@@ -81,6 +82,10 @@ typedef struct uiLayout uiLayout;
/* Defines */
+/* char for splitting strings, aligning shortcuts in menus, users never see */
+#define UI_SEP_CHAR '|'
+#define UI_SEP_CHAR_S "|"
+
/* names */
#define UI_MAX_DRAW_STR 400
#define UI_MAX_NAME_STR 128
@@ -327,30 +332,14 @@ typedef void (*uiMenuHandleFunc)(struct bContext *C, void *arg, int event);
typedef struct uiPopupMenu uiPopupMenu;
-struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon)
-#ifdef __GNUC__
-__attribute__((nonnull))
-#endif
-;
+struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) ATTR_NONNULL();
void uiPupMenuEnd(struct bContext *C, struct uiPopupMenu *head);
struct uiLayout *uiPupMenuLayout(uiPopupMenu *head);
-void uiPupMenuOkee(struct bContext *C, const char *opname, const char *str, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 3, 4)))
-#endif
-;
+void uiPupMenuOkee(struct bContext *C, const char *opname, const char *str, ...) ATTR_PRINTF_FORMAT(3, 4);
void uiPupMenuSaveOver(struct bContext *C, struct wmOperator *op, const char *filename);
-void uiPupMenuNotice(struct bContext *C, const char *str, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
-;
-void uiPupMenuError(struct bContext *C, const char *str, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
-;
+void uiPupMenuNotice(struct bContext *C, const char *str, ...) ATTR_PRINTF_FORMAT(2, 3);
+void uiPupMenuError(struct bContext *C, const char *str, ...) ATTR_PRINTF_FORMAT(2, 3);
void uiPupMenuReports(struct bContext *C, struct ReportList *reports);
void uiPupMenuInvoke(struct bContext *C, const char *idname); /* popup registered menu */
@@ -550,11 +539,7 @@ typedef struct uiStringInfo {
/* Note: Expects pointers to uiStringInfo structs as parameters.
* Will fill them with translated strings, when possible.
* Strings in uiStringInfo must be MEM_freeN'ed by caller. */
-void uiButGetStrInfo(struct bContext *C, uiBut *but, ...)
-#ifdef __GNUC__
-__attribute__((sentinel))
-#endif
-;
+void uiButGetStrInfo(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
/* Edit i18n stuff. */
/* Name of the main py op from i18n addon. */
@@ -845,7 +830,7 @@ void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type);
+ const char *active_propname, int rows, int maxrows, int layout_type, int columns);
void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 42e9d892871..0c8a39a6714 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -210,6 +210,9 @@ enum {
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
+ TH_UV_SHADOW,
+ TH_UV_OTHERS,
+
TH_FREESTYLE_EDGE_MARK,
TH_FREESTYLE_FACE_MARK,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index e46334b06e7..c9a19ab4d8e 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -192,6 +192,7 @@ void UI_view2d_listview_visible_cells(struct View2D *v2d, float columnwidth, flo
void UI_view2d_region_to_view(struct View2D *v2d, float x, float y, float *viewx, float *viewy);
void UI_view2d_view_to_region(struct View2D *v2d, float x, float y, int *regionx, int *regiony);
void UI_view2d_to_region_no_clip(struct View2D *v2d, float x, float y, int *regionx, int *region_y);
+void UI_view2d_to_region_float(struct View2D *v2d, float x, float y, float *regionx, float *regiony);
/* utilities */
struct View2D *UI_view2d_fromcontext(const struct bContext *C);
@@ -215,7 +216,7 @@ void UI_view2d_operatortypes(void);
void UI_view2d_keymap(struct wmKeyConfig *keyconf);
void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar,
- const struct rctf *cur);
+ const struct rctf *cur, const int smooth_viewtx);
#endif /* __UI_VIEW2D_H__ */
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index a8b8765a5c6..e13517adbb3 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -40,6 +40,7 @@ set(SRC
interface.c
interface_anim.c
interface_draw.c
+ interface_eyedropper.c
interface_handlers.c
interface_icons.c
interface_layout.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 21a63183c1a..e02cdf018c0 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -837,7 +837,7 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
{
if (do_strip) {
- char *cpoin = strchr(but->str, '|');
+ char *cpoin = strchr(but->str, UI_SEP_CHAR);
if (cpoin) {
*cpoin = '\0';
}
@@ -855,7 +855,7 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str
}
BLI_snprintf(but->strdata,
sizeof(but->strdata),
- "%s|%s",
+ "%s" UI_SEP_CHAR_S "%s",
butstr_orig, shortcut_str);
MEM_freeN(butstr_orig);
but->str = but->strdata;
@@ -962,10 +962,12 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
data_path = BLI_sprintfN("scene.%s", path);
MEM_freeN(path);
}
- /*else {
- printf("ERROR in %s(): Couldn't get path for scene property - %s\n",
+#if 0
+ else {
+ printf("ERROR in %s(): Couldn't get path for scene property - %s\n",
__func__, RNA_property_identifier(but->rnaprop));
- }*/
+ }
+#endif
}
}
else {
@@ -985,7 +987,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
IDPropertyTemplate val = {0};
prop_path = IDP_New(IDP_GROUP, &val, __func__);
- prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1); /* len + 1, or else will be truncated */
+ prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1);
IDP_AddToGroup(prop_path, prop_path_value);
/* check each until one works... */
@@ -1644,19 +1646,19 @@ void ui_set_but_val(uiBut *but, double value)
if (RNA_property_editable(&but->rnapoin, prop)) {
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if (RNA_property_array_length(&but->rnapoin, prop))
+ if (RNA_property_array_check(prop))
RNA_property_boolean_set_index(&but->rnapoin, prop, but->rnaindex, value);
else
RNA_property_boolean_set(&but->rnapoin, prop, value);
break;
case PROP_INT:
- if (RNA_property_array_length(&but->rnapoin, prop))
+ if (RNA_property_array_check(prop))
RNA_property_int_set_index(&but->rnapoin, prop, but->rnaindex, (int)value);
else
RNA_property_int_set(&but->rnapoin, prop, (int)value);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(&but->rnapoin, prop))
+ if (RNA_property_array_check(prop))
RNA_property_float_set_index(&but->rnapoin, prop, but->rnaindex, value);
else
RNA_property_float_set(&but->rnapoin, prop, value);
@@ -1807,12 +1809,14 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va
static float ui_get_but_step_unit(uiBut *but, float step_default)
{
int unit_type = RNA_SUBTYPE_UNIT_VALUE(uiButGetUnitType(but));
- float step;
+ double step;
step = bUnit_ClosestScalar(ui_get_but_scale_unit(but, step_default), but->block->unit->system, unit_type);
- if (step > 0.0f) { /* -1 is an error value */
- return (float)((double)step / ui_get_but_scale_unit(but, 1.0)) * 100.0f;
+ /* -1 is an error value */
+ if (step != -1.0) {
+ BLI_assert(step > 0.0);
+ return (float)(step / ui_get_but_scale_unit(but, 1.0)) * 100.0f;
}
else {
return step_default;
@@ -2047,13 +2051,14 @@ bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
return false;
}
-void ui_set_but_default(bContext *C, short all)
+void ui_set_but_default(bContext *C, const bool all)
{
+ const char *opstring = "UI_OT_reset_default_button";
PointerRNA ptr;
- WM_operator_properties_create(&ptr, "UI_OT_reset_default_button");
+ WM_operator_properties_create(&ptr, opstring);
RNA_boolean_set(&ptr, "all", all);
- WM_operator_name_call(C, "UI_OT_reset_default_button", WM_OP_EXEC_DEFAULT, &ptr);
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
}
@@ -2230,8 +2235,7 @@ void uiFreeBlock(const bContext *C, uiBlock *block)
{
uiBut *but;
- while ( (but = block->buttons.first) ) {
- BLI_remlink(&block->buttons, but);
+ while ((but = BLI_pophead(&block->buttons))) {
ui_free_but(C, but);
}
@@ -2255,8 +2259,7 @@ void uiFreeBlocks(const bContext *C, ListBase *lb)
{
uiBlock *block;
- while ( (block = lb->first) ) {
- BLI_remlink(lb, block);
+ while ((block = BLI_pophead(lb))) {
uiFreeBlock(C, block);
}
}
@@ -3024,7 +3027,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
but->rnapoin = *ptr;
but->rnaprop = prop;
- if (RNA_property_array_length(&but->rnapoin, but->rnaprop))
+ if (RNA_property_array_check(but->rnaprop))
but->rnaindex = index;
else
but->rnaindex = 0;
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 3feb563d3ee..5b6b889a6c6 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -144,7 +144,7 @@ int ui_but_anim_expression_create(uiBut *but, const char *str)
return 0;
}
- if (RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0) {
+ if (RNA_property_array_check(but->rnaprop) != 0) {
if (but->rnaindex == -1) {
if (G.debug & G_DEBUG)
printf("ERROR: create expression failed - can't create expression for entire array\n");
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index cd845da10c6..11062ea2bd2 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -1389,7 +1389,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (scopes->track_disabled) {
glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
ok = 1;
@@ -1437,7 +1437,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (scopes->use_track_mask) {
glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
}
@@ -1478,7 +1478,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (!ok) {
glColor4f(0.f, 0.f, 0.f, 0.3f);
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
new file mode 100644
index 00000000000..56dd18565dc
--- /dev/null
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -0,0 +1,639 @@
+/*
+ * ***** 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) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_eyedropper.c
+ * \ingroup edinterface
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math_vector.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_report.h"
+#include "BKE_idcode.h"
+
+#include "RNA_access.h"
+
+#include "BIF_gl.h"
+
+#include "UI_interface.h"
+
+#include "IMB_colormanagement.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "interface_intern.h"
+
+/* for HDR color sampling */
+#include "ED_image.h"
+#include "ED_node.h"
+#include "ED_clip.h"
+
+/* for ID data eyedropper */
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Eyedropper
+ */
+
+/** \name Eyedropper (RGB Color)
+ * \{ */
+
+typedef struct Eyedropper {
+ struct ColorManagedDisplay *display;
+
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ int accum_start; /* has mouse been presed */
+ float accum_col[3];
+ int accum_tot;
+} Eyedropper;
+
+static int eyedropper_init(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Eyedropper *eye;
+
+ op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper");
+
+ uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index);
+
+ if ((eye->ptr.data == NULL) ||
+ (eye->prop == NULL) ||
+ (RNA_property_editable(&eye->ptr, eye->prop) == FALSE) ||
+ (RNA_property_array_length(&eye->ptr, eye->prop) < 3) ||
+ (RNA_property_type(eye->prop) != PROP_FLOAT))
+ {
+ return FALSE;
+ }
+
+ if (RNA_property_subtype(eye->prop) == PROP_COLOR) {
+ const char *display_device;
+
+ display_device = scene->display_settings.display_device;
+ eye->display = IMB_colormanagement_display_get_named(display_device);
+ }
+
+ return TRUE;
+}
+
+static void eyedropper_exit(bContext *C, wmOperator *op)
+{
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+}
+
+static int eyedropper_cancel(bContext *C, wmOperator *op)
+{
+ eyedropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+/* *** eyedropper_color_ helper functions *** */
+
+/**
+ * \brief get the color from the screen.
+ *
+ * Special check for image or nodes where we MAY have HDR pixels which don't display.
+ */
+static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3])
+{
+
+ /* we could use some clever */
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa;
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceImage *sima = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_image_color_sample(sima, ar, mval, r_col)) {
+ return;
+ }
+ }
+ }
+ else if (sa->spacetype == SPACE_NODE) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceNode *snode = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_node_color_sample(snode, ar, mval, r_col)) {
+ return;
+ }
+ }
+ }
+ else if (sa->spacetype == SPACE_CLIP) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ SpaceClip *sc = sa->spacedata.first;
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+
+ if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /* fallback to simple opengl picker */
+ glReadBuffer(GL_FRONT);
+ glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
+ glReadBuffer(GL_BACK);
+}
+
+/* sets the sample color RGB, maintaining A */
+static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3])
+{
+ float col_conv[4];
+
+ /* to maintain alpha */
+ RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
+
+ /* convert from display space to linear rgb space */
+ if (eye->display) {
+ copy_v3_v3(col_conv, col);
+ IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display);
+ }
+ else {
+ copy_v3_v3(col_conv, col);
+ }
+
+ RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv);
+
+ RNA_property_update(C, &eye->ptr, eye->prop);
+}
+
+/* set sample from accumulated values */
+static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye)
+{
+ float col[3];
+ mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot);
+ eyedropper_color_set(C, eye, col);
+}
+
+/* single point sample & set */
+static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
+{
+ float col[3];
+ eyedropper_color_sample_fl(C, eye, mx, my, col);
+ eyedropper_color_set(C, eye, col);
+}
+
+static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my)
+{
+ float col[3];
+ eyedropper_color_sample_fl(C, eye, mx, my, col);
+ /* delay linear conversion */
+ add_v3_v3(eye->accum_col, col);
+ eye->accum_tot++;
+}
+
+/* main modal status check */
+static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Eyedropper *eye = (Eyedropper *)op->customdata;
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ return eyedropper_cancel(C, op);
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ if (eye->accum_tot == 0) {
+ eyedropper_color_sample(C, eye, event->x, event->y);
+ }
+ else {
+ eyedropper_color_set_accum(C, eye);
+ }
+ eyedropper_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else if (event->val == KM_PRESS) {
+ /* enable accum and make first sample */
+ eye->accum_start = TRUE;
+ eyedropper_color_sample_accum(C, eye, event->x, event->y);
+ }
+ break;
+ case MOUSEMOVE:
+ if (eye->accum_start) {
+ /* button is pressed so keep sampling */
+ eyedropper_color_sample_accum(C, eye, event->x, event->y);
+ eyedropper_color_set_accum(C, eye);
+ }
+ break;
+ case SPACEKEY:
+ if (event->val == KM_RELEASE) {
+ eye->accum_tot = 0;
+ zero_v3(eye->accum_col);
+ eyedropper_color_sample_accum(C, eye, event->x, event->y);
+ eyedropper_color_set_accum(C, eye);
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* init */
+ if (eyedropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ eyedropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Repeat operator */
+static int eyedropper_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (eyedropper_init(C, op)) {
+
+ /* do something */
+
+ /* cleanup */
+ eyedropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int eyedropper_poll(bContext *C)
+{
+ if (!CTX_wm_window(C)) return 0;
+ else return 1;
+}
+
+void UI_OT_eyedropper_color(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Eyedropper";
+ ot->idname = "UI_OT_eyedropper_color";
+ ot->description = "Sample a color from the Blender Window to store in a property";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_invoke;
+ ot->modal = eyedropper_modal;
+ ot->cancel = eyedropper_cancel;
+ ot->exec = eyedropper_exec;
+ ot->poll = eyedropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+ /* properties */
+}
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Data Dropper
+ *
+ * note: datadropper is only internal name to avoid confusion in this file
+ */
+
+/** \name Eyedropper (ID data-blocks)
+ * \{ */
+
+typedef struct DataDropper {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ short idcode;
+ const char *idcode_name;
+
+ ARegionType *art;
+ void *draw_handle_pixel;
+ char name[200];
+} DataDropper;
+
+
+static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
+{
+ DataDropper *ddr = arg;
+ int width;
+ const char *name = ddr->name;
+ wmWindow *win = CTX_wm_window(C);
+ int x = win->eventstate->x;
+ int y = win->eventstate->y;
+
+ if ((name[0] == '\0') ||
+ (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
+ {
+ return;
+ }
+
+ width = UI_GetStringWidth(name);
+ x = x - ar->winrct.xmin;
+ y = y - ar->winrct.ymin;
+
+ y += 20;
+
+ glColor4ub(0, 0, 0, 50);
+
+ uiSetRoundBox(UI_CNR_ALL | UI_RB_ALPHA);
+ uiRoundBox(x, y, x + width + 8, y + 15, 4);
+
+ glColor4ub(255, 255, 255, 255);
+ UI_DrawString(x + 4, y + 4, name);
+}
+
+
+static int datadropper_init(bContext *C, wmOperator *op)
+{
+ DataDropper *ddr;
+ int index_dummy;
+ StructRNA *type;
+
+ SpaceType *st;
+ ARegionType *art;
+
+ st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
+
+ op->customdata = ddr = MEM_callocN(sizeof(DataDropper), "DataDropper");
+
+ uiContextActiveProperty(C, &ddr->ptr, &ddr->prop, &index_dummy);
+
+ if ((ddr->ptr.data == NULL) ||
+ (ddr->prop == NULL) ||
+ (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+ (RNA_property_type(ddr->prop) != PROP_POINTER))
+ {
+ return false;
+ }
+
+ ddr->art = art;
+ ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+
+ type = RNA_property_pointer_type(&ddr->ptr, ddr->prop);
+ ddr->idcode = RNA_type_to_ID_code(type);
+ BLI_assert(ddr->idcode != 0);
+ ddr->idcode_name = BKE_idcode_to_name(ddr->idcode);
+
+ return true;
+}
+
+static void datadropper_exit(bContext *C, wmOperator *op)
+{
+ DataDropper *ddr = (DataDropper *)op->customdata;
+
+ WM_cursor_modal_restore(CTX_wm_window(C));
+
+ ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+}
+
+static int datadropper_cancel(bContext *C, wmOperator *op)
+{
+ datadropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+/* *** datadropper id helper functions *** */
+/**
+ * \brief get the ID from the screen.
+ *
+ */
+static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
+{
+
+ /* we could use some clever */
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa;
+
+ ScrArea *area_prev = CTX_wm_area(C);
+ ARegion *ar_prev = CTX_wm_region(C);
+
+ ddr->name[0] = '\0';
+
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ int mval[2] = {mx - ar->winrct.xmin,
+ my - ar->winrct.ymin};
+ Base *base;
+
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* grr, always draw else we leave stale text */
+ ED_region_tag_redraw(ar);
+
+ base = ED_view3d_give_base_under_cursor(C, mval);
+ if (base) {
+ Object *ob = base->object;
+ ID *id = NULL;
+ if (ddr->idcode == ID_OB) {
+ id = (ID *)ob;
+ }
+ else if (ob->data) {
+ if (GS(((ID *)ob->data)->name) == ddr->idcode) {
+ id = (ID *)ob->data;
+ }
+ else {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
+ ddr->idcode_name);
+ }
+ }
+
+ if (id) {
+ BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
+ ddr->idcode_name, id->name + 2);
+ *r_id = id;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ CTX_wm_area_set(C, area_prev);
+ CTX_wm_region_set(C, ar_prev);
+}
+
+/* sets the ID, returns success */
+static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id)
+{
+ PointerRNA ptr_value;
+
+ RNA_id_pointer_create(id, &ptr_value);
+
+ RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value);
+
+ RNA_property_update(C, &ddr->ptr, ddr->prop);
+
+ ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
+
+ return (ptr_value.id.data == id);
+}
+
+/* single point sample & set */
+static bool datadropper_id_sample(bContext *C, DataDropper *ddr, int mx, int my)
+{
+ ID *id = NULL;
+
+ datadropper_id_sample_pt(C, ddr, mx, my, &id);
+ return datadropper_id_set(C, ddr, id);
+}
+
+/* main modal status check */
+static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ DataDropper *ddr = (DataDropper *)op->customdata;
+
+ switch (event->type) {
+ case ESCKEY:
+ case RIGHTMOUSE:
+ return datadropper_cancel(C, op);
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ bool success;
+
+ success = datadropper_id_sample(C, ddr, event->x, event->y);
+ datadropper_exit(C, op);
+
+ if (success) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "Failed to set value");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ break;
+ case MOUSEMOVE:
+ {
+ ID *id = NULL;
+ datadropper_id_sample_pt(C, ddr, event->x, event->y, &id);
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int datadropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* init */
+ if (datadropper_init(C, op)) {
+ WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ datadropper_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+/* Repeat operator */
+static int datadropper_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (datadropper_init(C, op)) {
+ /* cleanup */
+ datadropper_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int datadropper_poll(bContext *C)
+{
+ if (!CTX_wm_window(C)) return 0;
+ else return 1;
+}
+
+void UI_OT_eyedropper_id(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Eyedropper Datablock";
+ ot->idname = "UI_OT_eyedropper_id";
+ ot->description = "Sample a color from the Blender Window to store in a property";
+
+ /* api callbacks */
+ ot->invoke = datadropper_invoke;
+ ot->modal = datadropper_modal;
+ ot->cancel = datadropper_cancel;
+ ot->exec = datadropper_exec;
+ ot->poll = datadropper_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+ /* properties */
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index f9ee2b67e6b..c5faa99e067 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -152,7 +152,9 @@ typedef struct uiHandleButtonData {
char *str, *origstr;
double value, origvalue, startvalue;
float vec[3], origvec[3];
+#if 0 /* UNUSED */
int togdual, togonly;
+#endif
ColorBand *coba;
/* tooltip */
@@ -170,6 +172,7 @@ typedef struct uiHandleButtonData {
/* coords are Window/uiBlock relative (depends on the button) */
int draglastx, draglasty;
int dragstartx, dragstarty;
+ int draglastvalue;
bool dragchange, draglock;
int dragsel;
float dragf, dragfstart;
@@ -1978,7 +1981,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
ui_check_but(but);
- WM_cursor_modal(CTX_wm_window(C), BC_TEXTEDITCURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_TEXTEDITCURSOR);
}
static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -2010,7 +2013,7 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
but->pos = -1;
}
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
}
static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonData *data)
@@ -2094,10 +2097,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
break;
case RIGHTMOUSE:
case ESCKEY:
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- retval = WM_UI_HANDLER_BREAK;
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ retval = WM_UI_HANDLER_BREAK;
+ }
break;
case LEFTMOUSE:
{
@@ -2217,13 +2222,21 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case BACKSPACEKEY:
changed = ui_textedit_delete(but, data, 0,
- event->shift ? STRCUR_JUMP_ALL : (event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE));
+ event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
retval = WM_UI_HANDLER_BREAK;
break;
case AKEY:
+
/* Ctrl + A: Select all */
- if (event->ctrl && !(event->alt || event->shift || event->oskey)) {
+#if defined(__APPLE__)
+ /* OSX uses cmd-a systemwide, so add it */
+ if ((event->oskey && !(event->alt || event->shift || event->ctrl)) ||
+ (event->ctrl && !(event->alt || event->shift || event->oskey)))
+#else
+ if (event->ctrl && !(event->alt || event->shift || event->oskey))
+#endif
+ {
ui_textedit_move(but, data, STRCUR_DIR_PREV,
false, STRCUR_JUMP_ALL);
ui_textedit_move(but, data, STRCUR_DIR_NEXT,
@@ -2566,9 +2579,11 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
return WM_UI_HANDLER_BREAK;
}
else if (event->type == ESCKEY) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
}
@@ -2606,7 +2621,10 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM4(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
- if (but->dt == UI_EMBOSSN && !event->ctrl) {
+ if (ELEM(event->type, PADENTER, RETKEY) && (!ui_is_but_utf8(but))) {
+ /* pass - allow filesel, enter to execute */
+ }
+ else if (but->dt == UI_EMBOSSN && !event->ctrl) {
/* pass */
}
else {
@@ -2640,13 +2658,8 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa
BLI_rcti_rctf_copy(&rect, &but->rect);
rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect));
- if ( BLI_rcti_isect_pt(&rect, x, y) ) {
- /* most likely NULL, but let's check, and give it temp zero string */
- if (data->str == NULL)
- data->str = MEM_callocN(16, "temp str");
- data->str[0] = 0;
-
- ui_apply_but_TEX(C, but, data);
+ if (BLI_rcti_isect_pt(&rect, x, y)) {
+ ui_set_but_string(C, but, "");
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
@@ -2660,8 +2673,10 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
#ifdef USE_DRAG_TOGGLE
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_is_but_bool(but)) {
+#if 0 /* UNUSED */
data->togdual = event->ctrl;
data->togonly = !event->shift;
+#endif
ui_apply_button(C, but->block, but, data, true);
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
@@ -2677,8 +2692,10 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
#endif
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+#if 0 /* UNUSED */
data->togdual = event->ctrl;
data->togonly = !event->shift;
+#endif
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
@@ -3007,9 +3024,11 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
if (data->dragchange)
@@ -3271,9 +3290,11 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- data->cancel = TRUE;
- data->escapecancel = TRUE;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = TRUE;
+ data->escapecancel = TRUE;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
if (data->dragchange)
@@ -3388,9 +3409,11 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -3406,6 +3429,102 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
return retval;
}
+static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ uiList *ui_list = but->custom_data;
+ int *size = (int *)but->poin;
+ int mx, my, raw_dir_sign;
+ int retval = WM_UI_HANDLER_CONTINUE;
+
+ mx = event->x;
+ my = event->y;
+
+ /* We find the direction of the mouse since last time, before converting coordinates into block's space.
+ * We'll use it to avoid flickering in case some rows are higher than UI_UNIT_Y.
+ */
+ raw_dir_sign = (data->draglasty - my < 0) ? -1 : 1;
+ data->draglasty = my;
+
+ ui_window_to_block(data->region, block, &mx, &my);
+
+ if (data->state == BUTTON_STATE_NUM_EDITING) {
+ if (event->type == ESCKEY) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ *size = (int)data->origvalue;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_list->flag &= ~UILST_RESIZING;
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_list->flag &= ~UILST_RESIZING;
+ ED_region_tag_redraw(data->region);
+ }
+ else if (event->type == MOUSEMOVE) {
+ /* If we switched from dragged to auto size, suspend shrinking dragging and set dragstarty to a temp
+ * refpoint.
+ */
+ if (data->draglastvalue > 0 && *size == 0) {
+ data->draglastvalue = *size;
+ data->dragstartx = data->dragstarty; /* draglasty already used... */
+ data->dragstarty = my;
+ }
+ else {
+ int delta = data->dragstarty - my;
+ /* We only actually do something if the real mousemouve direction matches the "virtual"
+ * mousemove direction in current block's space. This avoids flickering when drag-resizing lists with
+ * items drawing higher that UI_UNIT_Y.
+ */
+ if (delta * raw_dir_sign > 0) {
+ /* Number of rows to show/hide, UI_UNIT_Y should work nice in most cases. */
+ delta = (int)floorf(((float)delta / (float)UI_UNIT_Y) + 0.5f);
+
+ /* If we are not in autosize mode, default behavior... */
+ if (*size > 0 && delta != 0) {
+ /* This prevents some instability in case some items draw more/less than UI_UNIT_Y height. */
+ delta = (delta < -5) ? -5 : (delta > 5) ? 5 : delta;
+ /* We can't use ui_numedit_apply()... */
+ /* list template will clamp, but we do not want to reach 0 aka autosize mode! */
+ *size = max_ii(*size + delta, 1);
+
+ /* Used to detect switch to/from autosize mode. */
+ data->draglastvalue = *size;
+
+ data->dragchange = true;
+ data->applied = data->applied_interactive = true;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(data->region);
+ }
+ /* If we are leaving autosize mode (growing dragging), restore to minimal size. */
+ else if (delta > 0) {
+ /* We can't use ui_numedit_apply()... */
+ *size = ui_list->dyn_data->visual_height_min;
+
+ /* Restore real dragstarty value! */
+ data->dragstarty = data->dragstartx;
+
+ /* Used to detect switch to/from autosize mode. */
+ data->draglastvalue = *size;
+
+ data->dragchange = true;
+ data->applied = data->applied_interactive = true;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(data->region);
+ }
+ }
+ }
+ }
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ return retval;
+}
static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
@@ -3466,31 +3585,6 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_BREAK;
}
}
- else if (but->type == COLOR) {
- if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
- float *hsv = ui_block_hsv_get(but->block);
- float col[3];
-
- ui_get_but_vectorf(but, col);
- rgb_to_hsv_compat_v(col, hsv);
-
- if (event->type == WHEELDOWNMOUSE)
- hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
- else if (event->type == WHEELUPMOUSE)
- hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
- else {
- float fac = 0.005 * (event->y - event->prevy);
- hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
- }
-
- hsv_to_rgb_v(hsv, data->vec);
- ui_set_but_vectorf(but, data->vec);
-
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- ui_apply_button(C, but->block, but, data, true);
- return WM_UI_HANDLER_BREAK;
- }
- }
}
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
@@ -3578,6 +3672,41 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx,
return changed;
}
+static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ float *hsv = ui_block_hsv_get(but->block);
+ float col[3];
+
+ ui_get_but_vectorf(but, col);
+ rgb_to_hsv_compat_v(col, hsv);
+
+ if (event->type == WHEELDOWNMOUSE)
+ hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
+ else if (event->type == WHEELUPMOUSE)
+ hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ else {
+ float fac = 0.005 * (event->y - event->prevy);
+ hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
+ }
+
+ hsv_to_rgb_v(hsv, data->vec);
+ ui_set_but_vectorf(but, data->vec);
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_apply_button(C, but->block, but, data, true);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -3875,9 +4004,11 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == MOUSEMOVE) {
if (mx != data->draglastx || my != data->draglasty) {
@@ -4086,9 +4217,11 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
/* XXX hardcoded keymap check.... */
else if (event->type == WHEELDOWNMOUSE) {
@@ -4531,9 +4664,11 @@ static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandle
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == MOUSEMOVE) {
if (mx != data->draglastx || my != data->draglasty) {
@@ -4614,9 +4749,11 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == MOUSEMOVE) {
if (mx != data->draglastx || my != data->draglasty) {
@@ -4681,9 +4818,11 @@ static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHand
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == MOUSEMOVE) {
if (mx != data->draglastx || my != data->draglasty) {
@@ -4792,9 +4931,11 @@ static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHan
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == ESCKEY) {
- data->cancel = true;
- data->escapecancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
}
else if (event->type == MOUSEMOVE) {
if (mx != data->draglastx || my != data->draglasty) {
@@ -4967,7 +5108,12 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
if (but->rnapoin.data && but->rnaprop) {
- bool is_anim = RNA_property_animateable(&but->rnapoin, but->rnaprop);
+ PointerRNA *ptr = &but->rnapoin;
+ PropertyRNA *prop = but->rnaprop;
+ bool is_anim = RNA_property_animateable(ptr, prop);
+ bool is_editable = RNA_property_editable(ptr, prop);
+ /*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);
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
@@ -5114,6 +5260,10 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
ICON_NONE, "UI_OT_reset_default_button", "all", 1);
}
+ if (is_editable /*&& is_idprop*/ && is_set) {
+ uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"),
+ ICON_NONE, "UI_OT_unset_property_button");
+ }
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
ICON_NONE, "UI_OT_copy_data_path_button");
@@ -5161,13 +5311,12 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
/* Show header tools for header buttons. */
- if (CTX_wm_region(C)) {
+ {
ARegion *ar = CTX_wm_region(C);
- if (ar->regiontype == RGN_TYPE_HEADER) {
-
- uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
- uiItemS(layout);
- }
+ if (ar && (ar->regiontype == RGN_TYPE_HEADER)) {
+ uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
+ uiItemS(layout);
+ }
}
{ /* Docs */
@@ -5256,6 +5405,28 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
else if (event->type == EVT_DROP) {
ui_but_drop(C, event, but, data);
}
+ /* handle eyedropper */
+ else if ((event->type == EKEY) && (event->val == KM_PRESS)) {
+ if (event->alt || event->shift || event->ctrl || event->oskey) {
+ /* pass */
+ }
+ else {
+ if (but->type == COLOR) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, NULL);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else if (but->type == SEARCH_MENU_UNLINK) {
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_POINTER) {
+ StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ const short idcode = RNA_type_to_ID_code(type);
+ if ((idcode == ID_OB) || OB_DATA_SUPPORT_ID(idcode)) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ }
+ }
+ }
/* handle keyframing */
else if ((event->type == IKEY) &&
!ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) &&
@@ -5273,7 +5444,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
ui_but_anim_insert_keyframe(C);
}
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(data->region);
return WM_UI_HANDLER_BREAK;
}
@@ -5287,7 +5458,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
else
ui_but_anim_add_driver(C);
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(data->region);
return WM_UI_HANDLER_BREAK;
}
@@ -5301,17 +5472,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
else
ui_but_anim_add_keyingset(C);
- ED_region_tag_redraw(CTX_wm_region(C));
+ ED_region_tag_redraw(data->region);
return WM_UI_HANDLER_BREAK;
}
- /* reset to default */
- /* XXX hardcoded keymap check.... */
- else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) {
- /* ctrl+backspace = reset active button; backspace = reset a whole array*/
- if (!(ELEM3(but->type, HSVCIRCLE, HSVCUBE, HISTOGRAM)))
- ui_set_but_default(C, !event->ctrl);
- }
/* handle menu */
else if (event->type == RIGHTMOUSE && event->val == KM_PRESS) {
/* RMB has two options now */
@@ -5367,8 +5531,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case NUMSLI:
retval = ui_do_but_SLI(C, block, but, data, event);
break;
- case ROUNDBOX:
case LISTBOX:
+ retval = ui_do_but_LISTBOX(C, block, but, data, event);
+ break;
+ case ROUNDBOX:
case LABEL:
case LISTLABEL:
case ROW:
@@ -5406,7 +5572,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if (but->a1 == UI_GRAD_V_ALT) /* signal to prevent calling up color picker */
retval = ui_do_but_EXIT(C, but, data, event);
else
- retval = ui_do_but_BLOCK(C, but, data, event);
+ retval = ui_do_but_COLOR(C, but, data, event);
break;
case BUT_NORMAL:
retval = ui_do_but_NORMAL(C, block, but, data, event);
@@ -5436,7 +5602,22 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case BUT_EXTRA:
break;
}
-
+
+
+ /* reset to default (generic function, only use if not handled by switch above) */
+ /* XXX hardcoded keymap check.... */
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if ((retval == WM_UI_HANDLER_CONTINUE) &&
+ (event->type == BACKSPACEKEY && event->val == KM_PRESS))
+ {
+ /* ctrl+backspace = reset active button; backspace = reset a whole array*/
+ ui_set_but_default(C, !event->ctrl);
+ ED_region_tag_redraw(data->region);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
+
+
return retval;
}
@@ -5622,8 +5803,6 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
uiBut *but;
int mx, my;
-// if (!win->active)
-// return NULL;
if (!ui_mouse_inside_region(ar, x, y))
return NULL;
@@ -5768,7 +5947,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
WM_cursor_grab_disable(data->window, NULL);
}
#else
- WM_cursor_grab_disable(data->window, );
+ WM_cursor_grab_disable(data->window, NULL);
#endif
}
}
@@ -6423,90 +6602,166 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
{
- uiBut *but = ui_list_find_mouse_over(ar, event->x, event->y);
+ uiBut *but, *dragbut;
+ uiList *ui_list;
+ uiListDyn *dyn_data;
int retval = WM_UI_HANDLER_CONTINUE;
int type = event->type, val = event->val;
+ int mx, my;
+ bool is_over_dragbut = false;
- if (but) {
- uiList *ui_list = but->custom_data;
+ but = ui_list_find_mouse_over(ar, event->x, event->y);
+ if (!but) {
+ return retval;
+ }
- if (ui_list) {
-
- /* convert pan to scrollwheel */
- if (type == MOUSEPAN) {
- ui_pan_to_scroll(event, &type, &val);
-
- /* if type still is mousepan, we call it handled, since delta-y accumulate */
- /* also see wm_event_system.c do_wheel_ui hack */
- if (type == MOUSEPAN)
- retval = WM_UI_HANDLER_BREAK;
- }
-
- if (val == KM_PRESS) {
-
- if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
- ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
- {
- const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop);
- int value, min, max;
+ ui_list = but->custom_data;
+ if (!ui_list || !ui_list->dyn_data) {
+ return retval;
+ }
+ dyn_data = ui_list->dyn_data;
+
+ mx = event->x;
+ my = event->y;
+ ui_window_to_block(ar, but->block, &mx, &my);
- /* activate up/down the list */
- value = value_orig;
+ /* Find our "dragging" button. */
+ for (dragbut = but->block->buttons.first; dragbut; dragbut = dragbut->next) {
+ if (dragbut->poin == (void *)ui_list) {
+ break;
+ }
+ }
+ if (dragbut && dragbut == ui_but_find_mouse_over(ar, event->x, event->y)) {
+ is_over_dragbut = true;
+ }
- if (ELEM(type, UPARROWKEY, WHEELUPMOUSE))
- value--;
- else
- value++;
+ if (is_over_dragbut && type == LEFTMOUSE && val == KM_PRESS) {
+ uiHandleButtonData *data;
+ int *size = (int *)but->poin;
- CLAMP(value, 0, ui_list->list_last_len - 1);
+ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE);
+ button_activate_state(C, but, BUTTON_STATE_INIT);
- if (value < ui_list->list_scroll)
- ui_list->list_scroll = value;
- else if (value >= ui_list->list_scroll + ui_list->list_size)
- ui_list->list_scroll = value - ui_list->list_size + 1;
+ data = but->active;
+ data->dragstarty = my;
+
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ /* Again, have to override values set by ui_numedit_begin, because our listbox button also has a rnapoin... */
+ *size = data->origvalue = (double)dyn_data->visual_height;
+ ui_list->flag |= UILST_RESIZING;
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else {
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+
+ /* if type still is mousepan, we call it handled, since delta-y accumulate */
+ /* also see wm_event_system.c do_wheel_ui hack */
+ if (type == MOUSEPAN)
+ retval = WM_UI_HANDLER_BREAK;
+ }
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
- value = CLAMPIS(value, min, max);
+ if (val == KM_PRESS) {
+ if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
+ ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+ {
+ const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ int value, min, max, inc;
- if (value != value_orig) {
- RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ /* activate up/down the list */
+ value = value_orig;
+ if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) {
+ inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? 1 : -1;
+ }
+ else {
+ inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1;
+ }
- ui_apply_undo(but);
- ED_region_tag_redraw(ar);
+ if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) {
+ /* If we have a display order different from collection order, we have some work! */
+ int *org_order = MEM_mallocN(dyn_data->items_shown * sizeof(int), AT);
+ int *new_order = dyn_data->items_filter_neworder;
+ int i, org_idx = -1, len = dyn_data->items_len;
+ int current_idx = -1;
+ int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+
+ for (i = 0; i < len; i++) {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))
+ {
+ org_order[new_order ? new_order[++org_idx] : ++org_idx] = i;
+ if (i == value) {
+ current_idx = new_order ? new_order[org_idx] : org_idx;
+ }
+ }
+ else if (i == value && org_idx >= 0) {
+ current_idx = -(new_order ? new_order[org_idx] : org_idx) - 1;
+ }
+ }
+ /* Now, org_order maps displayed indices to real indices,
+ * and current_idx either contains the displayed index of active value (positive),
+ * or its more-nearest one (negated).
+ */
+ if (current_idx < 0) {
+ current_idx = (current_idx * -1) + (inc < 0 ? inc : inc - 1);
}
+ else {
+ current_idx += inc;
+ }
+ CLAMP(current_idx, 0, dyn_data->items_shown - 1);
+ value = org_order[current_idx];
+ MEM_freeN(org_order);
+ }
+ else {
+ value += inc;
+ }
- retval = WM_UI_HANDLER_BREAK;
+ CLAMP(value, 0, dyn_data->items_len - 1);
+
+ RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+ CLAMP(value, min, max);
+
+ if (value != value_orig) {
+ RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+
+ ui_apply_undo(but);
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(ar);
}
- else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
- /* silly replacement for proper grip */
- if (ui_list->list_grip_size == 0)
- ui_list->list_grip_size = ui_list->list_size;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+ /* We now have proper grip, but keep this anyway! */
+ if (ui_list->list_grip == 0)
+ ui_list->list_grip = dyn_data->visual_height;
+ /* list template will clamp */
+ if (type == WHEELUPMOUSE)
+ ui_list->list_grip--;
+ else
+ ui_list->list_grip++;
+
+ ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
+ ED_region_tag_redraw(ar);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ if (dyn_data->height > dyn_data->visual_height) {
+ /* list template will clamp */
if (type == WHEELUPMOUSE)
- ui_list->list_grip_size--;
+ ui_list->list_scroll--;
else
- ui_list->list_grip_size++;
-
- ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1);
+ ui_list->list_scroll++;
ED_region_tag_redraw(ar);
retval = WM_UI_HANDLER_BREAK;
}
- else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
- if (ui_list->list_last_len > ui_list->list_size) {
- /* list template will clamp */
- if (type == WHEELUPMOUSE)
- ui_list->list_scroll--;
- else
- ui_list->list_scroll++;
-
- ED_region_tag_redraw(ar);
-
- retval = WM_UI_HANDLER_BREAK;
- }
- }
}
}
}
@@ -7511,6 +7766,8 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
}
else if (temp.cancel_func)
temp.cancel_func(C, temp.popup_arg);
+
+ WM_event_add_mousemove(C);
}
else {
/* re-enable tooltips */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index d2a8c47b347..9cc16d82810 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -393,7 +393,7 @@ extern bool ui_set_but_string(struct bContext *C, uiBut *but, const char *str);
extern bool ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value);
extern int ui_get_but_string_max_length(uiBut *but);
-extern void ui_set_but_default(struct bContext *C, short all);
+extern void ui_set_but_default(struct bContext *C, const bool all);
extern void ui_check_but(uiBut *but);
extern bool ui_is_but_float(uiBut *but);
@@ -538,7 +538,7 @@ extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *s
struct ThemeUI;
void ui_widget_color_init(struct ThemeUI *tui);
-void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
+void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep);
void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
extern const unsigned char checker_stipple_sml[32 * 32 / 8];
@@ -584,4 +584,8 @@ int ui_but_anim_expression_set(uiBut *but, const char *str);
int ui_but_anim_expression_create(uiBut *but, const char *str);
void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra);
-#endif
+/* interface_eyedropper.c */
+void UI_OT_eyedropper_color(struct wmOperatorType *ot);
+void UI_OT_eyedropper_id(struct wmOperatorType *ot);
+
+#endif /* __INTERFACE_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 079ba97aa9d..424d2231a03 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -471,6 +471,8 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in
but->type = NUMSLI;
if (toggle && but->type == OPTION)
but->type = TOG;
+ if ((a == 0) && (subtype == PROP_AXISANGLE))
+ uiButSetUnitType(but, PROP_UNIT_ROTATION);
}
if (boolarr) {
@@ -568,7 +570,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n
PropertySubType subtype;
int labelw;
- sub = uiLayoutRow(layout, FALSE);
+ sub = uiLayoutRow(layout, layout->align);
uiBlockSetCurLayout(block, sub);
if (name[0]) {
@@ -1465,6 +1467,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
uiBlock *block;
StructRNA *icontype;
int w, h;
+ char namestr[UI_MAX_NAME_STR];
/* validate arguments */
prop = RNA_struct_find_property(ptr, propname);
@@ -1507,6 +1510,8 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
if (!name)
name = RNA_property_ui_name(prop);
+ name = ui_item_name_add_colon(name, namestr);
+
/* create button */
block = uiLayoutGetBlock(layout);
@@ -2429,6 +2434,15 @@ uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, Pr
but->rnapoin = *actptr;
but->rnaprop = actprop;
+ /* Resizing data. */
+ /* Note: we can't use usual "num button" value handling, as it only tries rnapoin when it is non-NULL... :/
+ * So just setting but->poin, not but->pointype.
+ */
+ but->poin = (void *)&ui_list->list_grip;
+ but->hardmin = but->softmin = 0.0f;
+ but->hardmax = but->softmax = 1000.0f; /* Should be more than enough! */
+ but->a1 = 0.0f;
+
/* only for the undo string */
if (but->flag & UI_BUT_UNDO) {
but->tip = RNA_property_description(actprop);
@@ -2678,8 +2692,9 @@ static void ui_item_align(uiLayout *litem, short nr)
BLI_remlink(&litem->root->block->buttons, box->roundbox);
BLI_addhead(&litem->root->block->buttons, box->roundbox);
}
- else
+ else if (((uiLayout *)item)->align) {
ui_item_align((uiLayout *)item, nr);
+ }
}
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index cfe6e313c58..36e965e13d2 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -27,20 +27,14 @@
* \ingroup edinterface
*/
-#include <stdio.h>
-#include <math.h>
#include <string.h>
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
#include "BLI_blenlib.h"
-#include "BLI_math_color.h"
-#include "BLI_math_vector.h"
-#include "BLI_utildefines.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -54,12 +48,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BIF_gl.h"
-
#include "UI_interface.h"
-#include "IMB_colormanagement.h"
-
#include "interface_intern.h"
#include "WM_api.h"
@@ -70,282 +60,6 @@
#include "BKE_main.h"
#include "BLI_ghash.h"
-#include "ED_image.h" /* for HDR color sampling */
-#include "ED_node.h" /* for HDR color sampling */
-#include "ED_clip.h" /* for HDR color sampling */
-
-/* ********************************************************** */
-
-typedef struct Eyedropper {
- struct ColorManagedDisplay *display;
-
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
-
- int accum_start; /* has mouse been presed */
- float accum_col[3];
- int accum_tot;
-} Eyedropper;
-
-static int eyedropper_init(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Eyedropper *eye;
-
- op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper");
-
- uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index);
-
- if ((eye->ptr.data == NULL) ||
- (eye->prop == NULL) ||
- (RNA_property_editable(&eye->ptr, eye->prop) == FALSE) ||
- (RNA_property_array_length(&eye->ptr, eye->prop) < 3) ||
- (RNA_property_type(eye->prop) != PROP_FLOAT))
- {
- return FALSE;
- }
-
- if (RNA_property_subtype(eye->prop) == PROP_COLOR) {
- const char *display_device;
-
- display_device = scene->display_settings.display_device;
- eye->display = IMB_colormanagement_display_get_named(display_device);
- }
-
- return TRUE;
-}
-
-static void eyedropper_exit(bContext *C, wmOperator *op)
-{
- WM_cursor_restore(CTX_wm_window(C));
-
- if (op->customdata)
- MEM_freeN(op->customdata);
- op->customdata = NULL;
-}
-
-static int eyedropper_cancel(bContext *C, wmOperator *op)
-{
- eyedropper_exit(C, op);
- return OPERATOR_CANCELLED;
-}
-
-/* *** eyedropper_color_ helper functions *** */
-
-/**
- * \brief get the color from the screen.
- *
- * Special check for image or nodes where we MAY have HDR pixels which don't display.
- */
-static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3])
-{
-
- /* we could use some clever */
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
- if (sa->spacetype == SPACE_IMAGE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceImage *sima = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_image_color_sample(sima, ar, mval, r_col)) {
- return;
- }
- }
- }
- else if (sa->spacetype == SPACE_NODE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceNode *snode = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_node_color_sample(snode, ar, mval, r_col)) {
- return;
- }
- }
- }
- else if (sa->spacetype == SPACE_CLIP) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
- SpaceClip *sc = sa->spacedata.first;
- int mval[2] = {mx - ar->winrct.xmin,
- my - ar->winrct.ymin};
-
- if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
- return;
- }
- }
- }
- }
- }
-
- /* fallback to simple opengl picker */
- glReadBuffer(GL_FRONT);
- glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
- glReadBuffer(GL_BACK);
-}
-
-/* sets the sample color RGB, maintaining A */
-static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3])
-{
- float col_conv[4];
-
- /* to maintain alpha */
- RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
-
- /* convert from display space to linear rgb space */
- if (eye->display) {
- copy_v3_v3(col_conv, col);
- IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display);
- }
- else {
- copy_v3_v3(col_conv, col);
- }
-
- RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv);
-
- RNA_property_update(C, &eye->ptr, eye->prop);
-}
-
-/* set sample from accumulated values */
-static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye)
-{
- float col[3];
- mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot);
- eyedropper_color_set(C, eye, col);
-}
-
-/* single point sample & set */
-static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
-{
- float col[3];
- eyedropper_color_sample_fl(C, eye, mx, my, col);
- eyedropper_color_set(C, eye, col);
-}
-
-static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my)
-{
- float col[3];
- eyedropper_color_sample_fl(C, eye, mx, my, col);
- /* delay linear conversion */
- add_v3_v3(eye->accum_col, col);
- eye->accum_tot++;
-}
-
-/* main modal status check */
-static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Eyedropper *eye = (Eyedropper *)op->customdata;
-
- switch (event->type) {
- case ESCKEY:
- case RIGHTMOUSE:
- return eyedropper_cancel(C, op);
- case LEFTMOUSE:
- if (event->val == KM_RELEASE) {
- if (eye->accum_tot == 0) {
- eyedropper_color_sample(C, eye, event->x, event->y);
- }
- else {
- eyedropper_color_set_accum(C, eye);
- }
- eyedropper_exit(C, op);
- return OPERATOR_FINISHED;
- }
- else if (event->val == KM_PRESS) {
- /* enable accum and make first sample */
- eye->accum_start = TRUE;
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- }
- break;
- case MOUSEMOVE:
- if (eye->accum_start) {
- /* button is pressed so keep sampling */
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- eyedropper_color_set_accum(C, eye);
- }
- break;
- case SPACEKEY:
- if (event->val == KM_RELEASE) {
- eye->accum_tot = 0;
- zero_v3(eye->accum_col);
- eyedropper_color_sample_accum(C, eye, event->x, event->y);
- eyedropper_color_set_accum(C, eye);
- }
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-/* Modal Operator init */
-static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- /* init */
- if (eyedropper_init(C, op)) {
- WM_cursor_modal(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
-
- /* add temp handler */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
- }
- else {
- eyedropper_exit(C, op);
- return OPERATOR_CANCELLED;
- }
-}
-
-/* Repeat operator */
-static int eyedropper_exec(bContext *C, wmOperator *op)
-{
- /* init */
- if (eyedropper_init(C, op)) {
-
- /* do something */
-
- /* cleanup */
- eyedropper_exit(C, op);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
-}
-
-static int eyedropper_poll(bContext *C)
-{
- if (!CTX_wm_window(C)) return 0;
- else return 1;
-}
-
-static void UI_OT_eyedropper(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Eyedropper";
- ot->idname = "UI_OT_eyedropper";
- ot->description = "Sample a color from the Blender Window to store in a property";
-
- /* api callbacks */
- ot->invoke = eyedropper_invoke;
- ot->modal = eyedropper_modal;
- ot->cancel = eyedropper_cancel;
- ot->exec = eyedropper_exec;
- ot->poll = eyedropper_poll;
-
- /* flags */
- ot->flag = OPTYPE_BLOCKING;
-
- /* properties */
-}
-
/* Reset Default Theme ------------------------ */
static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
@@ -434,6 +148,28 @@ static void UI_OT_copy_data_path_button(wmOperatorType *ot)
/* Reset to Default Values Button Operator ------------------------ */
+static int operator_button_property_finish(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
+{
+ ID *id = ptr->id.data;
+
+ /* perform updates required for this property */
+ RNA_property_update(C, ptr, prop);
+
+ /* as if we pressed the button */
+ uiContextActivePropertyHandle(C);
+
+ /* Since we don't want to undo _all_ edits to settings, eg window
+ * edits on the screen or on operator settings.
+ * it might be better to move undo's inline - campbell */
+ if (id && ID_CHECK_UNDO(id)) {
+ /* do nothing, go ahead with undo */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
static int reset_default_button_poll(bContext *C)
{
PointerRNA ptr;
@@ -449,7 +185,6 @@ static int reset_default_button_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr;
PropertyRNA *prop;
- int success = 0;
int index, all = RNA_boolean_get(op->ptr, "all");
/* try to reset the nominated setting to its default value */
@@ -457,32 +192,11 @@ static int reset_default_button_exec(bContext *C, wmOperator *op)
/* if there is a valid property that is editable... */
if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
- if (RNA_property_reset(&ptr, prop, (all) ? -1 : index)) {
- /* perform updates required for this property */
- RNA_property_update(C, &ptr, prop);
-
- /* as if we pressed the button */
- uiContextActivePropertyHandle(C);
-
- success = 1;
- }
+ if (RNA_property_reset(&ptr, prop, (all) ? -1 : index))
+ return operator_button_property_finish(C, &ptr, prop);
}
- /* Since we don't want to undo _all_ edits to settings, eg window
- * edits on the screen or on operator settings.
- * it might be better to move undo's inline - campbell */
- if (success) {
- ID *id = ptr.id.data;
- if (id && ID_CHECK_UNDO(id)) {
- /* do nothing, go ahead with undo */
- }
- else {
- return OPERATOR_CANCELLED;
- }
- }
- /* end hack */
-
- return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static void UI_OT_reset_default_button(wmOperatorType *ot)
@@ -503,6 +217,43 @@ static void UI_OT_reset_default_button(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
}
+/* Unset Property Button Operator ------------------------ */
+
+static int unset_property_button_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ /* try to unset the nominated property */
+ uiContextActiveProperty(C, &ptr, &prop, &index);
+
+ /* if there is a valid property that is editable... */
+ if (ptr.data && prop && RNA_property_editable(&ptr, prop)
+ /*&& RNA_property_is_idprop(prop)*/ && RNA_property_is_set(&ptr, prop))
+ {
+ RNA_property_unset(&ptr, prop);
+ return operator_button_property_finish(C, &ptr, prop);
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+static void UI_OT_unset_property_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unset property";
+ ot->idname = "UI_OT_unset_property_button";
+ ot->description = "Clear the property and use default or generated value in operators";
+
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = unset_property_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
/* Copy To Selected Operator ------------------------ */
static int copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb, int *use_path)
@@ -1077,10 +828,10 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
void UI_buttons_operatortypes(void)
{
- WM_operatortype_append(UI_OT_eyedropper);
WM_operatortype_append(UI_OT_reset_default_theme);
WM_operatortype_append(UI_OT_copy_data_path_button);
WM_operatortype_append(UI_OT_reset_default_button);
+ WM_operatortype_append(UI_OT_unset_property_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
@@ -1089,4 +840,8 @@ void UI_buttons_operatortypes(void)
WM_operatortype_append(UI_OT_edittranslation_init);
#endif
WM_operatortype_append(UI_OT_reloadtranslation);
+
+ /* external */
+ WM_operatortype_append(UI_OT_eyedropper_color);
+ WM_operatortype_append(UI_OT_eyedropper_id);
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 95f47be0b70..15fbd51c6fc 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -196,7 +196,7 @@ static MenuData *decompose_menu_string(const char *str)
s++;
}
}
- else if (c == '|' || c == '\n' || c == '\0') {
+ else if (c == UI_SEP_CHAR || c == '\n' || c == '\0') {
if (nitem) {
*s = '\0';
@@ -770,6 +770,7 @@ typedef struct uiSearchboxData {
int active; /* index in items array */
bool noback; /* when menu opened with enough space for this */
bool preview; /* draw thumbnail previews, rather than list */
+ bool use_sep; /* use the UI_SEP_CHAR char for splitting shortcuts (good for operators, bad for data) */
int prv_rows, prv_cols;
} uiSearchboxData;
@@ -928,7 +929,7 @@ bool ui_searchbox_apply(uiBut *but, ARegion *ar)
if (data->active != -1) {
const char *name = data->items.names[data->active];
- const char *name_sep = strchr(name, '|');
+ const char *name_sep = data->use_sep ? strchr(name, UI_SEP_CHAR) : NULL;
BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen);
@@ -1034,7 +1035,7 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, const bool reset)
for (a = 0; a < data->items.totitem; a++) {
const char *name = data->items.names[a];
- const char *name_sep = strchr(name, '|');
+ const char *name_sep = data->use_sep ? strchr(name, UI_SEP_CHAR) : NULL;
if (STREQLEN(but->editstr, name, name_sep ? (name_sep - name) : data->items.maxstrlen)) {
data->active = a;
break;
@@ -1087,10 +1088,14 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
- if (data->preview)
- ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a == data->active) ? UI_ACTIVE : 0);
- else
- ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a == data->active) ? UI_ACTIVE : 0);
+ if (data->preview) {
+ ui_draw_preview_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a],
+ (a == data->active) ? UI_ACTIVE : 0);
+ }
+ else {
+ ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a],
+ (a == data->active) ? UI_ACTIVE : 0, data->use_sep);
+ }
}
/* indicate more */
@@ -1114,7 +1119,8 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
- ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a == data->active) ? UI_ACTIVE : 0);
+ ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a],
+ (a == data->active) ? UI_ACTIVE : 0, data->use_sep);
}
/* indicate more */
@@ -1194,6 +1200,11 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
data->prv_rows = but->a1;
data->prv_cols = but->a2;
}
+
+ /* only show key shortcuts when needed (not rna buttons) [#36699] */
+ if (but->rnaprop == NULL) {
+ data->use_sep = true;
+ }
/* compute position */
if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
@@ -2174,7 +2185,7 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
yco = -3.0f * UI_UNIT_Y;
if (show_picker) {
- bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
+ bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
uiButSetFunc(bt, close_popup_cb, bt, NULL);
}
@@ -2301,11 +2312,11 @@ static int ui_popup_string_hash(const char *str)
{
/* sometimes button contains hotkey, sometimes not, strip for proper compare */
int hash;
- char *delimit = strchr(str, '|');
+ char *delimit = strchr(str, UI_SEP_CHAR);
- if (delimit) *delimit = 0;
+ if (delimit) *delimit = '\0';
hash = BLI_ghashutil_strhash(str);
- if (delimit) *delimit = '|';
+ if (delimit) *delimit = UI_SEP_CHAR;
return hash;
}
@@ -2605,12 +2616,10 @@ static void confirm_cancel_operator(bContext *UNUSED(C), void *opv)
WM_operator_free(opv);
}
-static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 4, 0)))
-#endif
-;
-static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap)
+static void vconfirm_opname(bContext *C, const char *opname, const char *title,
+ const char *itemfmt, va_list ap) ATTR_PRINTF_FORMAT(4, 0);
+static void vconfirm_opname(bContext *C, const char *opname, const char *title,
+ const char *itemfmt, va_list ap)
{
uiPopupBlockHandle *handle;
char *s, buf[512];
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 61cc021800e..6b6b7114c84 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1,4 +1,5 @@
/*
+
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -43,6 +44,7 @@
#include "BLI_rect.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_fnmatch.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -1017,6 +1019,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
Scene *scene = CTX_data_scene(C);
Object *ob;
ModifierData *md, *vmd;
+ VirtualModifierData virtualModifierData;
int i, lastCageIndex, cageIndex;
/* verify we have valid data */
@@ -1039,7 +1042,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
/* XXX virtual modifiers are not accesible for python */
- vmd = modifiers_getVirtualModifierList(ob);
+ vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
for (i = 0; vmd; i++, vmd = vmd->next) {
if (md == vmd)
@@ -1145,9 +1148,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
uiBlockSetEmboss(block, UI_EMBOSSN);
uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
uiBlockSetEmboss(block, UI_EMBOSS);
-
+
/* name */
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco + 0.5f*UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f*UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr,
+ xco + 0.5f * UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f * UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "");
if (con->flag & CONSTRAINT_DISABLE)
uiLayoutSetRedAlert(row, TRUE);
@@ -2468,7 +2472,7 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout,
struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
- int UNUSED(index))
+ int UNUSED(index), int UNUSED(flt_flag))
{
char *namebuf;
const char *name;
@@ -2494,30 +2498,245 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN
}
}
+static void uilist_draw_filter_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout)
+{
+ PointerRNA listptr;
+ uiLayout *row, *subrow;
+
+ RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr);
+
+ row = uiLayoutRow(layout, FALSE);
+
+ subrow = uiLayoutRow(row, TRUE);
+ uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE);
+ uiItemR(subrow, &listptr, "use_filter_invert", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "",
+ (ui_list->filter_flag & UILST_FLT_EXCLUDE) ? ICON_ZOOM_OUT : ICON_ZOOM_IN);
+
+ subrow = uiLayoutRow(row, TRUE);
+ uiItemR(subrow, &listptr, "use_filter_sort_alpha", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ uiItemR(subrow, &listptr, "use_filter_sort_reverse", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "",
+ (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_TRIA_UP : ICON_TRIA_DOWN);
+}
+
+typedef struct {
+ char name[MAX_IDPROP_NAME];
+ int org_idx;
+} StringCmp;
+
+static int cmpstringp(const void *p1, const void *p2)
+{
+ /* Case-insensitive comparison. */
+ return BLI_strcasecmp(((StringCmp *) p1)->name, ((StringCmp *) p2)->name);
+}
+
+static void uilist_filter_items_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct PointerRNA *dataptr,
+ const char *propname)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ PropertyRNA *prop = RNA_struct_find_property(dataptr, propname);
+
+ const char *filter_raw = ui_list->filter_byname;
+ char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL;
+ bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0;
+ bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_ALPHA) != 0;
+ int len = RNA_property_collection_length(dataptr, prop);
+
+ dyn_data->items_shown = dyn_data->items_len = len;
+
+ if (len && (order_by_name || filter_raw[0])) {
+ StringCmp *names = NULL;
+ int order_idx = 0, i = 0;
+
+ if (order_by_name) {
+ names = MEM_callocN(sizeof(StringCmp) * len, AT);
+ }
+ if (filter_raw[0]) {
+ size_t idx = 0, slen = strlen(filter_raw);
+
+ dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, AT);
+ dyn_data->items_shown = 0;
+
+ /* Implicitly add heading/trailing wildcards if needed. */
+ if (len + 3 <= 32) {
+ filter = filter_buff;
+ }
+ else {
+ filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), AT);
+ }
+ if (filter_raw[idx] != '*') {
+ filter[idx++] = '*';
+ }
+ memcpy(filter + idx, filter_raw, slen);
+ idx += slen;
+ if (filter[idx - 1] != '*') {
+ filter[idx++] = '*';
+ }
+ filter[idx] = '\0';
+ }
+
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ char *namebuf;
+ const char *name;
+ bool do_order = false;
+
+ namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
+ name = namebuf ? namebuf : "";
+
+ if (filter[0]) {
+ /* Case-insensitive! */
+ if (fnmatch(filter, name, FNM_CASEFOLD) == 0) {
+ dyn_data->items_filter_flags[i] = UILST_FLT_ITEM;
+ if (!filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ //printf("%s: '%s' matches '%s'\n", __func__, name, filter);
+ }
+ else if (filter_exclude) {
+ dyn_data->items_shown++;
+ do_order = order_by_name;
+ }
+ }
+ else {
+ do_order = order_by_name;
+ }
+
+ if (do_order) {
+ names[order_idx].org_idx = order_idx;
+ BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME);
+ }
+
+ /* free name */
+ if (namebuf) {
+ MEM_freeN(namebuf);
+ }
+ i++;
+ }
+ RNA_PROP_END;
+
+ if (order_by_name) {
+ int new_idx;
+ /* note: order_idx equals either to ui_list->items_len if no filtering done,
+ * or to ui_list->items_shown if filter is enabled,
+ * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded.
+ * This way, we only sort items we actually intend to draw!
+ */
+ qsort(names, order_idx, sizeof(StringCmp), cmpstringp);
+
+ dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx, AT);
+ for (new_idx = 0; new_idx < order_idx; new_idx++) {
+ dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx;
+ }
+ }
+
+ if (filter_dyn) {
+ MEM_freeN(filter_dyn);
+ }
+ if (names) {
+ MEM_freeN(names);
+ }
+ }
+}
+
+typedef struct {
+ PointerRNA item;
+ int org_idx;
+ int flt_flag;
+} _uilist_item;
+
+typedef struct {
+ int visual_items; /* Visual number of items (i.e. number of items we have room to display). */
+ int start_idx; /* Index of first item to display. */
+ int end_idx; /* Index of last item to display + 1. */
+} uiListLayoutdata;
+
+static void prepare_list(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns,
+ uiListLayoutdata *layoutdata)
+{
+ uiListDyn *dyn_data = ui_list->dyn_data;
+ int activei_row, max_scroll;
+
+ /* default rows */
+ if (rows == 0)
+ rows = 5;
+ dyn_data->visual_height_min = rows;
+ if (maxrows == 0)
+ maxrows = 5;
+ if (columns == 0)
+ columns = 9;
+
+ if (ui_list->list_grip >= rows) {
+ maxrows = rows = ui_list->list_grip;
+ }
+ else {
+ ui_list->list_grip = 0; /* Reset to auto-size mode. */
+ /* Prevent auto-size mode to take effect while grab-resizing! */
+ if (ui_list->flag & UILST_RESIZING) {
+ maxrows = rows;
+ }
+ }
+
+ if (columns > 1) {
+ dyn_data->height = (int)ceil((double)len / (double)columns);
+ activei_row = (int)floor((double)activei / (double)columns);
+ }
+ else {
+ dyn_data->height = len;
+ activei_row = activei;
+ }
+
+ /* Expand size if needed and possible. */
+ if ((ui_list->list_grip == 0) && (rows != maxrows) && (dyn_data->height > rows)) {
+ rows = min_ii(dyn_data->height, maxrows);
+ }
+
+ /* If list length changes or list is tagged to check this, and active is out of view, scroll to it .*/
+ if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) {
+ if (activei_row < ui_list->list_scroll) {
+ ui_list->list_scroll = activei_row;
+ }
+ else if (activei_row >= ui_list->list_scroll + rows) {
+ ui_list->list_scroll = activei_row - rows + 1;
+ }
+ ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM;
+ }
+
+ max_scroll = max_ii(0, dyn_data->height - rows);
+ CLAMP(ui_list->list_scroll, 0, max_scroll);
+ ui_list->list_last_len = len;
+ dyn_data->visual_height = rows;
+ layoutdata->visual_items = rows * columns;
+ layoutdata->start_idx = ui_list->list_scroll * columns;
+ layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
+}
+
void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type)
+ const char *active_propname, int rows, int maxrows, int layout_type, int columns)
{
uiListType *ui_list_type;
uiList *ui_list = NULL;
+ uiListDyn *dyn_data;
ARegion *ar;
uiListDrawItemFunc draw_item;
+ uiListDrawFilterFunc draw_filter;
+ uiListFilterItemsFunc filter_items;
PropertyRNA *prop = NULL, *activeprop;
PropertyType type, activetype;
+ _uilist_item *items_ptr = NULL;
StructRNA *ptype;
- uiLayout *box, *row, *col, *sub, *overlap;
+ uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap;
uiBlock *block, *subblock;
uiBut *but;
+ uiListLayoutdata layoutdata;
char ui_list_id[UI_MAX_NAME_STR];
char numstr[32];
int rnaicon = ICON_NONE, icon = ICON_NONE;
int i = 0, activei = 0;
int len = 0;
- int items;
- int found;
- int min, max;
/* validate arguments */
/* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */
@@ -2580,6 +2799,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
}
draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
+ draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : uilist_draw_filter_default;
+ filter_items = ui_list_type->filter_items ? ui_list_type->filter_items : uilist_filter_items_default;
/* Find or add the uiList to the current Region. */
/* We tag the list id with the list type... */
@@ -2589,146 +2810,211 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id));
if (!ui_list) {
- ui_list = MEM_callocN(sizeof(uiList), __func__);
+ ui_list = MEM_callocN(sizeof(uiList), AT);
BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
BLI_addtail(&ar->ui_lists, ui_list);
}
+ if (!ui_list->dyn_data) {
+ ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), AT);
+ }
+ dyn_data = ui_list->dyn_data;
+
/* Because we can't actually pass type across save&load... */
ui_list->type = ui_list_type;
ui_list->layout_type = layout_type;
+ /* Reset filtering data. */
+ if (dyn_data->items_filter_flags) {
+ MEM_freeN(dyn_data->items_filter_flags);
+ dyn_data->items_filter_flags = NULL;
+ }
+ if (dyn_data->items_filter_neworder) {
+ MEM_freeN(dyn_data->items_filter_neworder);
+ dyn_data->items_filter_neworder = NULL;
+ }
+ dyn_data->items_len = dyn_data->items_shown = -1;
+
+ /* Filter list items! (not for compact layout, though) */
+ if (dataptr->data && prop) {
+ int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+ bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0;
+ int items_shown, idx = 0;
+#if 0
+ int prev_ii = -1, prev_i;
+#endif
+
+ if (layout_type == UILST_LAYOUT_COMPACT) {
+ dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop);
+ }
+ else {
+ //printf("%s: filtering...\n", __func__);
+ filter_items(ui_list, C, dataptr, propname);
+ //printf("%s: filtering done.\n", __func__);
+ }
+
+ items_shown = dyn_data->items_shown;
+ if (items_shown >= 0) {
+ items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, AT);
+ //printf("%s: items shown: %d.\n", __func__, items_shown);
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ if (!dyn_data->items_filter_flags ||
+ ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude))
+ {
+ int ii;
+ if (dyn_data->items_filter_neworder) {
+ ii = dyn_data->items_filter_neworder[idx++];
+ ii = order_reverse ? items_shown - ii - 1 : ii;
+ }
+ else {
+ ii = order_reverse ? items_shown - ++idx : idx++;
+ }
+ //printf("%s: ii: %d\n", __func__, ii);
+ items_ptr[ii].item = itemptr;
+ items_ptr[ii].org_idx = i;
+ items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] : 0;
+
+ if (activei == i) {
+ activei = ii;
+ }
+# if 0 /* For now, do not alter active element, even if it will be hidden... */
+ else if (activei < i) {
+ /* We do not want an active but invisible item!
+ * Only exception is when all items are filtered out...
+ */
+ if (prev_ii >= 0) {
+ activei = prev_ii;
+ RNA_property_int_set(active_dataptr, activeprop, prev_i);
+ }
+ else {
+ activei = ii;
+ RNA_property_int_set(active_dataptr, activeprop, i);
+ }
+ }
+ prev_i = i;
+ prev_ii = ii;
+#endif
+ }
+ i++;
+ }
+ RNA_PROP_END;
+ }
+ if (dyn_data->items_shown >= 0) {
+ len = dyn_data->items_shown;
+ }
+ else {
+ len = dyn_data->items_len;
+ }
+ }
+
switch (layout_type) {
case UILST_LAYOUT_DEFAULT:
- /* default rows */
- if (rows == 0)
- rows = 5;
- if (maxrows == 0)
- maxrows = 5;
- if (ui_list->list_grip_size != 0)
- rows = ui_list->list_grip_size;
-
/* layout */
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- row = uiLayoutRow(box, FALSE);
+ glob = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(glob, FALSE);
col = uiLayoutColumn(row, TRUE);
/* init numbers */
- RNA_property_int_range(active_dataptr, activeprop, &min, &max);
-
- if (prop)
- len = RNA_property_collection_length(dataptr, prop);
- items = CLAMPIS(len, rows, MAX2(rows, maxrows));
-
- /* if list length changes and active is out of view, scroll to it */
- if ((ui_list->list_last_len != len) &&
- (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items))
- {
- ui_list->list_scroll = activei;
- }
-
- ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items);
- ui_list->list_scroll = max_ii(ui_list->list_scroll, 0);
- ui_list->list_size = items;
- ui_list->list_last_len = len;
+ prepare_list(ui_list, len, activei, rows, maxrows, 1, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) {
- subblock = uiLayoutGetBlock(col);
- overlap = uiLayoutOverlap(col);
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+ subblock = uiLayoutGetBlock(col);
- uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
+ overlap = uiLayoutOverlap(col);
+
+ uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, FALSE);
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, FALSE);
- but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, i, 0, 0, NULL);
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+ but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
- sub = uiLayoutRow(overlap, FALSE);
+ sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- if (icon == ICON_DOT)
- icon = ICON_NONE;
- draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
+ org_i, flt_flag);
- /* If we are "drawing" active item, set all labels as active. */
- if (i == activei) {
- ui_layout_list_set_labels_active(sub);
- }
- uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ /* If we are "drawing" active item, set all labels as active. */
+ if (i == activei) {
+ ui_layout_list_set_labels_active(sub);
}
- i++;
+
+ uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
}
- RNA_PROP_END;
}
/* add dummy buttons to fill space */
- while (i < ui_list->list_scroll + items) {
- if (i >= ui_list->list_scroll)
- uiItemL(col, "", ICON_NONE);
- i++;
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ uiItemL(col, "", ICON_NONE);
}
/* add scrollbar */
- if (len > items) {
+ if (len > layoutdata.visual_items) {
col = uiLayoutColumn(row, FALSE);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll,
- 0, len - items, items, 0, "");
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height, 0, "");
}
break;
case UILST_LAYOUT_COMPACT:
row = uiLayoutRow(layout, TRUE);
- if (dataptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
- found = (activei == i);
-
- if (found) {
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- if (icon == ICON_DOT)
- icon = ICON_NONE;
- draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
- }
+ if (dataptr->data && prop && dyn_data->items_shown > 0) {
+ PointerRNA *itemptr = &items_ptr[activei].item;
+ int org_i = items_ptr[activei].org_idx;
- i++;
- }
- RNA_PROP_END;
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0);
}
-
/* if list is empty, add in dummy button */
- if (i == 0)
+ else {
uiItemL(row, "", ICON_NONE);
+ }
/* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown);
but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
- if (i == 0)
+ if (dyn_data->items_shown == 0)
uiButSetFlag(but, UI_BUT_DISABLED);
break;
case UILST_LAYOUT_GRID:
box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
- col = uiLayoutColumn(box, TRUE);
- row = uiLayoutRow(col, FALSE);
+ glob = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(glob, FALSE);
+ col = uiLayoutColumn(row, TRUE);
+ subrow = NULL; /* Quite gcc warning! */
+
+ prepare_list(ui_list, len, activei, rows, maxrows, columns, &layoutdata);
if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (dataptr, itemptr, prop)
- {
+ for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) {
+ PointerRNA *itemptr = &items_ptr[i].item;
+ int org_i = items_ptr[i].org_idx;
+ int flt_flag = items_ptr[i].flt_flag;
+
/* create button */
- if (!(i % 9))
- row = uiLayoutRow(col, FALSE);
+ if (!(i % columns))
+ subrow = uiLayoutRow(col, FALSE);
- subblock = uiLayoutGetBlock(row);
- overlap = uiLayoutOverlap(row);
+ subblock = uiLayoutGetBlock(subrow);
+ overlap = uiLayoutOverlap(subrow);
uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM);
@@ -2736,13 +3022,14 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
sub = uiLayoutRow(overlap, FALSE);
but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
- active_dataptr, activeprop, 0, 0, i, 0, 0, NULL);
+ active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL);
uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
sub = uiLayoutRow(overlap, FALSE);
- icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false);
- draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false);
+ draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname,
+ org_i, flt_flag);
/* If we are "drawing" active item, set all labels as active. */
if (i == activei) {
@@ -2750,13 +3037,67 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co
}
uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM);
+ }
+ }
- i++;
+ /* add dummy buttons to fill space */
+ for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) {
+ if (!(i % columns)) {
+ subrow = uiLayoutRow(col, FALSE);
}
- RNA_PROP_END;
+ uiItemL(subrow, "", ICON_NONE);
+ }
+
+ /* add scrollbar */
+ if (len > layoutdata.visual_items) {
+ col = uiLayoutColumn(row, FALSE);
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height,
+ &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height,
+ dyn_data->visual_height, 0, "");
}
break;
}
+
+ if (glob) {
+ row = uiLayoutRow(glob, TRUE);
+ subblock = uiLayoutGetBlock(row);
+ uiBlockSetEmboss(subblock, UI_EMBOSSN);
+
+ if (ui_list->filter_flag & UILST_FLT_SHOW) {
+ but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_DOWN, 0, 0,
+ UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0,
+ TIP_("Hide filtering options"));
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list,
+ 0.0, 0.0, 0, -1, "");
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ uiBlockSetEmboss(subblock, UI_EMBOSS);
+
+ col = uiLayoutColumn(glob, FALSE);
+ subblock = uiLayoutGetBlock(col);
+ uiDefBut(subblock, SEPR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y * 0.05f, NULL, 0.0, 0.0, 0, 0, "");
+
+ draw_filter(ui_list, C, col);
+ }
+ else {
+ but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_RIGHT, 0, 0,
+ UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0,
+ TIP_("Show filtering options"));
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list,
+ 0.0, 0.0, 0, -1, "");
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
+
+ uiBlockSetEmboss(subblock, UI_EMBOSS);
+ }
+ }
+
+ if (items_ptr) {
+ MEM_freeN(items_ptr);
+ }
}
/************************* Operator Search Template **************************/
@@ -2792,7 +3133,7 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char
if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, true,
&name[len + 1], sizeof(name) - len - 1))
{
- name[len] = '|';
+ name[len] = UI_SEP_CHAR;
}
}
@@ -3003,7 +3344,7 @@ static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(
static void template_keymap_item_properties(uiLayout *layout, const char *title, PointerRNA *ptr)
{
- uiLayout *flow;
+ uiLayout *flow, *box, *row;
uiItemS(layout);
@@ -3015,6 +3356,8 @@ static void template_keymap_item_properties(uiLayout *layout, const char *title,
RNA_STRUCT_BEGIN (ptr, prop)
{
int flag = RNA_property_flag(prop);
+ bool is_set = RNA_property_is_set(ptr, prop);
+ uiBut *but;
if (flag & PROP_HIDDEN)
continue;
@@ -3030,8 +3373,22 @@ static void template_keymap_item_properties(uiLayout *layout, const char *title,
}
}
- /* add property */
- uiItemFullR(flow, ptr, prop, -1, 0, 0, NULL, ICON_NONE);
+ box = uiLayoutBox(flow);
+ uiLayoutSetActive(box, is_set);
+ row = uiLayoutRow(box, false);
+
+ /* property value */
+ uiItemFullR(row, ptr, prop, -1, 0, 0, NULL, ICON_NONE);
+
+ if (is_set) {
+ /* unset operator */
+ uiBlock *block = uiLayoutGetBlock(row);
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ but = uiDefIconButO(block, BUT, "UI_OT_unset_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ but->rnapoin = *ptr;
+ but->rnaprop = prop;
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ }
}
RNA_STRUCT_END;
}
@@ -3047,8 +3404,12 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
/* attach callbacks to compensate for missing properties update,
* we don't know which keymap (item) is being modified there */
- for (; but; but = but->next)
- uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);
+ for (; but; but = but->next) {
+ /* operator buttons may store props for use (file selector, [#36492]) */
+ if (but->rnaprop) {
+ uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);
+ }
+ }
}
}
@@ -3100,6 +3461,8 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE);
+ uiItemR(col, &view_transform_ptr, "look", 0, IFACE_("Look"), ICON_NONE);
+
col = uiLayoutColumn(layout, FALSE);
uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE);
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 594d3e40dcd..4be8812d68c 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1215,7 +1215,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* cut string in 2 parts - only for menu entries */
if ((but->block->flag & UI_BLOCK_LOOP)) {
if (ELEM3(but->type, NUM, TEX, NUMSLI) == 0) {
- cpoin = strchr(but->drawstr, '|');
+ cpoin = strchr(but->drawstr, UI_SEP_CHAR);
if (cpoin) *cpoin = 0;
}
}
@@ -1261,7 +1261,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
fstyle->align = UI_STYLE_TEXT_RIGHT;
rect->xmax -= ui_but_draw_menu_icon(but) ? UI_DPI_ICON_SIZE : 0.25f * U.widget_unit;
uiStyleFontDraw(fstyle, rect, cpoin + 1);
- *cpoin = '|';
+ *cpoin = UI_SEP_CHAR;
}
}
@@ -2850,6 +2850,16 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta;
}
+/* labels use Editor theme colors for text */
+static void widget_state_label(uiWidgetType *wt, int state)
+{
+ /* call this for option button */
+ widget_state(wt, state);
+ if (state & UI_SELECT)
+ UI_GetThemeColor3ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text);
+ else
+ UI_GetThemeColor3ubv(TH_TEXT, (unsigned char *)wt->wcol.text);
+}
static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
@@ -2970,9 +2980,12 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
case UI_WTYPE_LISTLABEL:
wt.wcol_theme = &btheme->tui.wcol_list_item;
- /* fall-through */ /* we use usual label code too. */
+ wt.draw = NULL;
+ /* Can't use usual label code. */
+ break;
case UI_WTYPE_LABEL:
wt.draw = NULL;
+ wt.state = widget_state_label;
break;
case UI_WTYPE_TOGGLE:
@@ -3482,7 +3495,7 @@ void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
/* helper call to draw a menu item without button */
/* state: UI_ACTIVE or 0 */
-void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state)
+void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep)
{
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
rcti _rect = *rect;
@@ -3499,21 +3512,25 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
if (iconid) rect->xmin += UI_DPI_ICON_SIZE;
/* cut string in 2 parts? */
- cpoin = strchr(name, '|');
- if (cpoin) {
- *cpoin = 0;
- rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1) + 10;
+ if (use_sep) {
+ cpoin = strchr(name, UI_SEP_CHAR);
+ if (cpoin) {
+ *cpoin = 0;
+ rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1) + 10;
+ }
}
glColor4ubv((unsigned char *)wt->wcol.text);
uiStyleFontDraw(fstyle, rect, name);
/* part text right aligned */
- if (cpoin) {
- fstyle->align = UI_STYLE_TEXT_RIGHT;
- rect->xmax = _rect.xmax - 5;
- uiStyleFontDraw(fstyle, rect, cpoin + 1);
- *cpoin = '|';
+ if (use_sep) {
+ if (cpoin) {
+ fstyle->align = UI_STYLE_TEXT_RIGHT;
+ rect->xmax = _rect.xmax - 5;
+ uiStyleFontDraw(fstyle, rect, cpoin + 1);
+ *cpoin = UI_SEP_CHAR;
+ }
}
/* restore rect, was messed with */
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 1ef4d43c9f3..ace35f0276e 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -484,6 +484,14 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_STITCH_PREVIEW_ACTIVE:
cp = ts->preview_stitch_active;
break;
+
+ case TH_UV_OTHERS:
+ cp = ts->uv_others;
+ break;
+ case TH_UV_SHADOW:
+ cp = ts->uv_shadow;
+ break;
+
case TH_MARKER_OUTLINE:
cp = ts->marker_outline; break;
case TH_MARKER:
@@ -918,6 +926,9 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
+ rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
+ rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
+
/* space text */
btheme->text = btheme->tv3d;
rgba_char_args_set(btheme->text.back, 153, 153, 153, 255);
@@ -2205,7 +2216,15 @@ void init_userdef_do_versions(void)
}
/* NOTE!! from now on use U.versionfile and U.subversionfile */
-
+
+ if (U.versionfile < 269 || (U.versionfile == 268 && U.subversionfile < 3)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
+ rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index f656d22fc64..037fa7c6a94 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -2029,6 +2029,17 @@ void UI_view2d_to_region_no_clip(View2D *v2d, float x, float y, int *regionx, in
}
}
+void UI_view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
+{
+ /* express given coordinates as proportional values */
+ x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur);
+ y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur);
+
+ /* convert proportional distances to screen coordinates */
+ *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
+ *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
+}
+
/* *********************************************************************** */
/* Utilities */
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 929b7ae2a5d..00113666872 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -128,7 +128,7 @@ static int view_pan_init(bContext *C, wmOperator *op)
}
/* apply transform to view (i.e. adjust 'cur' rect) */
-static void view_pan_apply(wmOperator *op)
+static void view_pan_apply(bContext *C, wmOperator *op)
{
v2dViewPanData *vpd = op->customdata;
View2D *v2d = vpd->v2d;
@@ -153,6 +153,7 @@ static void view_pan_apply(wmOperator *op)
/* request updates to be done... */
ED_region_tag_redraw(vpd->ar);
+ WM_event_add_mousemove(C);
UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
@@ -181,7 +182,7 @@ static int view_pan_exec(bContext *C, wmOperator *op)
if (!view_pan_init(C, op))
return OPERATOR_CANCELLED;
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
}
@@ -209,7 +210,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "deltax", event->prevx - event->x);
RNA_int_set(op->ptr, "deltay", event->prevy - event->y);
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
}
@@ -218,11 +219,11 @@ static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "deltay", 0);
if (v2d->keepofs & V2D_LOCKOFS_X)
- WM_cursor_modal(window, BC_NS_SCROLLCURSOR);
+ WM_cursor_modal_set(window, BC_NS_SCROLLCURSOR);
else if (v2d->keepofs & V2D_LOCKOFS_Y)
- WM_cursor_modal(window, BC_EW_SCROLLCURSOR);
+ WM_cursor_modal_set(window, BC_EW_SCROLLCURSOR);
else
- WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR);
+ WM_cursor_modal_set(window, BC_NSEW_SCROLLCURSOR);
/* add temp handler */
WM_event_add_modal_handler(C, op);
@@ -246,7 +247,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
vpd->lastx = event->x;
vpd->lasty = event->y;
- view_pan_apply(op);
+ view_pan_apply(C, op);
break;
}
/* XXX - Mode switching isn't implemented. See comments in 36818.
@@ -259,7 +260,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty));
view_pan_exit(op);
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
return OPERATOR_FINISHED;
}
@@ -272,7 +273,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty));
view_pan_exit(op);
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
return OPERATOR_FINISHED;
}
@@ -333,7 +334,7 @@ static int view_scrollright_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltay", 0);
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -377,7 +378,7 @@ static int view_scrollleft_exec(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "deltay", 0);
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -425,7 +426,7 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op)
}
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -475,7 +476,7 @@ static int view_scrollup_exec(bContext *C, wmOperator *op)
}
/* apply movement, then we're done */
- view_pan_apply(op);
+ view_pan_apply(C, op);
view_pan_exit(op);
return OPERATOR_FINISHED;
@@ -986,11 +987,11 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
}
if (v2d->keepofs & V2D_LOCKOFS_X)
- WM_cursor_modal(window, BC_NS_SCROLLCURSOR);
+ WM_cursor_modal_set(window, BC_NS_SCROLLCURSOR);
else if (v2d->keepofs & V2D_LOCKOFS_Y)
- WM_cursor_modal(window, BC_EW_SCROLLCURSOR);
+ WM_cursor_modal_set(window, BC_EW_SCROLLCURSOR);
else
- WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR);
+ WM_cursor_modal_set(window, BC_NSEW_SCROLLCURSOR);
/* add temp handler */
WM_event_add_modal_handler(C, op);
@@ -1092,7 +1093,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
/* free customdata */
view_zoomdrag_exit(C, op);
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
return OPERATOR_FINISHED;
}
@@ -1143,6 +1144,7 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
rctf rect;
rctf cur_new = v2d->cur;
int gesture_mode;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* convert coordinates of rect to 'tot' rect coordinates */
UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmin"), RNA_int_get(op->ptr, "ymin"), &rect.xmin, &rect.ymin);
@@ -1194,7 +1196,7 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op)
}
}
- UI_view2d_smooth_view(C, ar, &cur_new);
+ UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -1268,7 +1270,7 @@ static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b)
/* will start timer if appropriate */
/* the arguments are the desired situation */
void UI_view2d_smooth_view(bContext *C, ARegion *ar,
- const rctf *cur)
+ const rctf *cur, const int smooth_viewtx)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
@@ -1288,7 +1290,7 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar,
fac = smooth_view_rect_to_fac(&v2d->cur, cur);
}
- if (U.smooth_viewtx && fac > FLT_EPSILON) {
+ if (smooth_viewtx && fac > FLT_EPSILON) {
int changed = FALSE;
if (BLI_rctf_compare(&sms.new_cur, &v2d->cur, FLT_EPSILON) == FALSE)
@@ -1299,7 +1301,7 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar,
if (changed) {
sms.orig_cur = v2d->cur;
- sms.time_allowed = (double)U.smooth_viewtx / 1000.0;
+ sms.time_allowed = (double)smooth_viewtx / 1000.0;
/* scale the time allowed the change in view */
sms.time_allowed *= (double)fac;
@@ -1372,14 +1374,16 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Smooth View 2D";
- ot->description = "Zoom in the view to the nearest item contained in the border";
+ ot->description = "";
ot->idname = "VIEW2D_OT_smoothview";
/* api callbacks */
ot->invoke = view2d_smoothview_invoke;
-
ot->poll = view2d_poll;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+
/* rna */
WM_operator_properties_gesture_border(ot, FALSE);
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index a1bb7a8ae88..f50e4400b91 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -96,7 +96,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int use_object_instantiation;
int sort_by_name;
int export_transformation_type;
- int second_life;
+ int open_sim;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -106,6 +106,24 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", filepath);
BLI_ensure_extension(filepath, sizeof(filepath), ".dae");
+
+ /* Avoid File write exceptions in Collada */
+ if (!BLI_exists(filepath)) {
+ BLI_make_existing_file(filepath);
+ if (!BLI_file_touch(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't create export file");
+ fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else if (!BLI_file_is_writable(filepath)) {
+ BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
+ fprintf(stdout, "Collada export: Can not modify: %s\n", filepath);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Now the exporter can create and write the export file */
+
/* Options panel */
apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection");
@@ -124,11 +142,13 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
- second_life = RNA_boolean_get(op->ptr, "second_life");
+ open_sim = RNA_boolean_get(op->ptr, "open_sim");
/* get editmode results */
ED_object_editmode_load(CTX_data_edit_object(C));
+
+
if (collada_export(CTX_data_scene(C),
filepath,
apply_modifiers,
@@ -148,7 +168,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
use_object_instantiation,
sort_by_name,
export_transformation_type,
- second_life))
+ open_sim))
{
return OPERATOR_FINISHED;
}
@@ -216,7 +236,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, "second_life", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
/* Collada options: */
box = uiLayoutBox(layout);
@@ -330,8 +350,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
"Transform", "Transformation type for translation, scale and rotation");
- RNA_def_boolean(ot->srna, "second_life", 0, "Export for Second Life",
- "Compatibility mode for Second Life");
+ RNA_def_boolean(ot->srna, "open_sim", 0, "Export for OpenSim",
+ "Compatibility mode for OpenSim and compatible online worlds");
}
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 9c270144a0a..4cc9d3b59b1 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -737,3 +737,159 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
"Location", "Location of vertex in normalized space", -1.0f, 1.0f);
}
+
+/******************** common primitive functions *********************/
+
+static int create_primitive_from_points(bContext *C, wmOperator *op, const float (*points)[2],
+ int num_points, char handle_type)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask;
+ MaskLayer *mask_layer;
+ MaskSpline *new_spline;
+ float scale, location[2], frame_size[2];
+ int i, width, height;
+ int size = RNA_float_get(op->ptr, "size");
+
+ ED_mask_get_size(sa, &width, &height);
+ scale = (float)size / max_ii(width, height);
+
+ /* Get location in mask space. */
+ frame_size[0] = width;
+ frame_size[1] = height;
+ RNA_float_get_array(op->ptr, "location", location);
+ location[0] /= width;
+ location[1] /= height;
+ BKE_mask_coord_from_frame(location, location, frame_size);
+
+ /* Make it so new primitive is centered to mouse location. */
+ location[0] -= 0.5f * scale;
+ location[1] -= 0.5f * scale;
+
+ mask_layer = ED_mask_layer_ensure(C);
+ mask = CTX_data_edit_mask(C);
+
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
+ new_spline = BKE_mask_spline_add(mask_layer);
+ new_spline->flag = MASK_SPLINE_CYCLIC | SELECT;
+ new_spline->tot_point = num_points;
+ new_spline->points = MEM_recallocN(new_spline->points,
+ sizeof(MaskSplinePoint) * new_spline->tot_point);
+
+ mask_layer->act_spline = new_spline;
+ mask_layer->act_point = NULL;
+
+ for (i = 0; i < num_points; i++) {
+ MaskSplinePoint *new_point = &new_spline->points[i];
+
+ copy_v2_v2(new_point->bezt.vec[1], points[i]);
+ mul_v2_fl(new_point->bezt.vec[1], scale);
+ add_v2_v2(new_point->bezt.vec[1], location);
+
+ new_point->bezt.h1 = handle_type;
+ new_point->bezt.h2 = handle_type;
+ BKE_mask_point_select_set(new_point, true);
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ /* TODO: only update this spline */
+ BKE_mask_update_display(mask, CFRA);
+
+ return OPERATOR_FINISHED;
+}
+
+static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ ScrArea *sa = CTX_wm_area(C);
+ float cursor[2];
+ int width, height;
+
+ ED_mask_get_size(sa, &width, &height);
+ ED_mask_cursor_location_get(sa, cursor);
+
+ cursor[0] *= width;
+ cursor[1] *= height;
+
+ RNA_float_set_array(op->ptr, "location", cursor);
+
+ return op->type->exec(C, op);
+}
+
+static void define_prinitive_add_properties(wmOperatorType *ot)
+{
+ RNA_def_float(ot->srna, "size", 100, -FLT_MAX, FLT_MAX,
+ "Size", "Size of new circle", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Location", "Location of new circle", -FLT_MAX, FLT_MAX);
+}
+
+/******************** primitive add circle *********************/
+
+static int primitive_circle_add_exec(bContext *C, wmOperator *op)
+{
+ const float points[4][2] = {{0.0f, 0.5f},
+ {0.5f, 1.0f},
+ {1.0f, 0.5f},
+ {0.5f, 0.0f}};
+ int num_points = sizeof(points) / (2 * sizeof(float));
+
+ create_primitive_from_points(C, op, points, num_points, HD_AUTO);
+
+ return OPERATOR_FINISHED;
+}
+
+void MASK_OT_primitive_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Circle";
+ ot->description = "Add new circle-shaped spline";
+ ot->idname = "MASK_OT_primitive_circle_add";
+
+ /* api callbacks */
+ ot->exec = primitive_circle_add_exec;
+ ot->invoke = primitive_add_invoke;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ define_prinitive_add_properties(ot);
+}
+
+/******************** primitive add suqare *********************/
+
+static int primitive_square_add_exec(bContext *C, wmOperator *op)
+{
+ const float points[4][2] = {{0.0f, 0.0f},
+ {0.0f, 1.0f},
+ {1.0f, 1.0f},
+ {1.0f, 0.0f}};
+ int num_points = sizeof(points) / (2 * sizeof(float));
+
+ create_primitive_from_points(C, op, points, num_points, HD_VECT);
+
+ return OPERATOR_FINISHED;
+}
+
+void MASK_OT_primitive_square_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Square";
+ ot->description = "Add new square-shaped spline";
+ ot->idname = "MASK_OT_primitive_square_add";
+
+ /* api callbacks */
+ ot->exec = primitive_square_add_exec;
+ ot->invoke = primitive_add_invoke;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ define_prinitive_add_properties(ot);
+}
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index 9ae5b436fb3..62eb9cc240a 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -363,6 +363,40 @@ void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *s
}
}
+void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2])
+{
+ if (sa) {
+ switch (sa->spacetype) {
+ case SPACE_CLIP:
+ {
+ SpaceClip *space_clip = sa->spacedata.first;
+ copy_v2_v2(cursor, space_clip->cursor);
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ zero_v2(cursor);
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ SpaceImage *space_image = sa->spacedata.first;
+ copy_v2_v2(cursor, space_image->cursor);
+ break;
+ }
+ default:
+ /* possible other spaces from which mask editing is available */
+ BLI_assert(0);
+ zero_v2(cursor);
+ break;
+ }
+ }
+ else {
+ BLI_assert(0);
+ zero_v2(cursor);
+ }
+}
+
/********************** registration *********************/
void ED_operatortypes_mask(void)
@@ -376,6 +410,8 @@ void ED_operatortypes_mask(void)
/* add */
WM_operatortype_append(MASK_OT_add_vertex);
WM_operatortype_append(MASK_OT_add_feather_vertex);
+ WM_operatortype_append(MASK_OT_primitive_circle_add);
+ WM_operatortype_append(MASK_OT_primitive_square_add);
/* geometry */
WM_operatortype_append(MASK_OT_switch_direction);
@@ -417,6 +453,9 @@ void ED_operatortypes_mask(void)
/* layers */
WM_operatortype_append(MASK_OT_layer_move);
+
+ /* duplicate */
+ WM_operatortype_append(MASK_OT_duplicate);
}
void ED_keymap_mask(wmKeyConfig *keyconf)
@@ -429,6 +468,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
+ /* add menu */
+ WM_keymap_add_menu(keymap, "MASK_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
+
/* mask mode supports PET now */
ED_keymap_proportional_cycle(keyconf, keymap);
ED_keymap_proportional_maskmode(keyconf, keymap);
@@ -500,6 +542,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MASK_OT_shape_key_insert", IKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MASK_OT_shape_key_clear", IKEY, KM_PRESS, KM_ALT, 0);
+ /* duplicate */
+ WM_keymap_add_item(keymap, "MASK_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
+
/* for image editor only */
WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
@@ -514,7 +559,6 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
void ED_operatormacros_mask(void)
{
- /* XXX: just for sample */
wmOperatorType *ot;
wmOperatorTypeMacro *otmacro;
@@ -531,4 +575,11 @@ void ED_operatormacros_mask(void)
WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex");
otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
RNA_boolean_set(otmacro->ptr, "slide_feather", TRUE);
+
+ ot = WM_operatortype_append_macro("MASK_OT_duplicate_move", "Add Duplicate", "Duplicate mask and move",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MASK_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
}
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index bd148c48980..51705aa5837 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -42,9 +42,12 @@ struct wmOperatorType;
/* mask_add.c */
void MASK_OT_add_vertex(struct wmOperatorType *ot);
void MASK_OT_add_feather_vertex(struct wmOperatorType *ot);
+void MASK_OT_primitive_circle_add(struct wmOperatorType *ot);
+void MASK_OT_primitive_square_add(struct wmOperatorType *ot);
/* mask_ops.c */
struct Mask *ED_mask_new(struct bContext *C, const char *name);
+struct MaskLayer *ED_mask_layer_ensure(struct bContext *C);
void MASK_OT_new(struct wmOperatorType *ot);
void MASK_OT_layer_new(struct wmOperatorType *ot);
@@ -75,6 +78,8 @@ struct MaskSplinePoint *ED_mask_point_find_nearest(
void MASK_OT_layer_move(struct wmOperatorType *ot);
+void MASK_OT_duplicate(struct wmOperatorType *ot);
+
/* mask_relationships.c */
void MASK_OT_parent_set(struct wmOperatorType *ot);
void MASK_OT_parent_clear(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index c9d3bd19941..5ca0d133b0e 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -292,6 +292,26 @@ Mask *ED_mask_new(bContext *C, const char *name)
return mask;
}
+/* Get ative layer. Will create mask/layer to be sure there's an active layer. */
+MaskLayer *ED_mask_layer_ensure(bContext *C)
+{
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer;
+
+ if (mask == NULL) {
+ /* If there's no active mask, create one. */
+ mask = ED_mask_new(C, NULL);
+ }
+
+ mask_layer = BKE_mask_layer_active(mask);
+ if (mask_layer == NULL) {
+ /* If there's no active mask layer, create one. */
+ mask_layer = BKE_mask_layer_new(mask, "");
+ }
+
+ return mask_layer;
+}
+
static int mask_new_exec(bContext *C, wmOperator *op)
{
char name[MAX_ID_NAME - 2];
@@ -1467,3 +1487,110 @@ void MASK_OT_layer_move(wmOperatorType *ot)
/* properties */
RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move the active layer");
}
+
+/******************** duplicate *********************/
+
+static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Mask *mask = CTX_data_edit_mask(C);
+ MaskLayer *mask_layer = BKE_mask_layer_active(mask);
+ MaskSpline *spline;
+
+ if (mask_layer == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ for (spline = mask_layer->splines.last;
+ spline;
+ spline = spline->prev)
+ {
+ MaskSplinePoint *point = spline->points;
+ int i = 0;
+ while (i < spline->tot_point) {
+ int start = i, end = -1;
+ /* Find next selected segment. */
+ while (MASKPOINT_ISSEL_ANY(point)) {
+ BKE_mask_point_select_set(point, false);
+ end = i;
+ if (i >= spline->tot_point - 1) {
+ break;
+ }
+ i++;
+ point++;
+ }
+ if (end >= start) {
+ MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
+ MaskSplinePoint *new_point;
+ int b;
+
+ /* BKE_mask_spline_add might allocate the points, need to free them in this case. */
+ if (new_spline->points) {
+ MEM_freeN(new_spline->points);
+ }
+
+ /* Copy options from old spline. */
+ new_spline->flag = spline->flag;
+ new_spline->offset_mode = spline->offset_mode;
+ new_spline->weight_interp = spline->weight_interp;
+ new_spline->parent = spline->parent;
+
+ /* Allocate new points and copy them from old spline. */
+ new_spline->tot_point = end - start + 1;
+ new_spline->points = MEM_mallocN(sizeof(MaskSplinePoint) * new_spline->tot_point,
+ "duplicated mask points");
+
+ memcpy(new_spline->points, spline->points + start,
+ new_spline->tot_point * sizeof(MaskSplinePoint));
+
+ /* Select points and duplicate their UWs (if needed). */
+ for (b = 0, new_point = new_spline->points;
+ b < new_spline->tot_point;
+ b++, new_point++)
+ {
+ if (new_point->uw) {
+ new_point->uw = MEM_dupallocN(new_point->uw);
+ }
+ BKE_mask_point_select_set(new_point, true);
+ }
+
+ /* Clear cyclic flag if we didn't copy the whole spline. */
+ if (new_spline->flag & MASK_SPLINE_CYCLIC) {
+ if (start != 0 || end != spline->tot_point - 1) {
+ new_spline->flag &= ~MASK_SPLINE_CYCLIC;
+ }
+ }
+
+ /* Flush selection to splines. */
+ new_spline->flag |= SELECT;
+ spline->flag &= ~SELECT;
+
+ mask_layer->act_spline = new_spline;
+ }
+ i++;
+ point++;
+ }
+ }
+
+ /* TODO: only update edited splines */
+ BKE_mask_update_display(mask, CFRA);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+
+ return OPERATOR_FINISHED;
+}
+
+void MASK_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Mask";
+ ot->description = "Duplicate selected control points and segments between them";
+ ot->idname = "MASK_OT_duplicate";
+
+ /* api callbacks */
+ ot->exec = mask_duplicate_exec;
+ ot->poll = ED_maskedit_mask_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index 2a1bdee32f7..9cc1702addb 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -102,32 +102,54 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
MaskLayer *masklay;
/* parent info */
- SpaceClip *sc;
- MovieClip *clip;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking;
MovieTrackingTrack *track;
- MovieTrackingMarker *marker;
+ MovieTrackingPlaneTrack *plane_track;
MovieTrackingObject *tracking_object;
/* done */
- int framenr;
+ int framenr, parent_type;
+ float parmask_pos[2], orig_corners[4][2];
+ char *sub_parent_name;
- float marker_pos_ofs[2];
- float parmask_pos[2];
-
- if ((NULL == (sc = CTX_wm_space_clip(C))) ||
- (NULL == (clip = sc->clip)) ||
- (NULL == (track = clip->tracking.act_track)) ||
- (NULL == (tracking_object = BKE_tracking_object_get_active(&clip->tracking))))
- {
+ if (ELEM(NULL, sc, clip)) {
return OPERATOR_CANCELLED;
}
framenr = ED_space_clip_get_clip_frame_number(sc);
- marker = BKE_tracking_marker_get(track, framenr);
- add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
+ tracking = &clip->tracking;
+ tracking_object = BKE_tracking_object_get_active(&clip->tracking);
+
+ if (tracking_object == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if ((track = BKE_tracking_track_get_active(tracking)) != NULL) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+ float marker_pos_ofs[2];
+
+ add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
- BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
+ BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
+
+ sub_parent_name = track->name;
+ parent_type = MASK_PARENT_POINT_TRACK;
+ memset(orig_corners, 0, sizeof(orig_corners));
+ }
+ else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+ zero_v2(parmask_pos);
+ sub_parent_name = plane_track->name;
+ parent_type = MASK_PARENT_PLANE_TRACK;
+ memcpy(orig_corners, plane_marker->corners, sizeof(orig_corners));
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
@@ -144,10 +166,12 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
if (MASKPOINT_ISSEL_ANY(point)) {
point->parent.id_type = ID_MC;
point->parent.id = &clip->id;
+ point->parent.type = parent_type;
BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent));
- BLI_strncpy(point->parent.sub_parent, track->name, sizeof(point->parent.sub_parent));
+ BLI_strncpy(point->parent.sub_parent, sub_parent_name, sizeof(point->parent.sub_parent));
copy_v2_v2(point->parent.parent_orig, parmask_pos);
+ memcpy(point->parent.parent_corners_orig, orig_corners, sizeof(point->parent.parent_corners_orig));
}
}
}
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index 93bdca93096..d5fbdca5b0a 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -38,6 +38,7 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_mask.h"
+#include "BKE_report.h"
#include "DNA_object_types.h"
#include "DNA_mask_types.h"
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index f6da2a82150..2992290e9b6 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -43,7 +43,7 @@ set(SRC
editface.c
editmesh_add.c
editmesh_bevel.c
- editmesh_deform_laplacian.c
+ editmesh_deform_laplacian.c editmesh_bisect.c
editmesh_extrude.c
editmesh_inset.c
editmesh_knife.c
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 902906fcf8a..7944c2f0cca 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -691,6 +691,7 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
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;
@@ -720,36 +721,45 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
totedge = me->edit_btmesh->bm->totedge;
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- topo_hash[BM_elem_index_get(eed->v1)]++;
- topo_hash[BM_elem_index_get(eed->v2)]++;
+ const int i1 = BM_elem_index_get(eed->v1), i2 = BM_elem_index_get(eed->v2);
+ topo_hash[i1]++;
+ topo_hash[i2]++;
}
}
else {
totedge = me->totedge;
for (a = 0, medge = me->medge; a < me->totedge; a++, medge++) {
- topo_hash[medge->v1]++;
- topo_hash[medge->v2]++;
+ const unsigned int i1 = medge->v1, i2 = medge->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) {
- topo_hash[BM_elem_index_get(eed->v1)] += topo_hash_prev[BM_elem_index_get(eed->v2)] * topo_pass;
- topo_hash[BM_elem_index_get(eed->v2)] += topo_hash_prev[BM_elem_index_get(eed->v1)] * topo_pass;
+ 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, medge = me->medge; a < me->totedge; a++, medge++) {
- /* This can make really big numbers, wrapping around here is fine */
- topo_hash[medge->v1] += topo_hash_prev[medge->v2] * topo_pass;
- topo_hash[medge->v2] += topo_hash_prev[medge->v1] * topo_pass;
+ const unsigned int i1 = medge->v1, i2 = medge->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);
@@ -764,13 +774,14 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
}
}
- if (tot_unique <= tot_unique_prev) {
+ 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);
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index f372053db55..47b9d5e2a9e 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -96,15 +96,6 @@ static void make_prim_finish(bContext *C, Object *obedit, bool was_editmode, int
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
}
-static void make_prim_radius_prop(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
-}
-
-
static int add_primitive_plane_exec(bContext *C, wmOperator *op)
{
Object *obedit;
@@ -114,6 +105,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
bool was_editmode;
unsigned int layer;
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Plane"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -139,14 +131,13 @@ void MESH_OT_primitive_plane_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_plane_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_plane_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- make_prim_radius_prop(ot);
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -159,6 +150,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
bool was_editmode;
unsigned int layer;
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cube"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -185,14 +177,13 @@ void MESH_OT_primitive_cube_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_cube_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_cube_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- make_prim_radius_prop(ot);
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -215,6 +206,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
cap_end = RNA_enum_get(op->ptr, "fill_type");
cap_tri = (cap_end == 2);
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Circle"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -241,7 +233,6 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_circle_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_circle_exec;
ot->poll = ED_operator_scene_editable;
@@ -250,7 +241,7 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500);
- make_prim_radius_prop(ot);
+ ED_object_add_unit_props(ot);
RNA_def_enum(ot->srna, "fill_type", fill_type_items, 0, "Fill Type", "");
ED_object_add_generic_props(ot, true);
@@ -268,6 +259,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
const bool cap_end = (end_fill_type != 0);
const bool cap_tri = (end_fill_type == 2);
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cylinder"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -299,7 +291,6 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_cylinder_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_cylinder_exec;
ot->poll = ED_operator_scene_editable;
@@ -308,7 +299,7 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500);
- make_prim_radius_prop(ot);
+ ED_object_add_unit_props(ot);
prop = RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Cap Fill Type", "");
@@ -328,6 +319,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
const bool cap_end = (end_fill_type != 0);
const bool cap_tri = (end_fill_type == 2);
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Cone"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -356,7 +348,6 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_cone_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_cone_exec;
ot->poll = ED_operator_scene_editable;
@@ -385,6 +376,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
bool was_editmode;
unsigned int layer;
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Grid"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -412,7 +404,6 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_grid_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_grid_exec;
ot->poll = ED_operator_scene_editable;
@@ -422,7 +413,7 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "x_subdivisions", 10, 3, INT_MAX, "X Subdivisions", "", 3, 1000);
RNA_def_int(ot->srna, "y_subdivisions", 10, 3, INT_MAX, "Y Subdivisions", "", 3, 1000);
- make_prim_radius_prop(ot);
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, true);
}
@@ -437,6 +428,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
unsigned int layer;
bool was_editmode;
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, &is_view_aligned);
if (!is_view_aligned)
rot[0] += (float)M_PI / 2.0f;
@@ -469,12 +461,11 @@ void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_monkey_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_monkey_exec;
ot->poll = ED_operator_scene_editable;
/* flags */
- make_prim_radius_prop(ot);
+ ED_object_add_unit_props(ot);
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ED_object_add_generic_props(ot, true);
@@ -489,6 +480,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
bool was_editmode;
unsigned int layer;
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Sphere"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -517,7 +509,6 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_uv_sphere_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_uvsphere_exec;
ot->poll = ED_operator_scene_editable;
@@ -542,6 +533,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
bool was_editmode;
unsigned int layer;
+ WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
obedit = make_prim_init(C, CTX_DATA_(BLF_I18NCONTEXT_ID_MESH, "Icosphere"), &dia, mat, &was_editmode, loc, rot, layer);
em = BKE_editmesh_from_object(obedit);
@@ -570,7 +562,6 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
ot->idname = "MESH_OT_primitive_ico_sphere_add";
/* api callbacks */
- ot->invoke = WM_operator_view3d_distance_invoke;
ot->exec = add_primitive_icosphere_exec;
ot->poll = ED_operator_scene_editable;
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
new file mode 100644
index 00000000000..5431b1deb1c
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -0,0 +1,331 @@
+/*
+ * ***** 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 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/editmesh_bisect.c
+ * \ingroup edmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_global.h"
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+
+#include "mesh_intern.h" /* own include */
+
+static int mesh_bisect_exec(bContext *C, wmOperator *op);
+
+/* -------------------------------------------------------------------- */
+/* Model Helpers */
+
+typedef struct {
+ /* modal only */
+ BMBackup mesh_backup;
+ bool is_first;
+ short twtype;
+} BisectData;
+
+static bool mesh_bisect_interactive_calc(
+ bContext *C, wmOperator *op,
+ BMEditMesh *em,
+ float plane_co[3], float plane_no[3])
+{
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata;
+
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ int x_start = RNA_int_get(op->ptr, "xstart");
+ int y_start = RNA_int_get(op->ptr, "ystart");
+ int x_end = RNA_int_get(op->ptr, "xend");
+ int y_end = RNA_int_get(op->ptr, "yend");
+
+ /* reference location (some point in front of the view) for finding a point on a plane */
+ const float *co_ref = rv3d->ofs;
+ float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2];
+ float co_a[3], co_b[3];
+ const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
+
+ opdata = gesture->userdata;
+
+ /* view vector */
+ ED_view3d_win_to_vector(ar, co_a_ss, co_a);
+
+ /* view delta */
+ sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss);
+ ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac);
+
+ /* cross both to get a normal */
+ cross_v3_v3v3(plane_no, co_a, co_b);
+ normalize_v3(plane_no); /* not needed but nicer for user */
+
+ /* point on plane, can use either start or endpoint */
+ ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co);
+
+ if (opdata->is_first == false)
+ EDBM_redo_state_restore(opdata->mesh_backup, em, false);
+
+ opdata->is_first = false;
+
+ return true;
+}
+
+static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int ret;
+
+ /* if the properties are set or there is no rv3d,
+ * skip model and exec immediately */
+
+ if ((CTX_wm_region_view3d(C) == NULL) ||
+ (RNA_struct_property_is_set(op->ptr, "plane_co") &&
+ RNA_struct_property_is_set(op->ptr, "plane_no")))
+ {
+ return mesh_bisect_exec(C, op);
+ }
+
+ ret = WM_gesture_straightline_invoke(C, op, event);
+ if (ret & OPERATOR_RUNNING_MODAL) {
+ View3D *v3d = CTX_wm_view3d(C);
+
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata;
+
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
+ opdata->mesh_backup = EDBM_redo_state_store(em);
+ opdata->is_first = true;
+ gesture->userdata = opdata;
+
+ /* misc other vars */
+ G.moving = G_TRANSFORM_EDIT;
+ opdata->twtype = v3d->twtype;
+ v3d->twtype = 0;
+ }
+ return ret;
+}
+
+static void edbm_bisect_exit(bContext *C, BisectData *opdata)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
+ v3d->twtype = opdata->twtype;
+ G.moving = 0;
+}
+
+static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ wmGesture *gesture = op->customdata;
+ BisectData *opdata = gesture->userdata;
+ BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */
+ int ret;
+
+ ret = WM_gesture_straightline_modal(C, op, event);
+
+ if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
+ edbm_bisect_exit(C, &opdata_back);
+ }
+
+ return ret;
+}
+
+/* End Model Helpers */
+/* -------------------------------------------------------------------- */
+
+
+
+static int mesh_bisect_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ /* both can be NULL, fallbacks values are used */
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm;
+ BMOperator bmop;
+ float plane_co[3];
+ float plane_no[3];
+ float imat[4][4];
+
+ const float thresh = RNA_float_get(op->ptr, "threshold");
+ const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
+ const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
+ const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
+
+ PropertyRNA *prop_plane_co;
+ PropertyRNA *prop_plane_no;
+
+ prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
+ if (RNA_property_is_set(op->ptr, prop_plane_co)) {
+ RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co);
+ }
+ else {
+ copy_v3_v3(plane_co, give_cursor(scene, v3d));
+ RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+ }
+
+ prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
+ if (RNA_property_is_set(op->ptr, prop_plane_no)) {
+ RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no);
+ }
+ else {
+ if (rv3d) {
+ copy_v3_v3(plane_no, rv3d->viewinv[1]);
+ }
+ else {
+ /* fallback... */
+ plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f;
+ }
+ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+ }
+
+
+
+ /* -------------------------------------------------------------------- */
+ /* Modal support */
+ /* Note: keep this isolated, exec can work wihout this */
+ if ((op->customdata != NULL) &&
+ mesh_bisect_interactive_calc(C, op, em, plane_co, plane_no))
+ {
+ /* write back to the props */
+ RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+ RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+ }
+ /* End Modal */
+ /* -------------------------------------------------------------------- */
+
+
+
+ bm = em->bm;
+
+ invert_m4_m4(imat, obedit->obmat);
+ mul_m4_v3(imat, plane_co);
+ mul_mat3_m4_v3(imat, plane_no);
+
+ EDBM_op_init(em, &bmop, op,
+ "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
+ BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer);
+ BMO_op_exec(bm, &bmop);
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ if (use_fill) {
+ float normal_fill[3];
+ BMOperator bmop_fill;
+ BMOperator bmop_attr;
+
+ normalize_v3_v3(normal_fill, plane_no);
+ if (clear_outer == true && clear_inner == false) {
+ negate_v3(normal_fill);
+ }
+
+ /* Fill */
+ BMO_op_initf(
+ bm, &bmop_fill, op->flag,
+ "triangle_fill edges=%S normal=%v use_dissolve=%b",
+ &bmop, "geom_cut.out", normal_fill, true);
+ BMO_op_exec(bm, &bmop_fill);
+
+ /* Copy Attributes */
+ BMO_op_initf(bm, &bmop_attr, op->flag,
+ "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+ &bmop_fill, "geom.out", false, true);
+ BMO_op_exec(bm, &bmop_attr);
+
+ BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
+ BMO_op_finish(bm, &bmop_attr);
+ BMO_op_finish(bm, &bmop_fill);
+ }
+
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
+
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ EDBM_update_generic(em, true, true);
+ EDBM_selectmode_flush(em);
+ return OPERATOR_FINISHED;
+ }
+}
+
+
+void MESH_OT_bisect(struct wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Bisect";
+ ot->description = "Cut geometry along a plane";
+ ot->idname = "MESH_OT_bisect";
+
+ /* api callbacks */
+ ot->exec = mesh_bisect_exec;
+ ot->invoke = mesh_bisect_invoke;
+ ot->modal = mesh_bisect_modal;
+ ot->cancel = WM_gesture_straightline_cancel;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+
+ prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX,
+ "Plane Point", "A point on the plane", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX,
+ "Plane Normal", "The direction the plane points", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
+ RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
+ RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry in front of the plane");
+
+ RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1);
+
+ WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+}
diff --git a/source/blender/editors/mesh/editmesh_deform_laplacian.c b/source/blender/editors/mesh/editmesh_deform_laplacian.c
index 2e83a550022..4c1cb547684 100644
--- a/source/blender/editors/mesh/editmesh_deform_laplacian.c
+++ b/source/blender/editors/mesh/editmesh_deform_laplacian.c
@@ -758,9 +758,9 @@ wmKeyMap * laplacian_deform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, HKEY, KM_PRESS, 0, 0, LAP_MODAL_MARK_STATIC);
WM_modalkeymap_add_item(keymap, PKEY, KM_PRESS, 0, 0, LAP_MODAL_PREVIEW);
- WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, LAP_MODAL_TRANSFORM);
- WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, LAP_MODAL_TRANSFORM);
- WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, LAP_MODAL_TRANSFORM);
+ //WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, LAP_MODAL_TRANSFORM);
+ //WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, LAP_MODAL_TRANSFORM);
+ //WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, LAP_MODAL_TRANSFORM);
WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, LAP_MODAL_NOTHING);
WM_modalkeymap_add_item(keymap, TKEY, KM_PRESS, 0, 0, LAP_MODAL_NOTHING);
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index b38f09b1dec..300fb67ec80 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -836,6 +836,8 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ copy_v3_v3(nor, obedit->obmat[2]);
+
/* calculate dvec */
mul_v3_m4v3(v1_co_global, obedit->obmat, v1->co);
mul_v3_m4v3(v2_co_global, obedit->obmat, v2->co);
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index dba19ee5da6..3966826a5b2 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -228,10 +228,8 @@ static bool edbm_inset_calc(wmOperator *op)
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
}
else {
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, false);
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, false);
- /* re-select faces so the verts and edges get selected too */
- BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, BM_ELEM_SELECT);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_SELECT, true);
}
if (!EDBM_op_finish(em, &bmop, op, true)) {
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index e1d0a412ce7..5e88ecabd35 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -308,7 +308,7 @@ static void knife_add_edge_faces_to_vert(KnifeTool_OpData *kcd, KnifeVert *kfv,
BMIter bmiter;
BMFace *f;
- BM_ITER_ELEM(f, &bmiter, e, BM_FACES_OF_EDGE) {
+ BM_ITER_ELEM (f, &bmiter, e, BM_FACES_OF_EDGE) {
knife_append_list(kcd, &kfv->faces, f);
}
}
@@ -354,7 +354,7 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v)
kfv = new_knife_vert(kcd, v->co, kcd->cagecos[BM_elem_index_get(v)]);
kfv->v = v;
BLI_ghash_insert(kcd->origvertmap, v, kfv);
- BM_ITER_ELEM(f, &bmiter, v, BM_FACES_OF_VERT) {
+ BM_ITER_ELEM (f, &bmiter, v, BM_FACES_OF_VERT) {
knife_append_list(kcd, &kfv->faces, f);
}
}
@@ -379,7 +379,7 @@ static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e)
BLI_ghash_insert(kcd->origedgemap, e, kfe);
- BM_ITER_ELEM(f, &bmiter, e, BM_FACES_OF_EDGE) {
+ BM_ITER_ELEM (f, &bmiter, e, BM_FACES_OF_EDGE) {
knife_append_list(kcd, &kfe->faces, f);
}
}
@@ -420,7 +420,7 @@ static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f)
lst = knife_empty_list(kcd);
- BM_ITER_ELEM(e, &bmiter, f, BM_EDGES_OF_FACE) {
+ BM_ITER_ELEM (e, &bmiter, f, BM_EDGES_OF_FACE) {
knife_append_list(kcd, lst, get_bm_knife_edge(kcd, e));
}
@@ -497,13 +497,16 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float
* and move cur data to prev. */
static void knife_add_single_cut(KnifeTool_OpData *kcd)
{
- KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL;
+ KnifeEdge *kfe, *kfe2 = NULL, *kfe3 = NULL;
- if (kcd->prev.vert && kcd->prev.vert == kcd->curr.vert)
- return;
- if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge)
+ if ((kcd->prev.vert && kcd->prev.vert == kcd->curr.vert) ||
+ (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge))
+ {
+ kcd->prev = kcd->curr;
return;
+ }
+ kfe = new_knife_edge(kcd);
kfe->draw = true;
if (kcd->prev.vert) {
@@ -573,38 +576,107 @@ static int verge_linehit(const void *vlh1, const void *vlh2)
if (lh1->l < lh2->l) return -1;
else if (lh1->l > lh2->l) return 1;
+ else if (lh1->v && lh2->v) {
+ /* want like verts to sort together; just compare pointers */
+ if (lh1->v < lh2->v) return -1;
+ else if (lh1->v > lh2->v) return 1;
+ else return 0;
+ }
else return 0;
}
/* If there's a linehit connected (same face) as testi in range [firsti, lasti], return the first such, else -1.
+ * It also counts as connected if both linehits are snapped to the same vertex.
* If testi is out of range, look for connection to f instead, if f is non-NULL */
static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, int firsti, int lasti)
{
int i;
-
- for (i = firsti; i <= lasti; i++) {
- if (testi >= 0 && testi < kcd->totlinehit) {
- if (knife_find_common_face(&kcd->linehits[testi].kfe->faces,
- &kcd->linehits[i].kfe->faces))
- {
- return i;
- }
- }
- else if (f) {
- if (find_ref(&kcd->linehits[i].kfe->faces, f))
- return i;
+ ListBase *testfaces, *ifaces;
+ BMFace *testface, *iface;
+ BMEdgeHit *lh;
+ bool shareface;
+
+ if (testi >= 0 && testi < kcd->totlinehit) {
+ testface = NULL;
+ testfaces = NULL;
+ lh = &kcd->linehits[testi];
+ if (lh->v)
+ testfaces = &lh->v->faces;
+ else if (lh->kfe)
+ testfaces = &lh->kfe->faces;
+ else if (lh->f) {
+ testfaces = NULL;
+ testface = lh->f;
}
}
+ else {
+ testface = f;
+ testfaces = NULL;
+ }
+ for (i = firsti; i <= lasti; i++) {
+ shareface = false;
+ lh = &kcd->linehits[i];
+ iface = NULL;
+ ifaces = NULL;
+ if (lh->v)
+ ifaces = &lh->v->faces;
+ else if (lh->kfe)
+ ifaces = &lh->kfe->faces;
+ else if (lh->f) {
+ ifaces = NULL;
+ iface = lh->f;
+ }
+ if (testfaces) {
+ if (ifaces)
+ shareface = (knife_find_common_face(testfaces, ifaces) != NULL);
+ else if (iface)
+ shareface = (find_ref(testfaces, iface) != NULL);
+ }
+ else if (ifaces) {
+ if (testface)
+ shareface = (find_ref(ifaces, testface) != NULL);
+ }
+ else if (testface && iface) {
+ shareface = (testface == iface);
+ }
+ if (shareface)
+ return i;
+ }
return -1;
}
-/* Sort in order of distance along cut line, but take care when distances are equal */
-static void knife_sort_linehits(KnifeTool_OpData *kcd)
+/* Sort in order of distance along cut line.
+ * Remove any successive linehits that are snapped to the same vertex.
+ * If joinfaces, treat hits at same distance as follows: try to find
+ * ordering so that preceding and succeeding hits will share a face.
+ */
+static void knife_sort_linehits(KnifeTool_OpData *kcd, bool joinfaces)
{
int i, j, k, nexti, nsame;
qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
+ /* Remove duplicated linehits snapped to same vertex */
+ i = j = 0; /* loop copies from j to i */
+ while (j < kcd->totlinehit) {
+ nsame = 0;
+ if (kcd->linehits[j].v) {
+ for (k = j + 1; k < kcd->totlinehit; k++) {
+ if (kcd->linehits[k].v != kcd->linehits[j].v)
+ break;
+ nsame++;
+ }
+ }
+ if (i != j)
+ kcd->linehits[i] = kcd->linehits[j];
+ i++;
+ j += 1 + nsame;
+ }
+ kcd->totlinehit = i;
+
+ if (!joinfaces)
+ return;
+
/* for ranges of equal "l", swap if neccesary to make predecessor and
* successor faces connected to the linehits at either end of the range */
for (i = 0; i < kcd->totlinehit - 1; i = nexti) {
@@ -653,6 +725,7 @@ static void knife_add_single_cut_through(KnifeTool_OpData *kcd, KnifeVert *v1, K
knife_edge_append_face(kcd, kfenew, f);
}
+#if 0
static void knife_get_vert_faces(KnifeTool_OpData *kcd, KnifeVert *kfv, BMFace *facef, ListBase *lst)
{
BMIter bmiter;
@@ -685,20 +758,33 @@ static void knife_get_edge_faces(KnifeTool_OpData *kcd, KnifeEdge *kfe, ListBase
}
}
}
+#endif
+
+static void copy_hit_from_posdata(BMEdgeHit *lh, KnifePosData *pos, float lambda)
+{
+ lh->kfe = pos->edge;
+ lh->v = pos->vert;
+ lh->f = pos->bmface;
+ copy_v3_v3(lh->hit, pos->co);
+ copy_v3_v3(lh->cagehit, pos->cage);
+ copy_v3_v3(lh->realhit, pos->co);
+ lh->l = lambda;
+ /* perc and schit not used by callers of this function */
+}
/* BMESH_TODO: add more functionality to cut-through:
* - cutting "in face" (e.g., holes) should cut in all faces, not just visible one
* - perhaps improve O(n^2) algorithm used here */
static void knife_cut_through(KnifeTool_OpData *kcd)
{
- BMEdgeHit *lh, *lh2;
+ BMEdgeHit *lh, *lh2, *linehits;
BMFace *f;
- KnifeEdge *kfe, *kfe2, *kfe3;
- KnifeVert *v1, *v2, *firstv = NULL, *lastv = NULL;
- ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL};
- Ref *r, *r2;
+ KnifeEdge *kfe, *kfe2;
+ KnifeVert *v1, *v2, *lastv;
+ ListBase *faces1, *faces2;
KnifeEdge **splitkfe;
- int i, j;
+ bool needprev, needcurr;
+ int i, j, n;
if (!kcd->totlinehit) {
/* if no linehits then no interesting back face stuff to do */
@@ -706,93 +792,68 @@ static void knife_cut_through(KnifeTool_OpData *kcd)
return;
}
- /* TODO: probably don't need to sort at all */
- qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
- splitkfe = MEM_callocN(kcd->totlinehit * sizeof(KnifeEdge *), "knife_cut_through");
+ /* sort eliminates hits on same vertices */
+ knife_sort_linehits(kcd, false);
- if (kcd->prev.vert) {
- if (kcd->prev.vert == kcd->curr.vert)
- return;
- firstv = kcd->prev.vert;
- knife_get_vert_faces(kcd, firstv, kcd->prev.bmface, &firstfaces);
- }
- else if (kcd->prev.edge) {
- if (kcd->prev.edge == kcd->curr.edge)
- return;
- firstv = knife_split_edge(kcd, kcd->prev.edge, kcd->prev.co, &kfe3);
- knife_get_edge_faces(kcd, kcd->prev.edge, &firstfaces);
+ /* code is cleaner if make prev and curr into hits (if they are on edges or verts) */
+ n = kcd->totlinehit;
+ needprev = ((kcd->prev.vert && kcd->prev.vert != kcd->linehits[0].v) || kcd->prev.edge);
+ needcurr = ((kcd->curr.vert && kcd->curr.vert != kcd->linehits[n - 1].v) || kcd->curr.edge);
+ n += needprev + needcurr;
+ linehits = MEM_callocN(n * sizeof(BMEdgeHit), "knife_cut_through");
+ i = 0;
+ if (needprev) {
+ copy_hit_from_posdata(&linehits[0], &kcd->prev, 0.0f);
+ i++;
}
+ memcpy(linehits + i, kcd->linehits, kcd->totlinehit * sizeof(BMEdgeHit));
+ i += kcd->totlinehit;
+ if (needcurr)
+ copy_hit_from_posdata(&linehits[i], &kcd->curr, 1.0f);
- if (kcd->curr.vert) {
- lastv = kcd->curr.vert;
- knife_get_vert_faces(kcd, lastv, kcd->curr.bmface, &lastfaces);
- }
- else if (kcd->curr.edge) {
- lastv = knife_split_edge(kcd, kcd->curr.edge, kcd->curr.co, &kfe3);
- knife_get_edge_faces(kcd, kcd->curr.edge, &lastfaces);
- }
-
- if (firstv) {
- /* For each face incident to firstv,
- * find the first following linehit (if any) sharing that face and connect */
- for (r = firstfaces.first; r; r = r->next) {
- bool found = false;
- f = r->ref;
- for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit && !found; j++, lh2++) {
- kfe2 = lh2->kfe;
- for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
- knife_add_single_cut_through(kcd, firstv, v2, f);
- found = true;
- break;
- }
- }
- }
- if (!found && lastv) {
- for (r2 = lastfaces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- knife_add_single_cut_through(kcd, firstv, lastv, f);
- break;
- }
- }
- }
- }
- }
- for (i = 0, lh = kcd->linehits; i < kcd->totlinehit; i++, lh++) {
+ splitkfe = MEM_callocN(n * sizeof(KnifeEdge *), "knife_cut_through");
+
+ lastv = NULL;
+ for (i = 0, lh = linehits; i < n; i++, lh++) {
kfe = lh->kfe;
+ v1 = NULL;
- /* For each face attached to edge for this linehit,
- * find the first following linehit (if any) sharing that face and connect */
- for (r = kfe->faces.first; r; r = r->next) {
- bool found = false;
- f = r->ref;
- for (j = i + 1, lh2 = lh + 1; j < kcd->totlinehit && !found; j++, lh2++) {
- kfe2 = lh2->kfe;
- for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
- v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
- knife_add_single_cut_through(kcd, v1, v2, f);
- found = true;
- break;
- }
- }
+ /* get faces incident on hit lh */
+ if (lh->v) {
+ v1 = lh->v;
+ faces1 = &v1->faces;
+ }
+ else if (kfe) {
+ faces1 = &kfe->faces;
+ }
+
+ /* For each following hit, connect if lh1 an lh2 share a face */
+ for (j = i + 1, lh2 = lh + 1; j < n; j++, lh2++) {
+ kfe2 = lh2->kfe;
+ v2 = NULL;
+ if (lh2->v) {
+ v2 = lh2->v;
+ faces2 = &v2->faces;
}
- if (!found && lastv) {
- for (r2 = lastfaces.first; r2; r2 = r2->next) {
- if (r2->ref == f) {
- v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
- knife_add_single_cut_through(kcd, v1, lastv, f);
- break;
- }
- }
+ else if (kfe2) {
+ faces2 = &kfe2->faces;
+ }
+
+ f = knife_find_common_face(faces1, faces2);
+ if (f) {
+ if (!v1)
+ v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
+ if (!v2)
+ v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
+ knife_add_single_cut_through(kcd, v1, v2, f);
+ lastv = v2;
}
}
}
MEM_freeN(splitkfe);
+ MEM_freeN(linehits);
MEM_freeN(kcd->linehits);
kcd->linehits = NULL;
kcd->totlinehit = 0;
@@ -816,7 +877,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
BMEdgeHit *lh, *lastlh, *firstlh;
int i;
- knife_sort_linehits(kcd);
+ knife_sort_linehits(kcd, true);
lh = kcd->linehits;
lastlh = firstlh = NULL;
@@ -848,14 +909,14 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
continue;
/* first linehit may be down face parallel to view */
- if (!lastlh && fabsf(lh->l) < KNIFE_FLT_EPS)
+ if (!lastlh && !lh->v && fabsf(lh->l) < KNIFE_FLT_EPS)
continue;
if (kcd->prev.is_space) {
kcd->prev.is_space = 0;
copy_v3_v3(kcd->prev.co, lh->hit);
copy_v3_v3(kcd->prev.cage, lh->cagehit);
- kcd->prev.vert = NULL;
+ kcd->prev.vert = lh->v;
kcd->prev.edge = lh->kfe;
kcd->prev.bmface = lh->f;
continue;
@@ -1172,6 +1233,69 @@ static float len_v3_tri_side_max(const float v1[3], const float v2[3], const flo
return sqrtf(max_fff(s1, s2, s3));
}
+/**
+ * given a tri, return 3 planes aligned with the tri's normal.
+ *
+ * If the triangle were extruded along its normal,
+ * the planes calculated would be the 3 sides around the extrusion.
+ */
+static void plane_from_tri_clip3_v3(
+ float tri_plane_clip[3][4],
+ const float v0[3], const float v1[3], const float v2[3])
+{
+ float tri_norm[3];
+ float tvec[3], cross[3];
+
+ normal_tri_v3(tri_norm, v0, v1, v2);
+
+ sub_v3_v3v3(tvec, v0, v1);
+ cross_v3_v3v3(cross, tvec, tri_norm);
+ plane_from_point_normal_v3(tri_plane_clip[0], v0, cross);
+
+ sub_v3_v3v3(tvec, v1, v2);
+ cross_v3_v3v3(cross, tvec, tri_norm);
+ plane_from_point_normal_v3(tri_plane_clip[1], v1, cross);
+
+ sub_v3_v3v3(tvec, v2, v0);
+ cross_v3_v3v3(cross, tvec, tri_norm);
+ plane_from_point_normal_v3(tri_plane_clip[2], v2, cross);
+}
+
+/**
+ * Given a line that is planar with a tri, clip the segment by that tri.
+ *
+ * This is needed so we end up with both points in the triangle.
+ */
+static bool isect_line_tri_coplanar_v3(
+ const float p1[3], const float p2[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float r_isects[2][3],
+
+ /* avoid re-calculating every time */
+ float tri_plane[4], float tri_plane_clip[3][4])
+{
+ float p1_tmp[3] = {UNPACK3(p1)};
+ float p2_tmp[3] = {UNPACK3(p2)};
+
+ (void)v0, (void)v1, (void)v2;
+
+ /* first check if the points are planar with the tri */
+ if ((fabsf(dist_squared_to_plane_v3(p1, tri_plane)) < KNIFE_FLT_EPS_SQUARED) &&
+ (fabsf(dist_squared_to_plane_v3(p2, tri_plane)) < KNIFE_FLT_EPS_SQUARED) &&
+ /* clip the segment by planes around the triangle so we can be sure the points
+ * aren't outside the triangle */
+ (clip_segment_v3_plane_n(p1_tmp, p2_tmp, tri_plane_clip, 3)))
+ {
+ copy_v3_v3(r_isects[0], p1_tmp);
+ copy_v3_v3(r_isects[1], p2_tmp);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
const float v1[3], const float v2[3], const float v3[3],
SmallHash *ehash, bglMats *mats, int *count)
@@ -1181,9 +1305,11 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
BLI_array_declare(edges);
BVHTreeOverlap *results, *result;
BMLoop **ls;
- float cos[9], lambda;
+ float cos[9], tri_norm[3], tri_plane[4], isects[2][3], lambda;
+ float tri_plane_clip[3][4];
unsigned int tot = 0;
- int i;
+ int i, j, n_isects;
+
/* for comparing distances, error of intersection depends on triangle scale.
* need to scale down before squaring for accurate comparison */
@@ -1194,6 +1320,11 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
copy_v3_v3(cos + 3, v2);
copy_v3_v3(cos + 6, v3);
+ /* avoid re-calculation in #isect_line_tri_coplanar_v3 */
+ normal_tri_v3(tri_norm, v1, v2, v3);
+ plane_from_point_normal_v3(tri_plane, v1, tri_norm);
+ plane_from_tri_clip3_v3(tri_plane_clip, v1, v2, v3);
+
BLI_bvhtree_insert(tree2, 0, cos, 3);
BLI_bvhtree_balance(tree2);
@@ -1217,11 +1348,28 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
continue; /* We already found a hit on this knife edge */
}
- if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) {
- float p[3], no[3], view[3], sp[2];
+ n_isects = 0;
- interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda);
+ if (isect_line_tri_coplanar_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3,
+ isects,
+ /* cached values */
+ tri_plane, tri_plane_clip))
+ {
+ /* both kfe ends are in cutting triangle */
+ n_isects = 2;
+ }
+ else if (isect_line_tri_epsilon_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3,
+ &lambda, NULL, depsilon))
+ {
+ /* kfe intersects cutting triangle lambda of the way along kfe */
+ interp_v3_v3v3(isects[0], kfe->v1->cageco, kfe->v2->cageco, lambda);
+ n_isects = 1;
+ }
+
+ for (j = 0; j < n_isects; j++) {
+ float p[3];
+ copy_v3_v3(p, isects[j]);
if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_sq) {
continue;
}
@@ -1239,16 +1387,18 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
continue;
}
- knife_project_v2(kcd, p, sp);
- ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
- mul_m4_v3(kcd->ob->imat, view);
-
if (kcd->cut_through) {
f_hit = NULL;
}
else {
/* check if this point is visible in the viewport */
- float p1[3], lambda1;
+ float p1[3], no[3], view[3], sp[2];
+ float lambda1;
+
+ /* screen projection */
+ knife_project_v2(kcd, p, sp);
+ ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
+ mul_m4_v3(kcd->ob->imat, view);
/* if face isn't planer, p may be behind the current tesselated tri,
* so move it onto that and then a little towards eye */
@@ -1268,7 +1418,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
add_v3_v3(p1, no);
/* ray cast */
- f_hit = BKE_bmbvh_ray_cast(bmtree, p1, no, NULL, NULL, NULL);
+ f_hit = BKE_bmbvh_ray_cast(bmtree, p1, no, KNIFE_FLT_EPS, NULL, NULL, NULL);
}
/* ok, if visible add the new point */
@@ -1283,6 +1433,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
hit.kfe = kfe;
hit.v = NULL;
+ hit.l = 0.0f;
knife_find_basef(kfe);
hit.f = kfe->basef;
@@ -1292,7 +1443,6 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
interp_v3_v3v3(p, kfe->v1->co, kfe->v2->co, hit.perc);
copy_v3_v3(hit.realhit, p);
- /* BMESH_TODO: should also snap to vertices */
if (kcd->snap_midpoints) {
float perc = hit.perc;
@@ -1310,6 +1460,12 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc);
interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc);
}
+ else if (hit.perc < KNIFE_FLT_EPS || hit.perc > 1.0f - KNIFE_FLT_EPS) {
+ /* snap to vert */
+ hit.v = (hit.perc < KNIFE_FLT_EPS) ? kfe->v1 : kfe->v2;
+ copy_v3_v3(hit.hit, hit.v->co);
+ copy_v3_v3(hit.cagehit, hit.v->co);
+ }
else {
copy_v3_v3(hit.hit, p);
}
@@ -1347,7 +1503,7 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
float max_xyz = 0.0f;
int i;
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
for (i = 0; i < 3; i++)
max_xyz = max_ff(max_xyz, fabs(v->co[i]));
}
@@ -1390,8 +1546,16 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
knife_project_v2(kcd, v1, s1);
knife_project_v2(kcd, v2, s2);
- if (len_squared_v2v2(s1, s2) < 1)
- return;
+ if (kcd->is_interactive) {
+ if (len_squared_v2v2(s1, s2) < 1.0f) {
+ return;
+ }
+ }
+ else {
+ if (len_squared_v2v2(s1, s2) < KNIFE_FLT_EPS_SQUARED) {
+ return;
+ }
+ }
/* unproject screen line */
ED_view3d_win_to_segment(kcd->ar, kcd->vc.v3d, s1, v1, v3, true);
@@ -1502,7 +1666,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
sub_v3_v3v3(ray, origin_ofs, origin);
- f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, NULL, co, cageco);
+ f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, 0.0f, NULL, co, cageco);
if (is_space)
*is_space = !f;
@@ -1652,7 +1816,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
if (fptr)
*fptr = f;
- if (cure && p) {
+ if (cure) {
if (!kcd->ignore_edge_snapping || !(cure->e)) {
KnifeVert *edgesnap = NULL;
@@ -1745,7 +1909,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
if (fptr)
*fptr = f;
- if (curv && p) {
+ if (curv) {
copy_v3_v3(p, curv->co);
copy_v3_v3(cagep, curv->cageco);
@@ -1993,7 +2157,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) {
if (!kfv->v) {
/* shouldn't we be at least copying the normal? - if not some comment here should explain why - campbell */
- kfv->v = BM_vert_create(bm, kfv->co, NULL);
+ kfv->v = BM_vert_create(bm, kfv->co, NULL, BM_CREATE_NOP);
kfv->flag = 1;
BMO_elem_flag_enable(bm, kfv->v, DEL);
}
@@ -2656,7 +2820,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha
l_new = NULL;
if (nco == 0) {
/* Want to prevent creating two-sided polygons */
- if (BM_edge_exists(v1, v2)) {
+ if (v1 == v2 || BM_edge_exists(v1, v2)) {
f_new = NULL;
}
else {
@@ -2683,7 +2847,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha
BM_edge_select_set(bm, l_new->e, true);
}
}
- else {
+ else if (f_new) {
BM_elem_select_copy(bm, bm, f_new, f);
}
@@ -2918,7 +3082,7 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
return;
if (kcd->is_interactive) {
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
/* deactivate the extra drawing stuff in 3D-View */
ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
@@ -3053,7 +3217,7 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
knifetool_init(C, kcd, only_select, cut_through, true);
/* add a modal handler for this operator - handles loop selection */
- WM_cursor_modal(CTX_wm_window(C), BC_KNIFECURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR);
WM_event_add_modal_handler(C, op);
knifetool_update_mval_i(kcd, event->mval);
@@ -3073,7 +3237,8 @@ enum {
KNF_MODEL_IGNORE_SNAP_OFF,
KNF_MODAL_ADD_CUT,
KNF_MODAL_ANGLE_SNAP_TOGGLE,
- KNF_MODAL_CUT_THROUGH_TOGGLE
+ KNF_MODAL_CUT_THROUGH_TOGGLE,
+ KNF_MODAL_PANNING
};
wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
@@ -3089,6 +3254,7 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
{KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""},
{KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
{KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
+ {KNF_MODAL_PANNING, "PANNING", 0, "Panning", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3102,6 +3268,7 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
/* items for modal map */
WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL);
+ WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_ANY, KM_ANY, 0, KNF_MODAL_PANNING);
WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_ADD_CUT);
WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL);
WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM);
@@ -3227,18 +3394,12 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(kcd->ar);
break;
- }
- }
- else { /* non-modal-mapped events */
- switch (event->type) {
- case WHEELUPMOUSE:
- case WHEELDOWNMOUSE:
- return OPERATOR_PASS_THROUGH;
- case MIDDLEMOUSE:
+ case KNF_MODAL_PANNING:
if (event->val != KM_RELEASE) {
- if (kcd->mode != MODE_PANNING)
+ if (kcd->mode != MODE_PANNING) {
kcd->prevmode = kcd->mode;
- kcd->mode = MODE_PANNING;
+ kcd->mode = MODE_PANNING;
+ }
}
else {
kcd->mode = kcd->prevmode;
@@ -3246,7 +3407,17 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(kcd->ar);
return OPERATOR_PASS_THROUGH;
-
+ break;
+ }
+ }
+ else { /* non-modal-mapped events */
+ switch (event->type) {
+ case MOUSEPAN:
+ case MOUSEZOOM:
+ case MOUSEROTATE:
+ case WHEELUPMOUSE:
+ case WHEELDOWNMOUSE:
+ return OPERATOR_PASS_THROUGH;
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
if (kcd->mode != MODE_PANNING) {
knifetool_update_mval_i(kcd, event->mval);
@@ -3354,7 +3525,7 @@ static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f,
while (p) {
const float (*mval_fl)[2] = p->link;
const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
- isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1);
+ isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false);
p = p->next;
}
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index e7eaa625843..18db21a8726 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -52,6 +52,9 @@
#include "WM_types.h"
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
#include "mesh_intern.h" /* own include */
struct UserData {
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 1360a180b2d..84952297235 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -50,6 +50,9 @@
#include "ED_transform.h"
#include "ED_view3d.h"
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
#include "mesh_intern.h" /* own include */
/**
@@ -60,23 +63,29 @@
* point and would result in the same distance.
*/
#define INSET_DEFAULT 0.00001f
-static float edbm_rip_edgedist(ARegion *ar, float mat[4][4],
- const float co1[3], const float co2[3], const float mvalf[2],
- const float inset)
+static float edbm_rip_edgedist_squared(ARegion *ar, float mat[4][4],
+ const float co1[3], const float co2[3], const float mvalf[2],
+ const float inset)
{
- float vec1[2], vec2[2];
+ float vec1[2], vec2[2], dist_sq;
ED_view3d_project_float_v2_m4(ar, co1, vec1, mat);
ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
if (inset != 0.0f) {
- const float dist = inset / len_v2v2(vec1, vec2);
- interp_v2_v2v2(vec1, vec1, vec2, dist);
- interp_v2_v2v2(vec2, vec2, vec1, dist);
+ const float dist_2d = len_v2v2(vec1, vec2);
+ if (dist_2d > FLT_EPSILON) {
+ const float dist = inset / dist_2d;
+ BLI_assert(finite(dist));
+ interp_v2_v2v2(vec1, vec1, vec2, dist);
+ interp_v2_v2v2(vec2, vec2, vec1, dist);
+ }
}
- /* TODO: use dist_squared_to_line_segment_v2() looks like we only ever use for comparison */
- return dist_to_line_segment_v2(mvalf, vec1, vec2);
+ dist_sq = dist_squared_to_line_segment_v2(mvalf, vec1, vec2);
+ BLI_assert(finite(dist_sq));
+
+ return dist_sq;
}
#if 0
@@ -488,7 +497,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u
/* face should never exist */
BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == false);
- f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, false);
+ f = BM_face_create_verts(bm, f_verts, f_verts[3] ? 4 : 3, f_example, BM_CREATE_NOP, true);
l_iter = BM_FACE_FIRST_LOOP(f);
@@ -525,11 +534,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BMIter iter, liter;
BMLoop *l;
BMEdge *e, *e2;
- BMVert *v, *ripvert = NULL;
+ BMVert *v;
const int totvert_orig = bm->totvert;
int i;
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
- float dist = FLT_MAX;
+ float dist_sq = FLT_MAX;
float d;
bool is_wire;
@@ -562,15 +571,15 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
if (v->e) {
/* find closest edge to mouse cursor */
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- int is_boundary = BM_edge_is_boundary(e);
+ const bool is_boundary = BM_edge_is_boundary(e);
/* consider wire as boundary for this purpose,
* otherwise we can't a face away from a wire edge */
totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e));
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
if (is_boundary == false && BM_edge_is_manifold(e)) {
- d = edbm_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
- if (d < dist) {
- dist = d;
+ d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
+ if ((e2 == NULL) || (d < dist_sq)) {
+ dist_sq = d;
e2 = e;
}
}
@@ -596,10 +605,9 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
float l_mid_co[3];
l = l_all[i1];
edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
-
- if (d < dist) {
- dist = d;
+ d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
+ if ((e2 == NULL) || (d < dist_sq)) {
+ dist_sq = d;
/* find the edge that is not in this loop */
e2 = NULL;
@@ -647,7 +655,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_select_history_remove(bm, ese.ele);
}
- dist = FLT_MAX;
+ dist_sq = FLT_MAX;
/* in the loop below we find the best vertex to drag based on its connected geometry,
* either by its face corner, or connected edge (when no faces are attached) */
@@ -658,12 +666,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
float l_mid_co[3];
- edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT);
+ edbm_calc_loop_co(l, l_mid_co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT);
- if (d < dist) {
- dist = d;
+ if (d < dist_sq) {
+ dist_sq = d;
vi_best = i;
}
}
@@ -674,12 +682,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
float e_mid_co[3];
- mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co);
- d = edbm_rip_edgedist(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT);
+ mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT);
- if (d < dist) {
- dist = d;
+ if (d < dist_sq) {
+ dist_sq = d;
vi_best = i;
}
}
@@ -730,19 +738,36 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
/* rip two adjacent edges */
if (BM_edge_is_boundary(e2) || BM_vert_face_count(v) == 2) {
/* Don't run the edge split operator in this case */
+ BMVert *v_rip;
- BM_elem_flag_enable(e2, BM_ELEM_TAG); /* only for face-fill (we don't call the operator) */
+ l = BM_edge_vert_share_loop(e2->l, v);
+
+ /* only tag for face-fill (we don't call the operator) */
+ if (BM_edge_is_boundary(e2)) {
+ BM_elem_flag_enable(e2, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ }
/* keep directly before edgesplit */
if (do_fill) {
fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
}
- l = e2->l;
- ripvert = BM_face_vert_separate(bm, l->f, v);
+#if 0
+ v_rip = BM_face_vert_separate(bm, l->f, v);
+#else
+ v_rip = BM_face_loop_separate(bm, l);
+#endif
+
+ BLI_assert(v_rip);
- BLI_assert(ripvert);
- if (!ripvert) {
+ if (v_rip) {
+ BM_vert_select_set(bm, v_rip, true);
+ }
+ else {
if (fill_uloop_pairs) MEM_freeN(fill_uloop_pairs);
return OPERATOR_CANCELLED;
}
@@ -769,37 +794,28 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_mesh_edgesplit(em->bm, true, true, true);
}
- dist = FLT_MAX;
+ dist_sq = FLT_MAX;
{
/* --- select which vert --- */
BMVert *v_best = NULL;
- float l_prev_co[3], l_next_co[3], l_corner_co[3];
- float scale;
+ float l_corner_co[3];
- dist = FLT_MAX;
+ dist_sq = FLT_MAX;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
/* disable by default, re-enable winner at end */
BM_vert_select_set(bm, v, false);
+ BM_select_history_remove(bm, v);
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- /* calculate a point in the face, rather then calculate the middle,
- * make a vector pointing between the 2 edges attached to this loop */
- sub_v3_v3v3(l_prev_co, l->prev->v->co, l->v->co);
- sub_v3_v3v3(l_next_co, l->next->v->co, l->v->co);
-
- scale = normalize_v3(l_prev_co) + normalize_v3(l_next_co);
- mul_v3_fl(l_prev_co, scale);
- mul_v3_fl(l_next_co, scale);
-
- add_v3_v3v3(l_corner_co, l_prev_co, l_next_co);
- add_v3_v3(l_corner_co, l->v->co);
- d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT);
- if (d < dist) {
+ /* check if v_best is null in the _rare_ case there are numeric issues */
+ edbm_calc_loop_co(l, l_corner_co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT);
+ if ((v_best == NULL) || (d < dist_sq)) {
v_best = v;
- dist = d;
+ dist_sq = d;
}
}
}
@@ -965,7 +981,7 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
BMesh *bm = em->bm;
BMIter iter;
BMEdge *e;
- int singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0);
+ const bool singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0);
int ret;
/* running in face mode hardly makes sense, so convert to region loop and rip */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index a1f1f6bd83f..4d512fab1c0 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -33,6 +33,7 @@
#include "BLI_listbase.h"
#include "BLI_linklist.h"
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_array.h"
@@ -185,53 +186,6 @@ unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* set in dr
/* facilities for border select and circle select */
static char *selbuf = NULL;
-/* opengl doesn't support concave... */
-static void draw_triangulated(const int mcords[][2], const short tot)
-{
- ListBase lb = {NULL, NULL};
- DispList *dl;
- float *fp;
- int a;
- const float z_up[3] = {0.0f, 0.0f, 1.0f};
-
- /* make displist */
- dl = MEM_callocN(sizeof(DispList), "poly disp");
- dl->type = DL_POLY;
- dl->parts = 1;
- dl->nr = tot;
- dl->verts = fp = MEM_callocN(tot * 3 * sizeof(float), "poly verts");
- BLI_addtail(&lb, dl);
-
- for (a = 0; a < tot; a++, fp += 3) {
- fp[0] = (float)mcords[a][0];
- fp[1] = (float)mcords[a][1];
- }
-
- /* do the fill */
- BKE_displist_fill(&lb, &lb, z_up, false);
-
- /* do the draw */
- dl = lb.first; /* filldisplist adds in head of list */
- if (dl->type == DL_INDEX3) {
- int *index;
-
- a = dl->parts;
- fp = dl->verts;
- index = dl->index;
- glBegin(GL_TRIANGLES);
- while (a--) {
- glVertex3fv(fp + 3 * index[0]);
- glVertex3fv(fp + 3 * index[1]);
- glVertex3fv(fp + 3 * index[2]);
- index += 3;
- }
- glEnd();
- }
-
- BKE_displist_free(&lb);
-}
-
-
/* reads rect, and builds selection array for quick lookup */
/* returns if all is OK */
bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
@@ -265,7 +219,11 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma
int EDBM_backbuf_check(unsigned int index)
{
+ /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
+ * and just ignore the depth buffer, this is error prone since its possible
+ * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
if (selbuf == NULL) return 1;
+
if (index > 0 && index <= bm_vertoffs)
return selbuf[index];
return 0;
@@ -277,6 +235,18 @@ void EDBM_backbuf_free(void)
selbuf = NULL;
}
+struct LassoMaskData {
+ unsigned int *px;
+ int width;
+};
+
+static void edbm_mask_lasso_px_cb(int x, int y, void *user_data)
+{
+ struct LassoMaskData *data = user_data;
+ data->px[(y * data->width) + x] = true;
+}
+
+
/* mcords is a polygon mask
* - grab backbuffer,
* - draw with black in backbuffer,
@@ -285,9 +255,10 @@ void EDBM_backbuf_free(void)
*/
bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
{
- unsigned int *dr, *drm;
- struct ImBuf *buf, *bufmask;
+ unsigned int *dr, *dr_mask, *dr_mask_arr;
+ struct ImBuf *buf;
int a;
+ struct LassoMaskData lasso_mask_data;
/* method in use for face selecting too */
if (vc->obedit == NULL) {
@@ -305,49 +276,25 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
dr = buf->rect;
- if (vc->rv3d->gpuoffscreen)
- GPU_offscreen_bind(vc->rv3d->gpuoffscreen);
-
- /* draw the mask */
- glDisable(GL_DEPTH_TEST);
-
- glColor3ub(0, 0, 0);
-
- /* yah, opengl doesn't do concave... tsk! */
- ED_region_pixelspace(vc->ar);
- draw_triangulated(mcords, tot);
-
- glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */
- for (a = 0; a < tot; a++) {
- glVertex2iv(mcords[a]);
- }
- glEnd();
-
- glFinish(); /* to be sure readpixels sees mask */
-
- if (vc->rv3d->gpuoffscreen)
- GPU_offscreen_unbind(vc->rv3d->gpuoffscreen);
-
- /* grab mask */
- bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf->x * buf->y, __func__);
+ lasso_mask_data.px = dr_mask;
+ lasso_mask_data.width = (xmax - xmin) + 1;
- if (bufmask == NULL) {
- return false; /* only when mem alloc fails, go crash somewhere else! */
- }
- else {
- drm = bufmask->rect;
- }
+ fill_poly_v2i_n(
+ xmin, ymin, xmax + 1, ymax + 1,
+ mcords, tot,
+ edbm_mask_lasso_px_cb, &lasso_mask_data);
/* build selection lookup */
selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf");
a = (xmax - xmin + 1) * (ymax - ymin + 1);
while (a--) {
- if (*dr > 0 && *dr <= bm_vertoffs && *drm == 0) selbuf[*dr] = 1;
- dr++; drm++;
+ if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) selbuf[*dr] = 1;
+ dr++; dr_mask++;
}
IMB_freeImBuf(buf);
- IMB_freeImBuf(bufmask);
+ MEM_freeN(dr_mask_arr);
return true;
}
@@ -1233,7 +1180,7 @@ static void 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);
- BM_ITER_ELEM(f, &iterf, eed, BM_FACES_OF_EDGE) {
+ BM_ITER_ELEM (f, &iterf, eed, BM_FACES_OF_EDGE) {
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
float cent[3];
float co[2], tdist;
@@ -2509,7 +2456,7 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op)
int offset = RNA_int_get(op->ptr, "offset");
/* so input of offset zero ends up being (nth - 1) */
- offset = (offset + (nth - 1)) % nth;
+ offset = mod_i(offset, nth);
if (edbm_deselect_nth(em, nth, offset) == false) {
BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
@@ -2537,7 +2484,7 @@ void MESH_OT_select_nth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100);
- RNA_def_int(ot->srna, "offset", 0, 0, INT_MAX, "Offset", "", 0, 100);
+ RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100);
}
void em_setup_viewcontext(bContext *C, ViewContext *vc)
@@ -2609,8 +2556,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
- BMFace **stack = MEM_mallocN(sizeof(BMFace *) * bm->totface, __func__);
- STACK_DECLARE(stack);
+ BLI_LINKSTACK_DECLARE(stack, BMFace *);
BMIter iter, liter, liter2;
BMFace *f;
@@ -2619,6 +2565,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BLI_LINKSTACK_INIT(stack);
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if ((BM_elem_flag_test(f, BM_ELEM_HIDDEN) != 0) ||
@@ -2628,7 +2575,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
continue;
}
- STACK_INIT(stack);
+ BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
do {
BM_face_select_set(bm, f, true);
@@ -2648,16 +2595,14 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
angle = angle_normalized_v3v3(f->no, l2->f->no);
if (angle < angle_limit) {
- STACK_PUSH(stack, l2->f);
+ BLI_LINKSTACK_PUSH(stack, l2->f);
}
}
}
- } while ((f = STACK_POP(stack)));
+ } while ((f = BLI_LINKSTACK_POP(stack)));
}
- STACK_FREE(stack);
-
- MEM_freeN(stack);
+ BLI_LINKSTACK_FREE(stack);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 4610bb89ae4..9e5782c12f2 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -29,6 +29,8 @@
* \ingroup edmesh
*/
+#include <stddef.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_key_types.h"
@@ -43,6 +45,7 @@
#include "BLI_noise.h"
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_sort_utils.h"
#include "BKE_material.h"
#include "BKE_context.h"
@@ -892,14 +895,30 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
BMOperator bmop;
+ ListBase bm_selected_store = {NULL, NULL};
+
+ /* de-select all would clear otherwise */
+ SWAP(ListBase, bm->selected, bm_selected_store);
EDBM_op_init(em, &bmop, op, "duplicate geom=%hvef", BM_ELEM_SELECT);
- BMO_op_exec(em->bm, &bmop);
+ BMO_op_exec(bm, &bmop);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+
+ /* rebuild editselection */
+ bm->selected = bm_selected_store;
+
+ if (bm->selected.first) {
+ BMOpSlot *slot_vert_map_out = BMO_slot_get(bmop.slots_out, "vert_map.out");
+ BMOpSlot *slot_edge_map_out = BMO_slot_get(bmop.slots_out, "edge_map.out");
+ BMOpSlot *slot_face_map_out = BMO_slot_get(bmop.slots_out, "face_map.out");
+
+ BMO_mesh_selected_remap(bm, slot_vert_map_out, slot_edge_map_out, slot_face_map_out);
+ }
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
@@ -964,12 +983,6 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static const EnumPropertyItem direction_items[] = {
- {false, "CW", 0, "Clockwise", ""},
- {true, "CCW", 0, "Counter Clockwise", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
/* only accepts 1 selected edge, or 2 selected faces */
static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
{
@@ -2292,7 +2305,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
mouse_path = MEM_mallocN(len * sizeof(*mouse_path), __func__);
/* get the cut curve */
- RNA_BEGIN(op->ptr, itemptr, "path")
+ RNA_BEGIN (op->ptr, itemptr, "path")
{
RNA_float_get_array(&itemptr, "loc", (float *)&mouse_path[len]);
}
@@ -2399,7 +2412,7 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
}
-static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
Base *base_new;
Object *obedit = base_old->object;
@@ -2441,7 +2454,7 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_btmesh = NULL;
- return true;
+ return base_new;
}
static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
@@ -2452,7 +2465,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM
/* sel -> tag */
BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, BM_ELEM_SELECT);
- return mesh_separate_tagged(bmain, scene, base_old, bm_old);
+ return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
}
/* flush a hflag to from verts to edges/faces */
@@ -2492,6 +2505,63 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
}
}
+/**
+ * Sets an object to a single material. from one of its slots.
+ *
+ * \note This could be used for split-by-material for non mesh types.
+ * \note This could take material data from another object or args.
+ */
+static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr)
+{
+ ID *obdata = ob->data;
+
+ Material ***matarar;
+ short *totcolp;
+
+ totcolp = give_totcolp_id(obdata);
+ matarar = give_matarar_id(obdata);
+
+ if ((totcolp && matarar) == 0) {
+ BLI_assert(0);
+ return;
+ }
+
+ if (*totcolp) {
+ Material *ma_ob;
+ Material *ma_obdata;
+ char matbit;
+
+ if (mat_nr < ob->totcol) {
+ ma_ob = ob->mat[mat_nr];
+ matbit = ob->matbits[mat_nr];
+ }
+ else {
+ ma_ob = NULL;
+ matbit = 0;
+ }
+
+ if (mat_nr < *totcolp) {
+ ma_obdata = (*matarar)[mat_nr];
+ }
+ else {
+ ma_obdata = NULL;
+ }
+
+ BKE_material_clear_id(obdata, true);
+ BKE_material_resize_object(ob, 1, true);
+ BKE_material_resize_id(obdata, 1, true);
+
+ ob->mat[0] = ma_ob;
+ ob->matbits[0] = matbit;
+ (*matarar)[0] = ma_obdata;
+ }
+ else {
+ BKE_material_clear_id(obdata, true);
+ BKE_material_resize_object(ob, 0, true);
+ BKE_material_resize_id(obdata, 0, true);
+ }
+}
+
static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
BMFace *f_cmp, *f;
@@ -2499,6 +2569,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
bool result = false;
while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
+ Base *base_new;
const short mat_nr = f_cmp->mat_nr;
int tot = 0;
@@ -2522,11 +2593,22 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
/* leave the current object with some materials */
if (tot == bm_old->totface) {
+ mesh_separate_material_assign_mat_nr(base_old->object, mat_nr);
+
+ /* since we're in editmode, must set faces here */
+ BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
+ f->mat_nr = 0;
+ }
break;
}
/* Move selection into a separate object */
- result |= mesh_separate_tagged(bmain, scene, base_old, bm_old);
+ base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old);
+ if (base_new) {
+ mesh_separate_material_assign_mat_nr(base_new->object, mat_nr);
+ }
+
+ result |= (base_new != NULL);
}
return result;
@@ -2585,7 +2667,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
/* Move selection into a separate object */
- result |= mesh_separate_tagged(bmain, scene, base_old, bm_old);
+ result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
}
return result;
@@ -2747,6 +2829,146 @@ void MESH_OT_fill(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division");
}
+
+/* -------------------------------------------------------------------- */
+/* Grid Fill (and helper functions) */
+
+static bool bm_edge_test_fill_grid_cb(BMEdge *e, void *UNUSED(bm_v))
+{
+ return BM_elem_flag_test_bool(e, BM_ELEM_TAG);
+}
+
+static float edbm_fill_grid_vert_tag_angle(BMVert *v)
+{
+ BMIter iter;
+ BMEdge *e_iter;
+ BMVert *v_pair[2];
+ int i = 0;
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
+ v_pair[i++] = BM_edge_other_vert(e_iter, v);
+ }
+ }
+ BLI_assert(i == 2);
+
+ return fabsf((float)M_PI - angle_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co));
+}
+
+/**
+ * non-essential utility function to select 2 open edge loops from a closed loop.
+ */
+static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span_calc)
+{
+ BMEdge *e;
+ BMIter iter;
+ int count;
+ int span = *r_span;
+
+ ListBase eloops = {NULL};
+ struct BMEdgeLoopStore *el_store;
+ // LinkData *el_store;
+
+ /* select -> tag */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
+ }
+
+ count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
+ el_store = eloops.first;
+
+ if (count == 1 && BM_edgeloop_is_closed(el_store) && (BM_edgeloop_length_get(el_store) & 1) == 0) {
+ /* be clever! detect 2 edge loops from one closed edge loop */
+ const int verts_len = BM_edgeloop_length_get(el_store);
+ ListBase *verts = BM_edgeloop_verts_get(el_store);
+ BMVert *v_act = BM_mesh_active_vert_get(bm);
+ LinkData *v_act_link;
+ BMEdge **edges = MEM_mallocN(sizeof(*edges) * verts_len, __func__);
+ int i;
+
+ if (v_act && (v_act_link = BLI_findptr(verts, v_act, offsetof(LinkData, data)))) {
+ /* pass */
+ }
+ else {
+ /* find the vertex with the best angle (a corner vertex) */
+ LinkData *v_link, *v_link_best = NULL;
+ float angle_best = -1.0f;
+ for (v_link = verts->first; v_link; v_link = v_link->next) {
+ const float angle = edbm_fill_grid_vert_tag_angle(v_link->data);
+ if ((angle > angle_best) || (v_link_best == NULL)) {
+ angle_best = angle;
+ v_link_best = v_link;
+ }
+ }
+
+ v_act_link = v_link_best;
+ v_act = v_act_link->data;
+ }
+
+ if (offset != 0) {
+ v_act_link = BLI_findlink(verts, offset);
+ v_act = v_act_link->data;
+ }
+
+ /* set this vertex first */
+ BLI_rotatelist_first(verts, v_act_link);
+ BM_edgeloop_edges_get(el_store, edges);
+
+
+ if (span_calc) {
+ /* calculate the span by finding the next corner in 'verts'
+ * we dont know what defines a corner exactly so find the 4 verts
+ * in the loop with the greatest angle.
+ * Tag them and use the first tagged vertex to calculate the 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__);
+ LinkData *v_link;
+ for (v_link = verts->first, i = 0; v_link; v_link = v_link->next, i++) {
+ BMVert *v = v_link->data;
+ const float angle = edbm_fill_grid_vert_tag_angle(v);
+ ele_sort[i].sort_value = angle;
+ ele_sort[i].data = v;
+
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+
+ qsort(ele_sort, verts_len, sizeof(*ele_sort), BLI_sortutil_cmp_float_reverse);
+
+ for (i = 0; i < 4; i++) {
+ BMVert *v = ele_sort[i].data;
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+
+ /* now find the first... */
+ for (v_link = verts->first, i = 0; i < verts_len / 2; v_link = v_link->next, i++) {
+ BMVert *v = v_link->data;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (v != v_act) {
+ span = i;
+ break;
+ }
+ }
+ }
+ MEM_freeN(ele_sort);
+ }
+ /* end span calc */
+
+
+ /* un-flag 'rails' */
+ for (i = 0; i < span; i++) {
+ BM_elem_flag_disable(edges[i], BM_ELEM_TAG);
+ BM_elem_flag_disable(edges[(verts_len / 2) + i], BM_ELEM_TAG);
+ }
+ MEM_freeN(edges);
+ }
+ /* else let the bmesh-operator handle it */
+
+ BM_mesh_edgeloops_free(&eloops);
+
+ *r_span = span;
+}
+
static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
{
BMOperator bmop;
@@ -2755,10 +2977,45 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
const short use_smooth = edbm_add_edge_face__smooth_get(em->bm);
const int totedge_orig = em->bm->totedge;
const int totface_orig = em->bm->totface;
+ const bool use_interp_simple = RNA_boolean_get(op->ptr, "use_interp_simple");
+ const bool use_prepare = true;
+
+
+ if (use_prepare) {
+ /* use when we have a single loop selected */
+ PropertyRNA *prop_span = RNA_struct_find_property(op->ptr, "span");
+ PropertyRNA *prop_offset = RNA_struct_find_property(op->ptr, "offset");
+ bool calc_span;
+
+ const int clamp = em->bm->totvertsel;
+ int span;
+ int offset;
+
+ if (RNA_property_is_set(op->ptr, prop_span)) {
+ span = RNA_property_int_get(op->ptr, prop_span);
+ span = min_ii(span, (clamp / 2) - 1);
+ calc_span = false;
+ }
+ else {
+ span = clamp / 4;
+ calc_span = true;
+ }
+
+ offset = RNA_property_int_get(op->ptr, prop_offset);
+ offset = clamp ? mod_i(offset, clamp) : 0;
+
+ /* in simple cases, move selection for tags, but also support more advanced cases */
+ edbm_fill_grid_prepare(em->bm, offset, &span, calc_span);
+
+ RNA_property_int_set(op->ptr, prop_span, span);
+ }
+ /* end tricky prepare code */
+
if (!EDBM_op_init(em, &bmop, op,
- "grid_fill edges=%he mat_nr=%i use_smooth=%b",
- BM_ELEM_SELECT, em->mat_nr, use_smooth))
+ "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;
}
@@ -2786,6 +3043,8 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
void MESH_OT_fill_grid(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Grid Fill";
ot->description = "Fill grid from two loops";
@@ -2797,6 +3056,13 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "span", 1, 1, INT_MAX, "Span", "Number of sides (zero disables)", 1, 100);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Number of sides (zero disables)", -100, 100);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna, "use_interp_simple", 0, "Simple Blending", "");
}
static int edbm_fill_holes_exec(bContext *C, wmOperator *op)
@@ -3070,7 +3336,7 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Dissolve Vertices";
- ot->description = "Dissolve geometry";
+ ot->description = "Dissolve verts, merge edges and faces";
ot->idname = "MESH_OT_dissolve_verts";
/* api callbacks */
@@ -3107,7 +3373,7 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Dissolve Edges";
- ot->description = "Dissolve geometry";
+ ot->description = "Dissolve edges, merging faces";
ot->idname = "MESH_OT_dissolve_edges";
/* api callbacks */
@@ -3146,7 +3412,7 @@ void MESH_OT_dissolve_faces(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Dissolve Faces";
- ot->description = "Dissolve geometry";
+ ot->description = "Dissolve faces";
ot->idname = "MESH_OT_dissolve_faces";
/* api callbacks */
@@ -4247,7 +4513,7 @@ void MESH_OT_wireframe(wmOperatorType *ot)
/* identifiers */
ot->name = "Wire Frame";
ot->idname = "MESH_OT_wireframe";
- ot->description = "Inset new faces into selected faces";
+ ot->description = "Create a solid wire-frame from faces";
/* api callbacks */
ot->exec = edbm_wireframe_exec;
@@ -4289,7 +4555,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
/* 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",
@@ -4312,9 +4579,11 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
/* Merge adjacent triangles */
if (RNA_boolean_get(op->ptr, "join_triangles")) {
- if (!EDBM_op_callf(em, op, "join_triangles faces=%S limit=%f",
- &bmop, "geom.out",
- RNA_float_get(op->ptr, "limit")))
+ if (!EDBM_op_call_and_selectf(em, op,
+ "faces.out", true,
+ "join_triangles faces=%S limit=%f",
+ &bmop, "geom.out",
+ RNA_float_get(op->ptr, "limit")))
{
EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
@@ -4372,10 +4641,17 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "symmetrize input=%hvef direction=%i",
- BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"));
+ 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);
BMO_op_exec(em->bm, &bmop);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
@@ -4403,6 +4679,7 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to");
+ RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Threshold", "", 0.00001, 0.1);
}
static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 46cab3b4416..e457f7c45af 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -662,10 +662,7 @@ static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata))
UndoMesh *um = umv;
BMesh *bm;
- const BMAllocTemplate allocsize = {um->me.totvert,
- um->me.totedge,
- um->me.totloop,
- um->me.totpoly};
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&um->me);
ob->shapenr = em->bm->shapenr = um->shapenr;
@@ -1481,7 +1478,7 @@ int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d)
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, NULL, r_hitout, NULL);
+ BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL);
if (f && BM_edge_in_face(e, f))
return NULL;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 9dcb38b9f87..287938c4002 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -95,6 +95,8 @@ void MESH_OT_primitive_ico_sphere_add(struct wmOperatorType *ot);
/* *** editmesh_bevel.c *** */
void MESH_OT_bevel(struct wmOperatorType *ot);
+/* *** editmesh_bisect.c *** */
+void MESH_OT_bisect(struct wmOperatorType *ot);
/* *** editmesh_extrude.c *** */
void MESH_OT_extrude_repeat(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 66e577975b6..83feed6756f 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -26,6 +26,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/mesh/mesh_navmesh.c
+ * \ingroup edmesh
+ */
+
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
@@ -350,7 +354,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
co[1] = bmin[1] + v[1] * ch;
co[2] = bmin[2] + v[2] * cs;
SWAP(float, co[1], co[2]);
- BM_vert_create(em->bm, co, NULL, 0);
+ BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP);
}
/* create custom data layer to save polygon idx */
@@ -381,7 +385,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
for (j = nv; j < ndv; j++) {
copy_v3_v3(co, &dverts[3 * (vbase + j)]);
SWAP(float, co[1], co[2]);
- BM_vert_create(em->bm, co, NULL, 0);
+ BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP);
}
/* need to rebuild entirely because array size changes */
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index fb0ec4e5768..64ce040c729 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -176,6 +176,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_convex_hull);
#endif
+ WM_operatortype_append(MESH_OT_bisect);
WM_operatortype_append(MESH_OT_symmetrize);
WM_operatortype_append(MESH_OT_symmetry_snap);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index d012a8ac656..5ee980ef5cb 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -178,7 +178,6 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (kb->data) MEM_freeN(kb->data);
kb->data = MEM_callocN(sizeof(float) * 3 * totvert, "join_shapekey");
kb->totelem = totvert;
- kb->weights = NULL;
}
}
else if (haskey) {
@@ -315,7 +314,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* standard data */
CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
- CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert);
+ CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert);
/* vertex groups */
dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT);
@@ -416,7 +415,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
if (me->totedge) {
CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
- CustomData_copy_data(&me->edata, &edata, 0, edgeofs, me->totedge);
+ CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge);
for (a = 0; a < me->totedge; a++, medge++) {
medge->v1 += vertofs;
@@ -438,7 +437,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop);
- CustomData_copy_data(&me->ldata, &ldata, 0, loopofs, me->totloop);
+ CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop);
for (a = 0; a < me->totloop; a++, mloop++) {
mloop->v += vertofs;
@@ -462,7 +461,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly);
- CustomData_copy_data(&me->pdata, &pdata, 0, polyofs, me->totpoly);
+ CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly);
for (a = 0; a < me->totpoly; a++, mpoly++) {
mpoly->loopstart += loopofs;
@@ -1012,6 +1011,31 @@ BMVert *editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *e
}
}
+/**
+ * Wrapper for objectmode/editmode.
+ *
+ * call #EDBM_index_arrays_ensure first for editmesh.
+ */
+int ED_mesh_mirror_get_vert(Object *ob, int index)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ int index_mirr;
+
+ if (em) {
+ BMVert *eve, *eve_mirr;
+ eve = EDBM_vert_at_index(em, index);
+ eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology);
+ index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
+ }
+ else {
+ index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology);
+ }
+
+ return index_mirr;
+}
+
#if 0
static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float *mirrCent, float *face_cent)
@@ -1136,7 +1160,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
mesh_octree_table(ob, em, NULL, 'e');
- fhash = BLI_ghash_new(mirror_facehash, mirror_facecmp, "mirror_facehash gh");
+ fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
for (a = 0, mf = mface; a < me->totface; a++, mf++)
BLI_ghash_insert(fhash, mf, mf);
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index de0af1d1bb8..68ca55651a8 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -98,7 +98,7 @@ void load_editMball(Object *UNUSED(obedit))
}
/* Add metaelem primitive to metaball object (which is in edit mode) */
-MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[4][4], float dia, int type, int UNUSED(newname))
+MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[4][4], float dia, int type)
{
MetaBall *mball = (MetaBall *)obedit->data;
MetaElem *ml;
@@ -112,6 +112,8 @@ MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[
ml = BKE_mball_element_add(mball, type);
ml->rad *= dia;
+ mball->wiresize *= dia;
+ mball->rendersize *= dia;
copy_v3_v3(&ml->x, mat[3]);
ml->flag |= SELECT;
@@ -499,19 +501,13 @@ bool mouse_mball(bContext *C, const int mval[2], bool extend, bool deselect, boo
/* free all MetaElems from ListBase */
static void freeMetaElemlist(ListBase *lb)
{
- MetaElem *ml, *next;
+ MetaElem *ml;
if (lb == NULL) return;
- ml = lb->first;
- while (ml) {
- next = ml->next;
- BLI_remlink(lb, ml);
+ while ((ml = BLI_pophead(lb))) {
MEM_freeN(ml);
- ml = next;
}
-
- lb->first = lb->last = NULL;
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index ce61b4fce50..db68a0eca4d 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -191,7 +191,7 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3],
* Returns standard diameter. */
float ED_object_new_primitive_matrix(bContext *C, Object *obedit,
const float loc[3], const float rot[3], float primmat[4][4],
- int apply_diameter)
+ bool apply_diameter)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -236,7 +236,15 @@ static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(sc
RNA_struct_idprops_unset(ptr, "rotation");
}
-void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode)
+void ED_object_add_unit_props(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+}
+
+void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
{
PropertyRNA *prop;
@@ -261,8 +269,8 @@ void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
-int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], float rot[3],
- bool *enter_editmode, unsigned int *layer, bool *is_view_aligned)
+bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], float rot[3],
+ bool *enter_editmode, unsigned int *layer, bool *is_view_aligned)
{
View3D *v3d = CTX_wm_view3d(C);
unsigned int _layer;
@@ -356,16 +364,16 @@ int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], fl
if (layer && *layer == 0) {
BKE_report(op->reports, RPT_ERROR, "Property 'layer' has no values set");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* For object add primitive operators.
* Do not call undo push in this function (users of this function have to). */
Object *ED_object_add_type(bContext *C, int type, const float loc[3], const float rot[3],
- int enter_editmode, unsigned int layer)
+ bool enter_editmode, unsigned int layer)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -570,6 +578,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
float mat[4][4];
float dia;
+ WM_operator_view3d_unit_defaults(C, op);
if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
@@ -577,12 +586,14 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
obedit = ED_object_add_type(C, OB_MBALL, loc, rot, TRUE, layer);
newob = true;
}
- else
+ else {
DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ }
- dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, FALSE);
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
+ dia = RNA_float_get(op->ptr, "radius");
- add_metaball_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"), newob);
+ add_metaball_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
/* userdef */
if (newob && !enter_editmode) {
@@ -602,7 +613,7 @@ void OBJECT_OT_metaball_add(wmOperatorType *ot)
ot->idname = "OBJECT_OT_metaball_add";
/* api callbacks */
- ot->invoke = WM_menu_invoke;/* object_metaball_add_invoke; */
+ ot->invoke = WM_menu_invoke;
ot->exec = object_metaball_add_exec;
ot->poll = ED_operator_scene_editable;
@@ -611,6 +622,7 @@ void OBJECT_OT_metaball_add(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", metaelem_type_items, 0, "Primitive", "");
+ ED_object_add_unit_props(ot);
ED_object_add_generic_props(ot, TRUE);
}
@@ -1243,7 +1255,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob->parent = NULL;
ob->constraints.first = ob->constraints.last = NULL;
- ob->disp.first = ob->disp.last = NULL;
+ ob->curve_cache = NULL;
ob->transflag &= ~OB_DUPLI;
ob->lay = base->lay;
@@ -1385,7 +1397,7 @@ static EnumPropertyItem convert_target_items[] = {
static void curvetomesh(Scene *scene, Object *ob)
{
- if (ob->disp.first == NULL)
+ if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
BKE_displist_make_curveTypes(scene, ob, 0); /* force creation */
BKE_mesh_from_nurbs(ob); /* also does users */
@@ -1553,7 +1565,7 @@ static int convert_exec(bContext *C, wmOperator *op)
cu = newob->data;
- if (!newob->disp.first)
+ if ( !newob->curve_cache || !newob->curve_cache->disp.first)
BKE_displist_make_curveTypes(scene, newob, 0);
newob->type = OB_CURVE;
@@ -1595,7 +1607,7 @@ static int convert_exec(bContext *C, wmOperator *op)
curvetomesh(scene, newob);
/* meshes doesn't use displist */
- BKE_displist_free(&newob->disp);
+ BKE_object_free_curve_cache(newob);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -1616,7 +1628,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
/* meshes doesn't use displist */
- BKE_displist_free(&newob->disp);
+ BKE_object_free_curve_cache(newob);
}
curvetomesh(scene, newob);
@@ -1635,7 +1647,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
}
- if (!baseob->disp.first) {
+ if (!baseob->curve_cache || !baseob->curve_cache->disp.first) {
BKE_displist_make_mball(scene, baseob);
}
@@ -1658,7 +1670,7 @@ static int convert_exec(bContext *C, wmOperator *op)
for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
}
- BKE_mesh_from_metaball(&baseob->disp, newob->data);
+ BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data);
if (obact->type == OB_MBALL) {
basact = basen;
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 8b674cf1e50..376f2ed294b 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -264,40 +264,68 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l
}
typedef enum ClearFlag {
- CLEAR_NORMAL = 1
+ CLEAR_TANGENT_NORMAL = 1,
+ CLEAR_DISPLACEMENT = 2
} ClearFlag;
-static void clear_images(MTFace *mtface, int totface, ClearFlag flag)
+static void clear_single_image(Image *image, ClearFlag flag)
{
- int a;
const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
+ const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
+ const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
+
+ if ((image->id.flag & LIB_DOIT) == 0) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+
+ if (flag == CLEAR_TANGENT_NORMAL)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ else if (flag == CLEAR_DISPLACEMENT)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
+ else
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+
+ image->id.flag |= LIB_DOIT;
- for (a = 0; a < totface; a++)
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+}
+
+static void clear_images(MTFace *mtface, int totface, ClearFlag flag)
+{
+ int a;
+
+ for (a = 0; a < totface; a++) {
mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ }
for (a = 0; a < totface; a++) {
- Image *ima = mtface[a].tpage;
+ clear_single_image(mtface[a].tpage, flag);
+ }
- if ((ima->id.flag & LIB_DOIT) == 0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ for (a = 0; a < totface; a++) {
+ mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ }
+}
- if (flag == CLEAR_NORMAL)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
- else
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+static void clear_images_poly(MTexPoly *mtpoly, int totpoly, ClearFlag flag)
+{
+ int a;
- ima->id.flag |= LIB_DOIT;
+ for (a = 0; a < totpoly; a++) {
+ mtpoly[a].tpage->id.flag &= ~LIB_DOIT;
+ }
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
+ for (a = 0; a < totpoly; a++) {
+ clear_single_image(mtpoly[a].tpage, flag);
}
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ for (a = 0; a < totpoly; a++) {
+ mtpoly[a].tpage->id.flag &= ~LIB_DOIT;
+ }
}
static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
@@ -313,14 +341,20 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
Mesh *me;
+ ClearFlag clear_flag = 0;
ob = base->object;
me = (Mesh *)ob->data;
- if (scene->r.bake_mode == RE_BAKE_NORMALS && scene->r.bake_normal_space == R_BAKE_SPACE_TANGENT)
- clear_images(me->mtface, me->totface, CLEAR_NORMAL);
- else
- clear_images(me->mtface, me->totface, 0);
+ if (scene->r.bake_mode == RE_BAKE_NORMALS) {
+ clear_flag = CLEAR_TANGENT_NORMAL;
+ }
+ else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
+ clear_flag = CLEAR_DISPLACEMENT;
+ }
+
+ clear_images(me->mtface, me->totface, clear_flag);
+ clear_images_poly(me->mtpoly, me->totpoly, clear_flag);
}
CTX_DATA_END;
}
@@ -414,11 +448,16 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
for (data = bkj->data.first; data; data = data->next) {
DerivedMesh *dm = data->lores_dm;
MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ ClearFlag clear_flag = 0;
+
+ if (bkj->mode == RE_BAKE_NORMALS) {
+ clear_flag = CLEAR_TANGENT_NORMAL;
+ }
+ else if (bkj->mode == RE_BAKE_DISPLACEMENT) {
+ clear_flag = CLEAR_DISPLACEMENT;
+ }
- if (bkj->mode == RE_BAKE_NORMALS)
- clear_images(mtface, dm->getNumTessFaces(dm), CLEAR_NORMAL);
- else
- clear_images(mtface, dm->getNumTessFaces(dm), 0);
+ clear_images(mtface, dm->getNumTessFaces(dm), clear_flag);
}
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 7f7a0777bbf..bd4c2e997fe 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -79,6 +79,7 @@
#include "BKE_softbody.h"
#include "BKE_modifier.h"
#include "BKE_editmesh.h"
+#include "BKE_report.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -556,11 +557,20 @@ void ED_object_editmode_enter(bContext *C, int flag)
if (flag & EM_WAITCURSOR) waitcursor(0);
}
-static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+static int editmode_toggle_exec(bContext *C, wmOperator *op)
{
+ const int mode_flag = OB_MODE_EDIT;
+ const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
ToolSettings *toolsettings = CTX_data_tool_settings(C);
- if (!CTX_data_edit_object(C))
+ if (!is_mode_set) {
+ Scene *scene = CTX_data_scene(C);
+ if (!ED_object_mode_compat_set(C, scene->basact->object, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ 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] */
@@ -582,10 +592,7 @@ static int editmode_toggle_poll(bContext *C)
if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT))
return 0;
- return (ob->type == OB_MESH || ob->type == OB_ARMATURE ||
- ob->type == OB_FONT || ob->type == OB_MBALL ||
- ob->type == OB_LATTICE || ob->type == OB_SURF ||
- ob->type == OB_CURVE);
+ return (ELEM7(ob->type, OB_MESH, OB_ARMATURE, OB_FONT, OB_MBALL, OB_LATTICE, OB_SURF, OB_CURVE));
}
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
@@ -598,7 +605,6 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
/* api callbacks */
ot->exec = editmode_toggle_exec;
-
ot->poll = editmode_toggle_poll;
/* flags */
@@ -607,16 +613,25 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
/* *************************** */
-static int posemode_exec(bContext *C, wmOperator *UNUSED(op))
+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;
- if (base->object->type == OB_ARMATURE) {
- if (base->object == CTX_data_edit_object(C)) {
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ 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);
}
- else if (base->object->mode & OB_MODE_POSE)
+ else if (is_mode_set)
ED_armature_exit_posemode(C, base);
else
ED_armature_enter_posemode(C, base);
@@ -1417,8 +1432,9 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
space = size[0] / size[1];
}
else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
- Curve *cu = ob->data;
- space = cu->size[0] / cu->size[1];
+ float size[3];
+ BKE_curve_texspace_get(ob->data, NULL, NULL, size);
+ space = size[0] / size[1];
}
x = ibuf->x / space;
@@ -1455,12 +1471,14 @@ static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(
ob = CTX_data_active_object(C);
if (ob) {
+ const bool use_mode_particle_edit = (ob->particlesystem.first != NULL) || (ob->soft != NULL) ||
+ (modifiers_findByType(ob, eModifierType_Cloth) != NULL);
while (input->identifier) {
if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
- (input->value == OB_MODE_PARTICLE_EDIT && ob->particlesystem.first) ||
- ((input->value == OB_MODE_SCULPT || input->value == OB_MODE_VERTEX_PAINT ||
- input->value == OB_MODE_WEIGHT_PAINT || input->value == OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
+ (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
+ (ELEM4(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
+ OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
(input->value == OB_MODE_OBJECT))
{
RNA_enum_item_add(&item, &totitem, input);
@@ -1500,19 +1518,21 @@ static const char *object_mode_op_string(int mode)
}
/* checks the mode to be set is compatible with the object
- * should be made into a generic function */
-static bool object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *ob)
+ * should be made into a generic function
+ */
+static bool object_mode_compat_test(Object *ob, ObjectMode mode)
{
- ObjectMode mode = RNA_enum_get(op->ptr, "mode");
-
if (ob) {
if (mode == OB_MODE_OBJECT)
return true;
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))
+ 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:
@@ -1535,6 +1555,30 @@ static bool object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *
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);
+ 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_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
@@ -1542,25 +1586,31 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
ObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
int toggle = RNA_boolean_get(op->ptr, "toggle");
- if (!ob || !object_mode_set_compat(C, op, ob))
+ if (!ob || !object_mode_compat_test(ob, mode))
return OPERATOR_PASS_THROUGH;
- /* Exit current mode if it's not the mode we're setting */
- if (ob->mode != OB_MODE_OBJECT && ob->mode != mode)
- WM_operator_name_call(C, object_mode_op_string(ob->mode), WM_OP_EXEC_REGION_WIN, NULL);
+ if (ob->mode != mode) {
+ /* we should be able to remove this call, each operator calls */
+ ED_object_mode_compat_set(C, ob, mode, op->reports);
+ }
- if (mode != OB_MODE_OBJECT) {
+ /* Exit current mode if it's not the mode we're setting */
+ if (mode != OB_MODE_OBJECT && (ob->mode != mode || toggle)) {
/* Enter new mode */
- if (ob->mode != mode || toggle)
- WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL);
-
- if (toggle) {
- 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) {
- WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
- }
+ WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL);
+ }
+
+ if (toggle) {
+ /* Special case for Object mode! */
+ if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT && ob->restore_mode != OB_MODE_OBJECT) {
+ WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ 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) {
+ WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL);
}
}
@@ -1569,6 +1619,8 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
void OBJECT_OT_mode_set(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Set Object Mode";
ot->description = "Sets the object interaction mode";
@@ -1584,14 +1636,20 @@ void OBJECT_OT_mode_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", "");
RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void ED_object_toggle_modes(bContext *C, int mode)
{
+ /* Couldn't we use object_mode_op_string() here?
+ * Also, if several bits are set in mode, several toggle ops will be called, is this expected?
+ * If so, would be nice to explain why. ;) --mont29
+ */
if (mode & OB_MODE_SCULPT)
WM_operator_name_call(C, "SCULPT_OT_sculptmode_toggle", WM_OP_EXEC_REGION_WIN, NULL);
if (mode & OB_MODE_VERTEX_PAINT)
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 1f52346222c..a9fd3ce1288 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -289,7 +289,7 @@ void GROUP_OT_objects_remove_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove From All Groups";
- ot->description = "Remove selected objects from all groups or a selected group";
+ ot->description = "Remove selected objects from all groups";
ot->idname = "GROUP_OT_objects_remove_all";
/* api callbacks */
@@ -335,7 +335,7 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
/* identifiers */
ot->name = "Remove From Group";
- ot->description = "Remove selected objects from all groups or a selected group";
+ ot->description = "Remove selected objects from a group";
ot->idname = "GROUP_OT_objects_remove";
/* api callbacks */
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 5b20489c9cb..37656f82b25 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -569,7 +569,7 @@ void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hook to Selected Object";
- ot->description = "Hook selected vertices to the first selected Object";
+ ot->description = "Hook selected vertices to the first selected object";
ot->idname = "OBJECT_OT_hook_add_selob";
/* api callbacks */
@@ -603,7 +603,7 @@ void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hook to New Object";
- ot->description = "Hook selected vertices to the first selected Object";
+ ot->description = "Hook selected vertices to a newly created object";
ot->idname = "OBJECT_OT_hook_add_newob";
/* api callbacks */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 03d51fcbe82..0ba84e27420 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -637,9 +637,9 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
cu = ob->data;
BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
- vertexCos = BKE_curve_vertexCos_get(cu, &cu->nurb, &numVerts);
+ vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
- BK_curve_vertexCos_apply(cu, &cu->nurb, vertexCos);
+ BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
MEM_freeN(vertexCos);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 52f51cfcf48..be4948d8a80 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -55,6 +55,7 @@
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_string.h"
+#include "BLI_kdtree.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
@@ -584,12 +585,12 @@ EnumPropertyItem prop_make_parent_types[] = {
{PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
{PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
{PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
- {PAR_TRIA, "TRIA", 0, "Triangle", ""},
+ {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
{0, NULL, 0, NULL, NULL}
};
int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par,
- int partype, int xmirror, int keep_transform)
+ int partype, bool xmirror, bool keep_transform, const int vert_par[3])
{
bPoseChannel *pchan = NULL;
int pararm = ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
@@ -718,8 +719,17 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
if (pchan->bone)
pchan->bone->flag |= BONE_RELATIVE_PARENTING;
}
- else
+ else if (partype == PAR_VERTEX) {
+ ob->partype = PARVERT1;
+ ob->par1 = vert_par[0];
+ }
+ else if (partype == PAR_VERTEX_TRI) {
+ ob->partype = PARVERT3;
+ copy_v3_v3_int(&ob->par1, vert_par);
+ }
+ else {
ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
/* constraint */
if (partype == PAR_PATH_CONST) {
@@ -766,25 +776,83 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
return 1;
}
+
+
+static void parent_set_vert_find(KDTree *tree, Object *child, int vert_par[3], bool is_tri)
+{
+ const float *co_find = child->obmat[3];
+ if (is_tri) {
+ KDTreeNearest nearest[3];
+ int tot;
+
+ tot = BLI_kdtree_find_nearest_n(tree, co_find, NULL, nearest, 3);
+ BLI_assert(tot == 3);
+
+ vert_par[0] = nearest[0].index;
+ vert_par[1] = nearest[1].index;
+ vert_par[2] = nearest[2].index;
+
+ BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
+ }
+ else {
+ vert_par[0] = BLI_kdtree_find_nearest(tree, co_find, NULL, NULL);
+ BLI_assert(vert_par[0] >= 0);
+ vert_par[1] = 0;
+ vert_par[2] = 0;
+ }
+}
+
static int parent_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *par = ED_object_active_context(C);
int partype = RNA_enum_get(op->ptr, "type");
- int xmirror = RNA_boolean_get(op->ptr, "xmirror");
- int keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
- int ok = 1;
+ bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
+ bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
+ bool ok = true;
+
+ /* vertex parent (kdtree) */
+ const bool is_vert_par = ELEM(partype, PAR_VERTEX, PAR_VERTEX_TRI);
+ const bool is_tri = partype == PAR_VERTEX_TRI;
+ int tree_tot;
+ struct KDTree *tree = NULL;
+ int vert_par[3] = {0, 0, 0};
+ int *vert_par_p = is_vert_par ? vert_par : NULL;
+
+
+ if (is_vert_par) {
+ tree = BKE_object_as_kdtree(par, &tree_tot);
+ BLI_assert(tree != NULL);
+
+ if (tree_tot < (is_tri ? 3 : 1)) {
+ BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
+ ok = false;
+ goto cleanup;
+ }
+ }
+
+ /* Non vertex-parent */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform)) {
- ok = 0;
+ if (is_vert_par) {
+ parent_set_vert_find(tree, ob, vert_par, is_tri);
+ }
+
+ if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
+ ok = false;
break;
}
}
CTX_DATA_END;
+
+cleanup:
+ if (is_vert_par) {
+ BLI_kdtree_free(tree);
+ }
+
if (!ok)
return OPERATOR_CANCELLED;
@@ -835,6 +903,12 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE);
}
+ /* vertex parenting */
+ if (OB_TYPE_SUPPORT_PARVERT(ob->type)) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI);
+ }
+
uiPupMenuEnd(C, pup);
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 366aa72f2b8..4d7abbe7c39 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -50,6 +50,7 @@
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
+#include "BKE_idcode.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@@ -379,54 +380,45 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
- int change = 1;
+ bool change = true;
/* first check if we can execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
-
- if (ob->type == OB_MESH) {
- if (ID_REAL_USERS(ob->data) > 1) {
- BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user mesh, doing nothing");
- change = 0;
- }
- }
- else if (ob->type == OB_ARMATURE) {
- if (ID_REAL_USERS(ob->data) > 1) {
- BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user armature, doing nothing");
- change = 0;
+ if (ELEM6(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) {
+ ID *obdata = ob->data;
+ if (ID_REAL_USERS(obdata) > 1) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
+ change = false;
}
- }
- else if (ob->type == OB_LATTICE) {
- if (ID_REAL_USERS(ob->data) > 1) {
- BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user lattice, doing nothing");
- change = 0;
- }
- }
- else if (ob->type == OB_MBALL) {
- if (ID_REAL_USERS(ob->data) > 1) {
- BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user metaball, doing nothing");
- change = 0;
+
+ if (obdata->lib) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
+ change = false;
}
}
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu;
- if (ID_REAL_USERS(ob->data) > 1) {
- BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user curve, doing nothing");
- change = 0;
- }
+ if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ ID *obdata = ob->data;
+ Curve *cu;
cu = ob->data;
if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
- BKE_report(reports, RPT_ERROR,
- "Neither rotation nor location could be applied to a 2D curve, doing nothing");
- change = 0;
+ BKE_reportf(reports, RPT_ERROR,
+ "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
+ change = false;
}
if (cu->key) {
- BKE_report(reports, RPT_ERROR, "Cannot apply to a curve with vertex keys, doing nothing");
- change = 0;
+ BKE_reportf(reports, RPT_ERROR,
+ "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
+ change = false;
}
}
}
@@ -435,7 +427,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
if (!change)
return OPERATOR_CANCELLED;
- change = 0;
+ change = false;
/* now execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -551,7 +543,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
}
}
else if (ob->type == OB_CAMERA) {
- MovieClip *clip = BKE_object_movieclip_get(scene, ob, FALSE);
+ MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
/* applying scale on camera actually scales clip's reconstruction.
* of there's clip assigned to camera nothing to do actually.
@@ -562,6 +554,21 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
if (apply_scale)
BKE_tracking_reconstruction_scale(&clip->tracking, ob->size);
}
+ else if (ob->type == OB_EMPTY) {
+ /* It's possible for empties too, even though they don't
+ * really have obdata, since we can simply apply the maximum
+ * scaling to the empty's drawsize.
+ *
+ * Core Assumptions:
+ * 1) Most scaled empties have uniform scaling
+ * (i.e. for visibility reasons), AND/OR
+ * 2) Preserving non-uniform scaling is not that important,
+ * and is something that many users would be willing to
+ * sacrifice for having an easy way to do this.
+ */
+ float max_scale = MAX3(ob->size[0], ob->size[1], ob->size[2]);
+ ob->empty_drawsize *= max_scale;
+ }
else {
continue;
}
@@ -585,12 +592,14 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
- change = 1;
+ change = true;
}
CTX_DATA_END;
- if (!change)
+ if (!change) {
+ BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
return OPERATOR_CANCELLED;
+ }
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -768,7 +777,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
if (ctx_ob_act) {
- BLI_rotatelist(&ctx_data_list, (LinkData *)ctx_ob_act);
+ BLI_rotatelist_first(&ctx_data_list, (LinkData *)ctx_ob_act);
}
for (tob = bmain->object.first; tob; tob = tob->id.next) {
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 294b0632015..82454baae78 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -51,6 +51,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_linklist_stack.h"
#include "BLF_translation.h"
@@ -87,7 +88,6 @@ static void vgroup_remap_update_users(Object *ob, int *map);
static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup);
static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg);
static void vgroup_delete_all(Object *ob);
-static bool ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const bool use_vert_sel);
static bool vertex_group_use_vert_sel(Object *ob)
{
@@ -208,7 +208,7 @@ void ED_vgroup_data_clamp_range(ID *id, const int total)
MDeformVert **dvert_arr;
int dvert_tot;
- if (ED_vgroup_give_parray(id, &dvert_arr, &dvert_tot, false)) {
+ if (ED_vgroup_parray_alloc(id, &dvert_arr, &dvert_tot, false)) {
int i;
for (i = 0; i < dvert_tot; i++) {
MDeformVert *dv = dvert_arr[i];
@@ -223,7 +223,7 @@ void ED_vgroup_data_clamp_range(ID *id, const int total)
}
}
-static bool ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const bool use_vert_sel)
+bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const bool use_vert_sel)
{
*dvert_tot = 0;
*dvert_arr = NULL;
@@ -326,8 +326,121 @@ static bool ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_t
return false;
}
+/**
+ * For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true.
+ * This finds the unselected mirror deform verts and copys the weights to them from the selected.
+ *
+ * \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)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+ int i;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ if (em) {
+ EDBM_index_arrays_ensure(em, BM_VERT);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ if (dvert_array[i] == NULL) {
+ /* its unselected, check if its mirror is */
+ int i_sel = ED_mesh_mirror_get_vert(ob, i);
+ if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+ /* we found a match! */
+ MDeformVert *dv_src = dvert_array[i_sel];
+ MDeformVert *dv_dst = dvert_array_all[i];
+
+ defvert_copy_subset(dv_dst, dv_src, vgroup_validmap, vgroup_tot);
+
+ dvert_array[i] = dvert_array_all[i];
+ }
+ }
+ }
+
+ MEM_freeN(dvert_array_all);
+}
+
+/**
+ * Fill in the pointers for mirror verts (as if all mirror verts were selected too).
+ *
+ * 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)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+ int i;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ BLI_assert(dvert_tot == dvert_tot_all);
+ if (em) {
+ EDBM_index_arrays_ensure(em, BM_VERT);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ if (dvert_array[i] == NULL) {
+ /* its unselected, check if its mirror is */
+ int i_sel = ED_mesh_mirror_get_vert(ob, i);
+ if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+ /* we found a match! */
+ dvert_array[i] = dvert_array_all[i];
+ }
+ }
+ }
+
+ 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)
+{
+ MDeformVert *dv;
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = dv->totweight;
+
+ while (j--) {
+ MDeformWeight *dw;
+
+ if (keep_single && dv->totweight == 1)
+ break;
+
+ dw = dv->dw + j;
+ if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
+ if (dw->weight <= epsilon) {
+ defvert_remove_group(dv, dw);
+ }
+ }
+ }
+ }
+}
+
/* returns true if the id type supports weights */
-bool ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
+bool ED_vgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
{
if (id) {
switch (GS(id->name)) {
@@ -355,7 +468,7 @@ bool ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
}
/* matching index only */
-bool ED_vgroup_copy_array(Object *ob, Object *ob_from)
+bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
{
MDeformVert **dvert_array_from, **dvf;
MDeformVert **dvert_array, **dv;
@@ -366,11 +479,11 @@ bool ED_vgroup_copy_array(Object *ob, Object *ob_from)
int defbase_tot = BLI_countlist(&ob->defbase);
bool new_vgroup = false;
- ED_vgroup_give_parray(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, false);
+ ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
if ((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) {
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, false);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
new_vgroup = true;
}
@@ -783,8 +896,8 @@ static bool ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGro
if (!me_dst->dvert) ED_vgroup_data_create(ob_dst->data);
/* Get vertex group arrays.*/
- ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, false);
- ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, use_vert_sel);
+ ED_vgroup_parray_alloc(ob_src->data, &dv_array_src, &dv_tot_src, false);
+ ED_vgroup_parray_alloc(ob_dst->data, &dv_array_dst, &dv_tot_dst, use_vert_sel);
/* Get indexes of vertex groups.*/
index_src = BLI_findindex(&ob_src->defbase, dg_src);
@@ -1031,7 +1144,7 @@ static void ED_vgroup_nr_vert_add(Object *ob,
int tot;
/* get the vert */
- ED_vgroup_give_array(ob->data, &dvert, &tot);
+ ED_vgroup_array_get(ob->data, &dvert, &tot);
if (dvert == NULL)
return;
@@ -1117,7 +1230,7 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight,
/* if there's no deform verts then create some,
*/
- if (ED_vgroup_give_array(ob->data, &dv, &tot) && dv == NULL)
+ if (ED_vgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
ED_vgroup_data_create(ob->data);
/* call another function to do the work
@@ -1142,7 +1255,7 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
/* get the deform vertices corresponding to the
* vertnum
*/
- ED_vgroup_give_array(ob->data, &dvert, &tot);
+ ED_vgroup_array_get(ob->data, &dvert, &tot);
if (dvert) {
MDeformVert *dv = &dvert[vertnum];
@@ -1335,7 +1448,7 @@ static void vgroup_duplicate(Object *ob)
icdg = (ob->actdef - 1);
/* TODO, we might want to allow only copy selected verts here? - campbell */
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, false);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
if (dvert_array) {
for (i = 0; i < dvert_tot; i++) {
@@ -1367,7 +1480,7 @@ bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, i
const int def_nr_active = ob->actdef - 1;
vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
memset(vgroup_validmap, false, *r_vgroup_tot * sizeof(*vgroup_validmap));
- if (def_nr_active < *r_vgroup_tot) {
+ if ((def_nr_active >= 0) && (def_nr_active < *r_vgroup_tot)) {
*r_subset_count = 1;
vgroup_validmap[def_nr_active] = true;
}
@@ -1419,6 +1532,20 @@ bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, i
return vgroup_validmap;
}
+/**
+ * store indices from the vgroup_validmap (faster lookups in some cases)
+ */
+void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
+ int *r_vgroup_subset_map)
+{
+ int i, j = 0;
+ for (i = 0; i < vgroup_tot; i++) {
+ if (vgroup_validmap[i]) {
+ r_vgroup_subset_map[j++] = i;
+ }
+ }
+}
+
static void vgroup_normalize(Object *ob)
{
MDeformWeight *dw;
@@ -1432,7 +1559,7 @@ static void vgroup_normalize(Object *ob)
return;
}
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
float weight_max = 0.0f;
@@ -1561,9 +1688,12 @@ static void getVerticalAndHorizontalChange(const float norm[3], float d, const f
/* A = Q - ((Q - P).N)N
* D = (a * x0 + b * y0 +c * z0 + d) */
float projA[3], projB[3];
+ float plane[4];
+
+ plane_from_point_normal_v3(plane, coord, norm);
- closest_to_plane_v3(projA, coord, norm, start);
- closest_to_plane_v3(projB, coord, norm, end);
+ closest_to_plane_v3(projA, plane, start);
+ closest_to_plane_v3(projB, plane, end);
/* (vertical and horizontal refer to the plane's y and xz respectively)
* vertical distance */
dists[index] = dot_v3v3(norm, end) + d;
@@ -1833,9 +1963,10 @@ static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const
MDeformVert *dv, **dvert_array = NULL;
int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
@@ -1860,6 +1991,11 @@ 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);
+ }
+
MEM_freeN(dvert_array);
}
}
@@ -1876,7 +2012,7 @@ static void vgroup_normalize_all(Object *ob, const bool lock_active)
return;
}
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
const int defbase_tot = BLI_countlist(&ob->defbase);
@@ -1963,9 +2099,10 @@ static void vgroup_invert_subset(Object *ob,
MDeformWeight *dw;
MDeformVert *dv, **dvert_array = NULL;
int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
for (i = 0; i < dvert_tot; i++) {
@@ -1989,149 +2126,153 @@ static void vgroup_invert_subset(Object *ob,
if (dw) {
dw->weight = 1.0f - dw->weight;
- if (auto_remove && dw->weight <= 0.0f) {
- defvert_remove_group(dv, dw);
- }
+ CLAMP(dw->weight, 0.0f, 1.0f);
}
}
}
}
+ if (use_mirror && use_vert_sel) {
+ 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);
+ }
+ }
+
MEM_freeN(dvert_array);
}
}
-static void vgroup_blend(Object *ob, const float fac)
+static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
+ const int subset_count,
+ const float fac)
{
- MDeformVert *dv;
- MDeformWeight *dw;
+ const float ifac = 1.0f - fac;
+ MDeformVert **dvert_array = NULL;
int i, dvert_tot = 0;
- const int def_nr = ob->actdef - 1;
-
- BLI_assert(fac >= 0.0f && fac <= 1.0f);
+ int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
+ float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- if (ob->type != OB_MESH) {
- return;
- }
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em ? em->bm : NULL;
+ Mesh *me = em ? NULL : ob->data;
- if (BLI_findlink(&ob->defbase, def_nr)) {
- const float ifac = 1.0f - fac;
+ MeshElemMap *emap ;
+ int *emap_mem;
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em ? em->bm : NULL;
- Mesh *me = em ? NULL : ob->data;
+ BLI_SMALLSTACK_DECLARE(dv_stack, MDeformVert *);
- /* bmesh only*/
- BMEdge *eed;
- BMVert *eve;
- BMIter iter;
+ ED_vgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+ memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
- /* mesh only */
- MDeformVert *dvert_array = NULL;
+ if (bm) {
+ EDBM_index_arrays_ensure(em, BM_VERT);
+ emap = NULL;
+ emap_mem = NULL;
+ }
+ else {
+ BKE_mesh_vert_edge_map_create(&emap, &emap_mem,
+ me->medge, me->totvert, me->totedge);
+ }
- float *vg_weights;
- float *vg_users;
- int sel1, sel2;
- if (bm) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- dvert_tot = bm->totvert;
- }
- else {
- dvert_tot = me->totvert;
- dvert_array = me->dvert;
- }
-
- vg_weights = MEM_callocN(sizeof(float) * dvert_tot, "vgroup_blend_f");
- vg_users = MEM_callocN(sizeof(int) * dvert_tot, "vgroup_blend_i");
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv;
+ int dv_stack_tot = 0;
+ int j;
+ /* in case its not selected */
if (bm) {
- const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- sel1 = BM_elem_flag_test(eed->v1, BM_ELEM_SELECT);
- sel2 = BM_elem_flag_test(eed->v2, BM_ELEM_SELECT);
-
- if (sel1 != sel2) {
- int i1 /* , i2 */;
- /* i1 is always the selected one */
- if (sel1) {
- i1 = BM_elem_index_get(eed->v1);
- /* i2 = BM_elem_index_get(eed->v2); */ /* UNUSED */
- eve = eed->v2;
- }
- else {
- /* i2 = BM_elem_index_get(eed->v1); */ /* UNUSED */
- i1 = BM_elem_index_get(eed->v2);
- eve = eed->v1;
+ BMVert *v = EDBM_vert_at_index(em, i);
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ const int i_other = BM_elem_index_get(v_other);
+
+ if (BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) {
+ dv = dvert_array[i_other];
+ BLI_SMALLSTACK_PUSH(dv_stack, dv);
+ dv_stack_tot++;
}
-
- dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- dw = defvert_find_index(dv, def_nr);
- if (dw) {
- vg_weights[i1] += dw->weight;
- }
- vg_users[i1]++;
}
}
-
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && vg_users[i] > 0) {
- dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-
- dw = defvert_verify_index(dv, def_nr);
- dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight);
- /* in case of division errors */
- CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ else {
+ MVert *v = &me->mvert[i];
+ if (v->flag & SELECT) {
+ for (j = 0; j < emap[i].count; j++) {
+ MEdge *e = &me->medge[emap[i].indices[j]];
+ const int i_other = (e->v1 == i ? e->v2 : e->v1);
+ MVert *v_other = &me->mvert[i_other];
+
+ if ((v_other->flag & SELECT) == 0) {
+ dv = dvert_array[i_other];
+ BLI_SMALLSTACK_PUSH(dv_stack, dv);
+ dv_stack_tot++;
+ }
}
}
}
- else {
- MEdge *ed = me->medge;
- MVert *mv;
- for (i = 0; i < me->totedge; i++, ed++) {
- sel1 = me->mvert[ed->v1].flag & SELECT;
- sel2 = me->mvert[ed->v2].flag & SELECT;
+ if (dv_stack_tot) {
+ const float dv_mul = 1.0f / (float)dv_stack_tot;
- if (sel1 != sel2) {
- int i1, i2;
- /* i1 is always the selected one */
- if (sel1) {
- i1 = ed->v1;
- i2 = ed->v2;
- }
- else {
- i2 = ed->v1;
- i1 = ed->v2;
- }
-
- dv = &dvert_array[i2];
- dw = defvert_find_index(dv, def_nr);
- if (dw) {
- vg_weights[i1] += dw->weight;
- }
- vg_users[i1]++;
+ /* vgroup_subset_weights is zero'd at this point */
+ while ((dv = BLI_SMALLSTACK_POP(dv_stack))) {
+ for (j = 0; j < subset_count; j++) {
+ vgroup_subset_weights[j] += dv_mul * defvert_find_weight(dv, vgroup_subset_map[j]);
}
}
- mv = me->mvert;
- dv = dvert_array;
-
- for (i = 0; i < dvert_tot; i++, mv++, dv++) {
- if ((mv->flag & SELECT) && (vg_users[i] > 0)) {
- dw = defvert_verify_index(dv, def_nr);
- dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight);
+ dv = dvert_array[i];
+ for (j = 0; j < subset_count; j++) {
+ MDeformWeight *dw;
+ if (vgroup_subset_weights[j] > 0.0f) {
+ dw = defvert_verify_index(dv, vgroup_subset_map[j]);
+ }
+ else {
+ dw = defvert_find_index(dv, vgroup_subset_map[j]);
+ }
- /* in case of division errors */
+ if (dw) {
+ dw->weight = (fac * vgroup_subset_weights[j]) + (ifac * dw->weight);
CLAMP(dw->weight, 0.0f, 1.0f);
}
+
+ /* zero for next iteration */
+ vgroup_subset_weights[j] = 0.0f;
}
}
+ }
- MEM_freeN(vg_weights);
- MEM_freeN(vg_users);
+ if (bm) {
+ /* pass */
+ }
+ else {
+ MEM_freeN(emap);
+ MEM_freeN(emap_mem);
+ }
+
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+ BLI_SMALLSTACK_FREE(dv_stack);
+
+ /* 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);
+ if (dvert_array)
+ MEM_freeN(dvert_array);
}
}
@@ -2164,7 +2305,7 @@ static int vgroup_limit_total_subset(Object *ob,
const int use_vert_sel = vertex_group_use_vert_sel(ob);
int remove_tot = 0;
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
int num_to_drop = 0;
@@ -2228,39 +2369,24 @@ static void vgroup_clean_subset(Object *ob, const bool *vgroup_validmap, const i
const float epsilon, const bool keep_single)
{
MDeformVert **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ int dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
if (dvert_array) {
- MDeformVert *dv;
- MDeformWeight *dw;
-
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = dv->totweight;
-
- while (j--) {
-
- if (keep_single && dv->totweight == 1)
- break;
-
- dw = dv->dw + j;
- if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
- if (dw->weight <= epsilon) {
- defvert_remove_group(dv, dw);
- }
- }
- }
+ if (use_mirror && use_vert_sel) {
+ /* correct behavior in this case isn't well defined
+ * for now assume both sides are mirrored correctly,
+ * so cleaning one side also cleans the other */
+ 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);
+
MEM_freeN(dvert_array);
}
}
@@ -2585,7 +2711,7 @@ static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
assert(def_nr > -1);
- ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
+ ED_vgroup_array_get(ob->data, &dvert_array, &dvert_tot);
if (dvert_array) {
int i, j;
@@ -3504,8 +3630,13 @@ static int vertex_group_blend_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
float fac = RNA_float_get(op->ptr, "factor");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+
+ int subset_count, vgroup_tot;
- vgroup_blend(ob, fac);
+ const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_blend_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac);
+ MEM_freeN((void *)vgroup_validmap);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -3523,10 +3654,14 @@ static int vertex_group_blend_poll(bContext *C)
if (!(ob && !ob->id.lib && data && !data->lib))
return false;
+ if (ob->type != OB_MESH) {
+ return false;
+ }
+
if (BKE_object_is_in_editmode_vgroup(ob)) {
return true;
}
- else if ((ob->type == OB_MESH) && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
if (ME_EDIT_PAINT_SEL_MODE(((Mesh *)data)) == SCE_SELECT_VERTEX) {
return true;
}
@@ -3557,6 +3692,7 @@ void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ vgroup_operator_subset_select_props(ot, true);
prop = RNA_def_property(ot->srna, "factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "Factor", "");
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -3746,7 +3882,7 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (obact != ob) {
- if (ED_vgroup_copy_array(ob, obact)) change++;
+ if (ED_vgroup_array_copy(ob, obact)) change++;
else fail++;
}
}
@@ -4040,7 +4176,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
else {
int dvert_tot = 0;
- ED_vgroup_give_array(ob->data, &dvert, &dvert_tot);
+ ED_vgroup_array_get(ob->data, &dvert, &dvert_tot);
/*create as necessary*/
if (dvert) {
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index 5cb74e1ca09..568802dd7a0 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -18,6 +18,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/physics/dynamicpaint_ops.c
+ * \ingroup edphys
+ */
+
#include <math.h>
#include <stdio.h>
#include <string.h>
@@ -384,7 +388,7 @@ static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op)
/* Clear bake */
canvas->flags &= ~MOD_DPAINT_BAKING;
if (!G.background) {
- WM_cursor_restore(win);
+ WM_cursor_modal_restore(win);
}
dynamicPaint_freeSurfaceData(surface);
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index d6bb394ff79..b0e19d04e35 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -69,6 +69,7 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "ED_object.h"
#include "ED_physics.h"
#include "ED_mesh.h"
#include "ED_particle.h"
@@ -2452,7 +2453,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
- totn= BLI_kdtree_find_n_nearest(tree, 10, co, NULL, nearest);
+ totn = BLI_kdtree_find_nearest_n(tree, co, NULL, nearest, 10);
for (n=0; n<totn; n++) {
/* this needs a custom threshold still */
@@ -3458,7 +3459,7 @@ static int brush_add(PEData *data, short number)
float maxd, totw=0.0, weight[3];
psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
- maxw= BLI_kdtree_find_n_nearest(tree, 3, co1, NULL, ptn);
+ maxw = BLI_kdtree_find_nearest_n(tree, co1, NULL, ptn, 3);
maxd= ptn[maxw-1].dist;
@@ -4345,23 +4346,36 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache,
static int particle_edit_toggle_poll(bContext *C)
{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!scene || !ob || ob->id.lib)
+ if (ob == NULL || ob->type != OB_MESH)
return 0;
-
- return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) || modifiers_findByType(ob, eModifierType_Softbody));
+ if (!ob->data || ((ID *)ob->data)->lib)
+ return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
+
+ return (ob->particlesystem.first ||
+ modifiers_findByType(ob, eModifierType_Cloth) ||
+ modifiers_findByType(ob, eModifierType_Softbody));
}
-static int particle_edit_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_PARTICLE_EDIT;
+ const 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)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ if (!is_mode_set) {
PTCacheEdit *edit;
- ob->mode |= OB_MODE_PARTICLE_EDIT;
+ ob->mode |= mode_flag;
edit= PE_create_current(scene, ob);
/* mesh may have changed since last entering editmode.
@@ -4373,7 +4387,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
}
else {
- ob->mode &= ~OB_MODE_PARTICLE_EDIT;
+ ob->mode &= ~mode_flag;
toggle_particle_cursor(C, 0);
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
}
@@ -4407,7 +4421,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
ParticleSystem *psys = psys_get_current(ob);
if (psys->edit) {
- if (psys->edit->edited || 1) { // XXX okee("Lose changes done in particle mode?"))
+ if (psys->edit->edited || 1) {
PE_free_ptcache_edit(psys->edit);
psys->edit = NULL;
@@ -4433,6 +4447,11 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
+static int clear_edited_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_operator_confirm_message(C, op, "Lose changes done in particle mode? (no undo)");
+}
+
void PARTICLE_OT_edited_clear(wmOperatorType *ot)
{
/* identifiers */
@@ -4443,6 +4462,7 @@ void PARTICLE_OT_edited_clear(wmOperatorType *ot)
/* api callbacks */
ot->exec = clear_edited_exec;
ot->poll = particle_edit_toggle_poll;
+ ot->invoke = clear_edited_invoke;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index b9742c9968f..515ac330cc9 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -126,7 +126,7 @@ static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
* the job system soon anyways. */
if (win) {
baker.progressbar = (void (*)(void *, int))WM_cursor_time;
- baker.progressend = (void (*)(void *))WM_cursor_restore;
+ baker.progressend = (void (*)(void *))WM_cursor_modal_restore;
baker.progresscontext = win;
}
else {
@@ -230,7 +230,7 @@ static int ptcache_bake_exec(bContext *C, wmOperator *op)
* the job system soon anyways. */
if (win) {
baker.progressbar = (void (*)(void *, int))WM_cursor_time;
- baker.progressend = (void (*)(void *))WM_cursor_restore;
+ baker.progressend = (void (*)(void *))WM_cursor_modal_restore;
baker.progresscontext = win;
}
else {
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 3a6bd05df0b..39d6f836815 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -164,7 +164,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
&scene->view_settings, &scene->display_settings,
- rxmin, rymin, rxmin + xmax, rymin + ymax, TRUE);
+ rxmin, rymin, rxmin + xmax, rymin + ymax, true);
}
/* ****************************** render invoking ***************** */
@@ -212,7 +212,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
Image *ima;
View3D *v3d = CTX_wm_view3d(C);
Main *mainp = CTX_data_main(C);
- unsigned int lay;
+ unsigned int lay_override;
const short is_animation = RNA_boolean_get(op->ptr, "animation");
const short is_write_still = RNA_boolean_get(op->ptr, "write_still");
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
@@ -226,7 +226,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
}
re = RE_NewRender(scene->id.name);
- lay = (v3d) ? v3d->lay : scene->lay;
+ lay_override = (v3d && v3d->lay != scene->lay) ? v3d->lay : 0;
G.is_break = FALSE;
RE_test_break_cb(re, NULL, render_break);
@@ -244,9 +244,9 @@ static int screen_render_exec(bContext *C, wmOperator *op)
RE_SetReports(re, op->reports);
if (is_animation)
- RE_BlenderAnim(re, mainp, scene, camera_override, lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
+ 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, srl, camera_override, lay, scene->r.cfra, is_write_still);
+ RE_BlenderFrame(re, mainp, scene, srl, camera_override, lay_override, scene->r.cfra, is_write_still);
RE_SetReports(re, NULL);
@@ -265,11 +265,12 @@ typedef struct RenderJob {
wmWindow *win;
SceneRenderLayer *srl;
struct Object *camera_override;
- int lay;
+ int lay_override;
bool v3d_override;
short anim, write_still;
Image *image;
ImageUser iuser;
+ bool image_outdated;
short *stop;
short *do_update;
float *progress;
@@ -409,9 +410,19 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
void *lock;
/* only update if we are displaying the slot being rendered */
- if (ima->render_slot != ima->last_render_slot)
+ if (ima->render_slot != ima->last_render_slot) {
+ rj->image_outdated = true;
return;
+ }
+ else if (rj->image_outdated) {
+ /* update entire render */
+ rj->image_outdated = false;
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ *(rj->do_update) = TRUE;
+ return;
+ }
+ /* update part of render */
ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
if (ibuf) {
image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
@@ -433,9 +444,9 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro
RE_SetReports(rj->re, rj->reports);
if (rj->anim)
- RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->camera_override, rj->lay, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step);
+ RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->camera_override, rj->lay_override, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step);
else
- RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->camera_override, rj->lay, rj->scene->r.cfra, rj->write_still);
+ RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->camera_override, rj->lay_override, rj->scene->r.cfra, rj->write_still);
RE_SetReports(rj->re, NULL);
}
@@ -491,7 +502,9 @@ static void render_endjob(void *rjv)
* engine API, so lets use simple and robust way for now
* - sergey -
*/
- if (rj->scene->r.layers.first != rj->scene->r.layers.last) {
+ if (rj->scene->r.layers.first != rj->scene->r.layers.last ||
+ rj->image_outdated)
+ {
void *lock;
Image *ima = rj->image;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
@@ -551,6 +564,17 @@ static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event
return OPERATOR_PASS_THROUGH;
}
+static int screen_render_cancel(bContext *C, wmOperator *op)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ Scene *scene = (Scene *) op->customdata;
+
+ /* kill on cancel, because job is using op->reports */
+ WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
+
+ return OPERATOR_CANCELLED;
+}
+
/* using context, starts job */
static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -558,14 +582,15 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
Main *mainp;
Scene *scene = CTX_data_scene(C);
SceneRenderLayer *srl = NULL;
- View3D *v3d = CTX_wm_view3d(C);
Render *re;
wmJob *wm_job;
RenderJob *rj;
Image *ima;
int jobflag;
- const short is_animation = RNA_boolean_get(op->ptr, "animation");
- const short is_write_still = RNA_boolean_get(op->ptr, "write_still");
+ const bool is_animation = RNA_boolean_get(op->ptr, "animation");
+ const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
+ const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
+ View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL;
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
const char *name;
Object *active_object = CTX_data_active_object(C);
@@ -638,7 +663,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->win = CTX_wm_window(C);
rj->srl = srl;
rj->camera_override = camera_override;
- rj->lay = scene->lay;
+ rj->lay_override = 0;
rj->anim = is_animation;
rj->write_still = is_write_still && !is_animation;
rj->iuser.scene = scene;
@@ -646,15 +671,15 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->reports = op->reports;
if (v3d) {
- if (rj->lay != v3d->lay) {
- rj->lay = v3d->lay;
+ if (scene->lay != v3d->lay) {
+ rj->lay_override = v3d->lay;
rj->v3d_override = true;
}
else if (camera_override && camera_override != scene->camera)
rj->v3d_override = true;
if (v3d->localvd)
- rj->lay |= v3d->localvd->lay;
+ rj->lay_override = scene->lay | v3d->localvd->lay;
}
/* setup job */
@@ -718,12 +743,14 @@ void RENDER_OT_render(wmOperatorType *ot)
/* api callbacks */
ot->invoke = screen_render_invoke;
ot->modal = screen_render_modal;
+ ot->cancel = screen_render_cancel;
ot->exec = screen_render_exec;
/*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */
RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
+ RNA_def_boolean(ot->srna, "use_viewport", 0, "Use 3D Viewport", "When inside a 3D viewport, use layers and camera of the viewport");
prop = RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME - 2, "Scene", "Scene to render, current scene if not specified");
@@ -804,6 +831,11 @@ static bool render_view3d_get_rects(ARegion *ar, View3D *v3d, RegionView3D *rv3d
return true;
}
+static bool render_view3d_is_valid(RenderPreview *rp)
+{
+ return (rp->rv3d->render_engine != NULL);
+}
+
/* called by renderer, checks job value */
static int render_view3d_break(void *rpv)
{
@@ -813,8 +845,9 @@ static int render_view3d_break(void *rpv)
return 1;
/* during render, rv3d->engine can get freed */
- if (rp->rv3d->render_engine == NULL)
+ if (render_view3d_is_valid(rp) == false) {
*rp->stop = 1;
+ }
return *(rp->stop);
}
@@ -928,8 +961,11 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
RE_Database_Preprocess(re);
/* conversion not completed, need to do it again */
- if (!rstats->convertdone)
- rp->engine->job_update_flag |= PR_UPDATE_DATABASE;
+ if (!rstats->convertdone) {
+ if (render_view3d_is_valid(rp)) {
+ rp->engine->job_update_flag |= PR_UPDATE_DATABASE;
+ }
+ }
// printf("dbase update\n");
}
@@ -1116,7 +1152,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
/* Try using GLSL display transform. */
if (force_fallback == false) {
- if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE)) {
+ if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, true, false)) {
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT,
@@ -1134,7 +1170,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
"render_view3d_draw");
IMB_colormanagement_buffer_make_display_space(rres.rectf, display_buffer, rres.rectx, rres.recty,
- 4, dither, NULL, &scene->display_settings);
+ 4, dither, &scene->view_settings, &scene->display_settings);
glEnable(GL_BLEND);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index e21e889d99d..21074bdc47c 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -469,7 +469,7 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
}
- WM_cursor_restore(oglrender->win);
+ WM_cursor_modal_restore(oglrender->win);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
@@ -517,7 +517,7 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
return 1;
}
-static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
+static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
OGLRender *oglrender = op->customdata;
@@ -549,12 +549,9 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
- printf("skipping existing frame \"%s\"\n", name);
-
- /* go to next frame */
- oglrender->nfra += scene->r.frame_step;
-
- return 1;
+ BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
+ ok = true;
+ goto finally;
}
}
@@ -591,7 +588,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
ibuf_save = ibuf;
if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) {
- ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings,
+ ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings,
&scene->display_settings, &scene->r.im_format);
needs_free = TRUE;
@@ -656,6 +653,9 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
/* movie stats prints have no line break */
printf("\n");
+
+finally: /* Step the frame and bail early if needed */
+
/* go to next frame */
oglrender->nfra += scene->r.frame_step;
@@ -673,7 +673,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
{
OGLRender *oglrender = op->customdata;
int anim = RNA_boolean_get(op->ptr, "animation");
- int ret;
+ bool ret;
switch (event->type) {
case ESCKEY:
@@ -698,11 +698,12 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
screen_opengl_render_end(C, op->customdata);
return OPERATOR_FINISHED;
}
- else
+ else {
ret = screen_opengl_render_anim_step(C, op);
+ }
/* stop at the end or on error */
- if (ret == 0) {
+ if (ret == false) {
return OPERATOR_FINISHED;
}
@@ -750,7 +751,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
else {
- int ret = 1;
+ bool ret = true;
if (!screen_opengl_render_anim_initialize(C, op))
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 4bd8a7d426a..2bf8a48edc4 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -587,6 +587,7 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
ID *parent = (ID *)parentp;
MTex *slot = (MTex *)slotp;
SpaceButs *sbuts = sa->spacedata.first;
+ ShaderPreview *sp = WM_jobs_customdata(wm, sa);
rcti newrect;
int ok;
int newx = BLI_rcti_size_x(rect);
@@ -608,9 +609,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
*rect = newrect;
/* start a new preview render job if signalled through sbuts->preview,
- * or if no render result was found and no preview render job is running */
+ * if no render result was found and no preview render job is running,
+ * or if the job is running and the size of preview changed */
if ((sbuts->spacetype == SPACE_BUTS && sbuts->preview) ||
- (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)))
+ (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) ||
+ (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2)))
{
sbuts->preview = 0;
ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 58c244228ed..553a543390f 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -588,6 +588,20 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot)
#ifdef WITH_FREESTYLE
+static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports)
+{
+ if (!lineset) {
+ BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ return false;
+ }
+ if (!lineset->linestyle) {
+ BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)");
+ return false;
+ }
+
+ return true;
+}
+
static int freestyle_active_module_poll(bContext *C)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
@@ -860,8 +874,13 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
return OPERATOR_CANCELLED;
}
- lineset->linestyle->id.us--;
- lineset->linestyle = BKE_copy_linestyle(lineset->linestyle);
+ if (lineset->linestyle) {
+ lineset->linestyle->id.us--;
+ lineset->linestyle = BKE_copy_linestyle(lineset->linestyle);
+ }
+ else {
+ lineset->linestyle = BKE_new_linestyle("LineStyle", NULL);
+ }
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
@@ -890,10 +909,10 @@ static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_color_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
return OPERATOR_CANCELLED;
@@ -929,10 +948,10 @@ static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_alpha_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
return OPERATOR_CANCELLED;
@@ -968,10 +987,10 @@ static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_thickness_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
return OPERATOR_CANCELLED;
@@ -1007,10 +1026,10 @@ static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
int type = RNA_enum_get(op->ptr, "type");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
+
if (BKE_add_linestyle_geometry_modifier(lineset->linestyle, type) == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
return OPERATOR_CANCELLED;
@@ -1060,8 +1079,7 @@ static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
LineStyleModifier *modifier = ptr.data;
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
@@ -1110,8 +1128,7 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
LineStyleModifier *modifier = ptr.data;
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
@@ -1161,8 +1178,7 @@ static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
LineStyleModifier *modifier = ptr.data;
int dir = RNA_enum_get(op->ptr, "direction");
- if (!lineset) {
- BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ if (!freestyle_linestyle_check_report(lineset, op->reports)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index e805b3f30fc..fccce0357a4 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1446,7 +1446,6 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type)
}
if (sl) {
-
/* swap regions */
slold->regionbase = sa->regionbase;
sa->regionbase = sl->regionbase;
@@ -1696,8 +1695,10 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
/* Note: this code scales fine, but because of rounding differences, positions of elements
* flip +1 or -1 pixel compared to redoing the entire layout again.
* Leaving in commented code for future tests */
- /* uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
- break; */
+#if 0
+ uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
+ break;
+#endif
}
else {
break;
@@ -1806,7 +1807,7 @@ void ED_region_header_init(ARegion *ar)
/* UI_UNIT_Y is defined as U variable now, depending dpi */
int ED_area_headersize(void)
{
- return (int)(1.3f * UI_UNIT_Y);
+ return (int)(HEADERY * UI_DPI_FAC);
}
void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_color[4])
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 723dce5e226..70e5aab6628 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -1091,15 +1091,18 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
if (ibuf->rect_float) {
if (ibuf->float_colorspace) {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->float_colorspace, TRUE);
+ ibuf->float_colorspace,
+ true, false);
}
else {
- ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, TRUE);
+ ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings,
+ true, false);
}
}
else {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- ibuf->rect_colorspace, FALSE);
+ ibuf->rect_colorspace,
+ false, false);
}
if (ok) {
@@ -1157,57 +1160,3 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int
glaDrawImBuf_glsl(ibuf, x, y, zoomfilter, view_settings, display_settings);
}
-
-/* Transform buffer from role to scene linear space using GLSL OCIO conversion
- *
- * See IMB_colormanagement_setup_transform_from_role_glsl description for
- * some more details
- *
- * NOTE: this only works for RGBA buffers!
- */
-int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role)
-{
- GPUOffScreen *ofs;
- char err_out[256];
- rcti display_rect;
-
- ofs = GPU_offscreen_create(width, height, err_out);
-
- if (!ofs)
- return FALSE;
-
- GPU_offscreen_bind(ofs);
-
- if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) {
- GPU_offscreen_unbind(ofs);
- GPU_offscreen_free(ofs);
- return FALSE;
- }
-
- BLI_rcti_init(&display_rect, 0, width, 0, height);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
- glaDefine2DArea(&display_rect);
-
- glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT,
- GL_NEAREST, buffer);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, buffer);
-
- IMB_colormanagement_finish_glsl_transform();
-
- /* unbind */
- GPU_offscreen_unbind(ofs);
- GPU_offscreen_free(ofs);
-
- return TRUE;
-}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 498762f1603..356db174c2f 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -327,10 +327,12 @@ static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa)
static short testsplitpoint(ScrArea *sa, char dir, float fac)
{
short x, y;
+ const short area_min_x = AREAMINX;
+ const short area_min_y = ED_area_headersize();
// area big enough?
- if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * AREAMINX)) return 0;
- if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * AREAMINY)) return 0;
+ if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * area_min_x)) return 0;
+ if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * area_min_y)) return 0;
// to be sure
CLAMP(fac, 0.0f, 1.0f);
@@ -338,10 +340,10 @@ static short testsplitpoint(ScrArea *sa, char dir, float fac)
if (dir == 'h') {
y = sa->v1->vec.y + fac * (sa->v2->vec.y - sa->v1->vec.y);
- if (y - sa->v1->vec.y < AREAMINY)
- y = sa->v1->vec.y + AREAMINY;
- else if (sa->v2->vec.y - y < AREAMINY)
- y = sa->v2->vec.y - AREAMINY;
+ if (y - sa->v1->vec.y < area_min_y)
+ y = sa->v1->vec.y + area_min_y;
+ else if (sa->v2->vec.y - y < area_min_y)
+ y = sa->v2->vec.y - area_min_y;
else y -= (y % AREAGRID);
return y;
@@ -349,10 +351,10 @@ static short testsplitpoint(ScrArea *sa, char dir, float fac)
else {
x = sa->v1->vec.x + fac * (sa->v4->vec.x - sa->v1->vec.x);
- if (x - sa->v1->vec.x < AREAMINX)
- x = sa->v1->vec.x + AREAMINX;
- else if (sa->v4->vec.x - x < AREAMINX)
- x = sa->v4->vec.x - AREAMINX;
+ if (x - sa->v1->vec.x < area_min_x)
+ x = sa->v1->vec.x + area_min_x;
+ else if (sa->v4->vec.x - x < area_min_x)
+ x = sa->v4->vec.x - area_min_x;
else x -= (x % AREAGRID);
return x;
@@ -1007,8 +1009,6 @@ void ED_screen_do_listen(bContext *C, wmNotifier *note)
win->screen->do_draw = TRUE;
break;
case NC_SCREEN:
- if (note->data == ND_SUBWINACTIVE)
- uiFreeActiveButtons(C, win->screen);
if (note->action == NA_EDITED)
win->screen->do_draw = win->screen->do_refresh = TRUE;
break;
@@ -1333,7 +1333,11 @@ void ED_screen_set_subwinactive(bContext *C, wmEvent *event)
/* notifier invokes freeing the buttons... causing a bit too much redraws */
if (oldswin != scr->subwinactive) {
region_cursor_set(win, scr->subwinactive, TRUE);
- WM_event_add_notifier(C, NC_SCREEN | ND_SUBWINACTIVE, scr);
+
+ /* this used to be a notifier, but needs to be done immediate
+ * because it can undo setting the right button as active due
+ * to delayed notifier handling */
+ uiFreeActiveButtons(C, win->screen);
}
else
region_cursor_set(win, scr->subwinactive, FALSE);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 3066b733fc5..fbdd90312dd 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -696,28 +696,39 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
sActionzoneData *sad = op->customdata;
- int deltax, deltay;
- int mindelta = sad->az->type == AZONE_REGION ? 1 : 12;
switch (event->type) {
case MOUSEMOVE:
+ {
+ bool is_gesture;
+
+ const int delta_x = (event->x - sad->x);
+ const int delta_y = (event->y - sad->y);
+
/* calculate gesture direction */
- deltax = (event->x - sad->x);
- deltay = (event->y - sad->y);
-
- if (deltay > ABS(deltax))
+ if (delta_y > ABS(delta_x))
sad->gesture_dir = 'n';
- else if (deltax > ABS(deltay))
+ else if (delta_x > ABS(delta_y))
sad->gesture_dir = 'e';
- else if (deltay < -ABS(deltax))
+ else if (delta_y < -ABS(delta_x))
sad->gesture_dir = 's';
else
sad->gesture_dir = 'w';
+ if (sad->az->type == AZONE_AREA) {
+ /* once we drag outside the actionzone, register a gesture
+ * check we're not on an edge so join finds the other area */
+ is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) &&
+ (screen_find_active_scredge(CTX_wm_screen(C), event->x, event->y) == NULL));
+ }
+ else {
+ const int delta_min = 1;
+ is_gesture = (ABS(delta_x) > delta_min || ABS(delta_y) > delta_min);
+ }
+
/* gesture is large enough? */
- if (ABS(deltax) > mindelta || ABS(deltay) > mindelta) {
-
- /* second area, for join */
+ if (is_gesture) {
+ /* second area, for join when (sa1 != sa2) */
sad->sa2 = screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
/* apply sends event */
actionzone_apply(C, op, sad->az->type);
@@ -726,6 +737,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
break;
+ }
case ESCKEY:
actionzone_exit(op);
return OPERATOR_CANCELLED;
@@ -807,7 +819,7 @@ static int area_swap_init(wmOperator *op, const wmEvent *event)
static void area_swap_exit(bContext *C, wmOperator *op)
{
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
if (op->customdata)
MEM_freeN(op->customdata);
op->customdata = NULL;
@@ -826,7 +838,7 @@ static int area_swap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_PASS_THROUGH;
/* add modal handler */
- WM_cursor_modal(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -1396,7 +1408,7 @@ static void area_split_exit(bContext *C, wmOperator *op)
op->customdata = NULL;
}
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
/* this makes sure aligned edges will result in aligned grabbing */
@@ -3928,9 +3940,11 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
/* render */
- WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "use_viewport", TRUE);
kmi = WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "animation", TRUE);
+ RNA_boolean_set(kmi->ptr, "use_viewport", TRUE);
WM_keymap_add_item(keymap, "RENDER_OT_view_cancel", ESCKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "RENDER_OT_view_show", F11KEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "RENDER_OT_play_rendered_anim", F11KEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 584d4cef133..dbe1197436b 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -77,6 +77,18 @@ typedef struct ScreenshotData {
ImageFormatData im_format;
} ScreenshotData;
+static void screenshot_read_pixels(int x, int y, int w, int h, unsigned char *rect)
+{
+ int i;
+
+ glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glFinish();
+
+ /* clear alpha, it is not set to a meaningful value in opengl */
+ for (i = 0, rect += 3; i < w * h; i++, rect += 4)
+ *rect = 255;
+}
+
/* get shot from frontbuffer */
static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy)
{
@@ -93,8 +105,7 @@ static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy)
dumprect = MEM_mallocN(sizeof(int) * (*dumpsx) * (*dumpsy), "dumprect");
glReadBuffer(GL_FRONT);
- glReadPixels(x, y, *dumpsx, *dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
- glFinish();
+ screenshot_read_pixels(x, y, *dumpsx, *dumpsy, (unsigned char*)dumprect);
glReadBuffer(GL_BACK);
}
@@ -316,8 +327,7 @@ static void screenshot_updatejob(void *sjv)
if (sj->dumprect == NULL) {
dumprect = MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect");
- glReadPixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
- glFinish();
+ screenshot_read_pixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, (unsigned char *)dumprect);
sj->dumprect = dumprect;
}
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 2c1f5b620c4..c18afd066fa 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -643,21 +643,17 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
}
if (load_tex_cursor(brush, vc, zoom)) {
+ bool do_pop = false;
+ float center[2];
glEnable(GL_BLEND);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glDepthFunc(GL_ALWAYS);
- /* scale based on tablet pressure */
- if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
- glTranslatef(0.5f, 0.5f, 0);
- glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1);
- glTranslatef(-0.5f, -0.5f, 0);
- }
-
if (ups->draw_anchored) {
const float *aim = ups->anchored_initial_mouse;
+ copy_v2_v2(center, aim);
quad.xmin = aim[0] - ups->anchored_size;
quad.ymin = aim[1] - ups->anchored_size;
quad.xmax = aim[0] + ups->anchored_size;
@@ -665,12 +661,25 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
}
else {
const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
+ center[0] = x;
+ center[1] = y;
+
quad.xmin = x - radius;
quad.ymin = y - radius;
quad.xmax = x + radius;
quad.ymax = y + radius;
}
+ /* scale based on tablet pressure */
+ if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ do_pop = true;
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslatef(center[0], center[1], 0);
+ glScalef(ups->pressure_value, ups->pressure_value, 1);
+ glTranslatef(-center[0], -center[1], 0);
+ }
+
glColor4f(U.sculpt_paint_overlay_col[0],
U.sculpt_paint_overlay_col[1],
U.sculpt_paint_overlay_col[2],
@@ -687,6 +696,9 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
glTexCoord2f(0, 1);
glVertex2f(quad.xmin, quad.ymax);
glEnd();
+
+ if (do_pop)
+ glPopMatrix();
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index db6380e920f..345db7a0ed0 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -71,18 +71,6 @@
#include <assert.h>
-static int planes_contain_v3(float (*planes)[4], int totplane, const float p[3])
-{
- int i;
-
- for (i = 0; i < totplane; i++) {
- if (dot_v3v3(planes[i], p) + planes[i][3] > 0)
- return 0;
- }
-
- return 1;
-}
-
/* return true if the element should be hidden/shown */
static int is_effected(PartialVisArea area,
float planes[4][4],
@@ -95,7 +83,7 @@ static int is_effected(PartialVisArea area,
return mask > 0.5f;
}
else {
- int inside = planes_contain_v3(planes, 4, co);
+ bool inside = isect_point_planes_v3(planes, 4, co);
return ((inside && area == PARTIALVIS_INSIDE) ||
(!inside && area == PARTIALVIS_OUTSIDE));
}
@@ -235,20 +223,20 @@ static void partialvis_update_grids(Object *ob,
}
static void partialvis_update_bmesh_verts(BMesh *bm,
- GHash *verts,
- PartialVisAction action,
- PartialVisArea area,
- float planes[4][4],
- int *any_changed,
- int *any_visible)
+ GSet *verts,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4],
+ int *any_changed,
+ int *any_visible)
{
- GHashIterator gh_iter;
+ GSetIterator gs_iter;
- GHASH_ITER (gh_iter, verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
float *vmask = CustomData_bmesh_get(&bm->vdata,
- v->head.data,
- CD_PAINT_MASK);
+ v->head.data,
+ CD_PAINT_MASK);
/* hide vertex if in the hide volume */
if (is_effected(area, planes, v->co, *vmask)) {
@@ -272,7 +260,7 @@ static void partialvis_update_bmesh(Object *ob,
float planes[4][4])
{
BMesh *bm;
- GHash *unique, *other;
+ GSet *unique, *other;
int any_changed = 0, any_visible = 0;
bm = BKE_pbvh_get_bmesh(pbvh);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index fcf00d4ab2c..910a49a8f7d 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -82,6 +82,7 @@
#include "UI_view2d.h"
#include "ED_image.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_uvedit.h"
@@ -962,24 +963,9 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-/* same as image_paint_poll but fail when face mask mode is enabled */
-static int image_paint_sample_color_poll(bContext *C)
+static int sample_color_poll(bContext *C)
{
- if (image_paint_poll(C)) {
- if (CTX_wm_view3d(C)) {
- Object *obact = CTX_data_active_object(C);
- if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
- Mesh *me = BKE_mesh_from_object(obact);
- if (me) {
- return !(me->editflag & ME_EDIT_PAINT_FACE_SEL);
- }
- }
- }
-
- return 1;
- }
-
- return 0;
+ return (image_paint_poll(C) || vertex_paint_poll(C));
}
void PAINT_OT_sample_color(wmOperatorType *ot)
@@ -993,7 +979,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
ot->exec = sample_color_exec;
ot->invoke = sample_color_invoke;
ot->modal = sample_color_modal;
- ot->poll = image_paint_sample_color_poll;
+ ot->poll = sample_color_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1006,9 +992,12 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
static int texture_paint_toggle_poll(bContext *C)
{
- if (CTX_data_edit_object(C))
+ Object *ob = CTX_data_active_object(C);
+ if (ob == NULL || ob->type != OB_MESH)
return 0;
- if (CTX_data_active_object(C) == NULL)
+ if (!ob->data || ((ID *)ob->data)->lib)
+ return 0;
+ if (CTX_data_edit_object(C))
return 0;
return 1;
@@ -1018,25 +1007,20 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- Mesh *me = NULL;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
- return OPERATOR_CANCELLED;
+ const int mode_flag = OB_MODE_TEXTURE_PAINT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ Mesh *me;
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
}
me = BKE_mesh_from_object(ob);
- if (!(ob->mode & OB_MODE_TEXTURE_PAINT) && !me) {
- BKE_report(op->reports, RPT_ERROR, "Can only enter texture paint mode for mesh objects");
- return OPERATOR_CANCELLED;
- }
-
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- ob->mode &= ~OB_MODE_TEXTURE_PAINT;
+ if (ob->mode & mode_flag) {
+ ob->mode &= ~mode_flag;
if (U.glreslimit != 0)
GPU_free_images();
@@ -1045,7 +1029,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 0);
}
else {
- ob->mode |= OB_MODE_TEXTURE_PAINT;
+ ob->mode |= mode_flag;
if (me->mtface == NULL)
me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index db55dc271f1..c90f9756707 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3883,7 +3883,7 @@ static void *do_projectpaint_thread(void *ph_v)
float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
straight_uchar_to_premul_float(newColor_f, projPixel->newColor.ch);
- IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, TRUE, ps->reproject_ibuf->rect_colorspace);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, true, ps->reproject_ibuf->rect_colorspace);
mul_v4_v4fl(newColor_f, newColor_f, mask);
blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f,
@@ -4164,7 +4164,7 @@ void paint_proj_stroke(bContext *C, void *pps, const float prev_pos[2], const fl
view3d_operator_needs_opengl(C);
- if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor, false))
+ if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor, false, NULL))
return;
ED_region_tag_redraw(ps->ar);
@@ -4279,9 +4279,6 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
return ps;
}
- /* needed so multiple threads don't try to initialize the brush at once (can leak memory) */
- curvemapping_initialize(ps->brush->curve);
-
paint_brush_init_tex(ps->brush);
ps->source = PROJ_SRC_VIEW;
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index bdf542526ee..0b0607babc1 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -1011,7 +1011,8 @@ typedef enum {
RC_COLOR = 1,
RC_ROTATION = 2,
RC_ZOOM = 4,
- RC_WEIGHT = 8
+ RC_WEIGHT = 8,
+ RC_SECONDARY_ROTATION = 16
} RCFlags;
static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path,
@@ -1043,7 +1044,10 @@ static void set_brush_rc_props(PointerRNA *ptr, const char *paint,
RNA_string_set(ptr, "data_path_secondary", "");
}
set_brush_rc_path(ptr, brush_path, "color_path", "cursor_color_add");
- set_brush_rc_path(ptr, brush_path, "rotation_path", "texture_slot.angle");
+ if (flags & RC_SECONDARY_ROTATION)
+ set_brush_rc_path(ptr, brush_path, "rotation_path", "mask_texture_slot.angle");
+ else
+ set_brush_rc_path(ptr, brush_path, "rotation_path", "texture_slot.angle");
RNA_string_set(ptr, "image_id", brush_path);
if (flags & RC_COLOR)
@@ -1055,6 +1059,11 @@ static void set_brush_rc_props(PointerRNA *ptr, const char *paint,
else
RNA_string_set(ptr, "zoom_path", "");
+ if (flags & RC_SECONDARY_ROTATION)
+ RNA_boolean_set(ptr, "secondary_tex", true);
+ else
+ RNA_boolean_set(ptr, "secondary_tex", false);
+
MEM_freeN(brush_path);
}
@@ -1064,6 +1073,7 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p
wmKeyMapItem *kmi;
/* only size needs to follow zoom, strength shows fixed size circle */
int flags_nozoom = flags & (~RC_ZOOM);
+ int flags_noradial_secondary = flags & (~(RC_SECONDARY_ROTATION | RC_ZOOM));
kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
set_brush_rc_props(kmi->ptr, paint, "size", "use_unified_size", flags);
@@ -1078,7 +1088,12 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p
if (flags & RC_ROTATION) {
kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0);
- set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags_nozoom);
+ set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags_noradial_secondary);
+ }
+
+ if (flags & RC_SECONDARY_ROTATION) {
+ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ set_brush_rc_props(kmi->ptr, paint, "mask_texture_slot.angle", NULL, flags_nozoom);
}
}
@@ -1265,7 +1280,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_switch(keymap, "image_paint");
ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size");
- ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION);
+ ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION | RC_SECONDARY_ROTATION);
ed_keymap_stencil(keymap);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 36e1b1feb38..973f6555deb 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -46,6 +46,7 @@
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_brush.h"
+#include "BKE_colortools.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -184,7 +185,8 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
if (paint_supports_dynamic_tex_coords(brush, mode)) {
if (((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) ||
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)) &&
+ (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) ||
+ (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)) &&
!(brush->flag & BRUSH_RAKE))
{
if (brush->flag & BRUSH_RANDOM_ROTATION)
@@ -477,6 +479,9 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->redraw = redraw;
stroke->done = done;
stroke->event_type = event_type; /* for modal, return event */
+
+ /* initialize here to avoid initialization conflict with threaded strokes */
+ curvemapping_initialize(br->curve);
BKE_paint_set_overlay_override(br->overlay_flags);
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
index e406d4f5c3b..50a79005ee3 100644
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_undo.c
@@ -124,6 +124,30 @@ 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) */
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index d376bd3180f..bfc431baea5 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -441,7 +441,7 @@ static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wm
void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
{
ot->name = "Select Linked Pick";
- ot->description = "Select linked faces";
+ ot->description = "Select linked faces under the cursor";
ot->idname = "PAINT_OT_face_select_linked_pick";
ot->invoke = paint_select_linked_pick_invoke;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 2c654507015..122dbae6129 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -61,6 +61,7 @@
#include "BKE_object_deform.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_colortools.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -68,12 +69,14 @@
#include "GPU_buffers.h"
#include "ED_armature.h"
+#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "paint_intern.h" /* own include */
+
/* check if we can do partial updates and have them draw realtime
* (without rebuilding the 'derivedFinal') */
static int vertex_paint_use_fast_update_check(Object *ob)
@@ -916,15 +919,13 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
co, co_ss,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
- float delta[2];
- float dist_squared;
- float factor = 1.0;
+ const float dist_squared = len_squared_v2v2(mval, co_ss);
- sub_v2_v2v2(delta, mval, co_ss);
- dist_squared = dot_v2v2(delta, delta); /* len squared */
if (dist_squared <= brush_size_pressure * brush_size_pressure) {
Brush *brush = BKE_paint_brush(&vp->paint);
const float dist = sqrtf(dist_squared);
+ float factor;
+
if (brush->mtex.tex && rgba) {
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
BKE_brush_sample_tex_3D(vc->scene, brush, co, rgba, 0, NULL);
@@ -935,6 +936,9 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
}
factor = rgba[3];
}
+ else {
+ factor = 1.0f;
+ }
return factor * BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
}
}
@@ -2025,41 +2029,28 @@ static void do_weight_paint_vertex(
/* *************** set wpaint operator ****************** */
-static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* toggle */
+/**
+ * \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);
VPaint *wp = scene->toolsettings->wpaint;
Mesh *me;
-
- me = BKE_mesh_from_object(ob);
- if (ob->id.lib || me == NULL) return OPERATOR_PASS_THROUGH;
-
- if (ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT;
- else ob->mode |= OB_MODE_WEIGHT_PAINT;
-
-
- /* Weightpaint works by overriding colors in mesh,
- * so need to make sure we recalc on enter and
- * exit (exit needs doing regardless because we
- * should redeform).
- */
- DAG_id_tag_update(&me->id, 0);
-
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (wp == NULL)
- wp = scene->toolsettings->wpaint = new_vpaint(1);
- BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
- paint_cursor_start(C, weight_paint_poll);
-
- mesh_octree_table(ob, NULL, NULL, 's');
-
- ED_vgroup_sync_from_pose(ob);
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
}
- else {
- mesh_octree_table(NULL, NULL, NULL, 'e');
- mesh_mirrtopo_table(NULL, 'e');
+
+ me = BKE_mesh_from_object(ob);
+
+ if (ob->mode & mode_flag) {
+ ob->mode &= ~mode_flag;
if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
BKE_mesh_flush_select_from_verts(me);
@@ -2067,10 +2058,35 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* togg
else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
BKE_mesh_flush_select_from_polys(me);
}
+
+ /* weight paint spesific */
+ mesh_octree_table(NULL, NULL, NULL, 'e');
+ mesh_mirrtopo_table(NULL, 'e');
+ }
+ else {
+ ob->mode |= mode_flag;
+
+ if (wp == NULL)
+ wp = scene->toolsettings->wpaint = new_vpaint(1);
+
+ paint_cursor_start(C, weight_paint_poll);
+
+ BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
+
+ /* weight paint spesific */
+ mesh_octree_table(ob, NULL, NULL, 's');
+ ED_vgroup_sync_from_pose(ob);
}
+ /* Weightpaint works by overriding colors in mesh,
+ * so need to make sure we recalc on enter and
+ * exit (exit needs doing regardless because we
+ * should redeform).
+ */
+ DAG_id_tag_update(&me->id, 0);
+
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -2078,12 +2094,12 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* togg
static int paint_poll_test(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (CTX_data_edit_object(C))
- return 0;
- if (CTX_data_active_object(C) == NULL)
+ if (ob == NULL || ob->type != OB_MESH)
return 0;
if (!ob->data || ((ID *)ob->data)->lib)
return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
return 1;
}
@@ -2633,7 +2649,7 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
/* api callbacks */
ot->exec = weight_paint_set_exec;
- ot->poll = mask_paint_poll; /* it was facemask_paint_poll */
+ ot->poll = mask_paint_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2641,40 +2657,41 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
/* ************ set / clear vertex paint mode ********** */
-
-static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) /* toggle */
+/**
+ * \note Keep in sync with #wpaint_mode_toggle_exec
+ */
+static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
+ 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;
-
- me = BKE_mesh_from_object(ob);
-
- if (me == NULL || BKE_object_obdata_is_libdata(ob)) {
- ob->mode &= ~OB_MODE_VERTEX_PAINT;
- return OPERATOR_PASS_THROUGH;
- }
-
- if (me && me->mloopcol == NULL) {
- make_vertexcol(ob);
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
}
+
+ me = BKE_mesh_from_object(ob);
/* toggle: end vpaint */
- if (ob->mode & OB_MODE_VERTEX_PAINT) {
-
- ob->mode &= ~OB_MODE_VERTEX_PAINT;
+ if (is_mode_set) {
+ ob->mode &= ~mode_flag;
if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
BKE_mesh_flush_select_from_polys(me);
}
}
else {
- ob->mode |= OB_MODE_VERTEX_PAINT;
- /* Turn off weight painting */
- if (ob->mode & OB_MODE_WEIGHT_PAINT)
- wpaint_mode_toggle_exec(C, op);
-
+ ob->mode |= mode_flag;
+
+ if (me->mloopcol == NULL) {
+ make_vertexcol(ob);
+ }
+
if (vp == NULL)
vp = scene->toolsettings->vpaint = new_vpaint(0);
@@ -3407,6 +3424,9 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
VPaint *wp = ts->wpaint;
struct Brush *brush = BKE_paint_brush(&wp->paint);
+
+ curvemapping_initialize(brush->curve);
+
data.brush = brush;
data.weightpaint = BKE_brush_weight_get(scene, brush);
}
@@ -3460,7 +3480,7 @@ void PAINT_OT_weight_gradient(wmOperatorType *ot)
/* identifiers */
ot->name = "Weight Gradient";
ot->idname = "PAINT_OT_weight_gradient";
- ot->description = "Sample a line and show it in Scope panels";
+ ot->description = "Draw a line to apply a weight gradient to selected vertices";
/* api callbacks */
ot->invoke = paint_weight_gradient_invoke;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 2edd00c015d..53357b2616b 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -70,6 +70,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_subsurf.h"
+#include "BKE_colortools.h"
#include "BIF_glutil.h"
@@ -77,6 +78,7 @@
#include "WM_types.h"
#include "ED_sculpt.h"
+#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h" /* for crazyspace correction */
@@ -91,6 +93,7 @@
#include "GPU_buffers.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include <math.h>
#include <stdlib.h>
@@ -150,6 +153,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
{
Mesh *me = (Mesh *)ob->data;
ModifierData *md;
+ VirtualModifierData virtualModifierData;
if (ob->sculpt && ob->sculpt->bm) {
/* can't combine multires and dynamic topology */
@@ -161,7 +165,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
return NULL;
}
- for (md = modifiers_getVirtualModifierList(ob); md; md = md->next) {
+ for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) {
if (md->type == eModifierType_Multires) {
MultiresModifierData *mmd = (MultiresModifierData *)md;
@@ -180,8 +184,9 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
static int sculpt_has_active_modifiers(Scene *scene, Object *ob)
{
ModifierData *md;
+ VirtualModifierData virtualModifierData;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* exception for shape keys because we can edit those */
for (; md; md = md->next) {
@@ -198,6 +203,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
ModifierData *md;
Mesh *me = (Mesh *)ob->data;
MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
+ VirtualModifierData virtualModifierData;
if (mmd || ob->sculpt->bm)
return 0;
@@ -206,7 +212,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
return 1;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* exception for shape keys because we can edit those */
for (; md; md = md->next) {
@@ -327,7 +333,7 @@ typedef struct {
/* Original coordinate, normal, and mask */
const float *co;
float mask;
- short no[3];
+ const short *no;
} SculptOrigVertData;
@@ -378,11 +384,10 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data,
}
if (orig_data->normals) {
- copy_v3_v3_short(orig_data->no, orig_data->normals[iter->i]);
+ orig_data->no = orig_data->normals[iter->i];
}
else {
- /* TODO: log doesn't store normals yet */
- normal_float_to_short_v3(orig_data->no, iter->bm_vert->no);
+ orig_data->no = BM_log_original_vert_no(orig_data->bm_log, iter->bm_vert);
}
}
else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
@@ -664,10 +669,10 @@ static int sculpt_brush_test_cube(SculptBrushTest *test, float co[3], float loca
}
}
-static float frontface(Brush *brush, const float sculpt_normal[3],
+static float frontface(Brush *br, const float sculpt_normal[3],
const short no[3], const float fno[3])
{
- if (brush->flag & BRUSH_FRONTFACE) {
+ if (br->flag & BRUSH_FRONTFACE) {
float dot;
if (no) {
@@ -944,7 +949,8 @@ static float tex_strength(SculptSession *ss, Brush *br,
const float fno[3],
const float mask)
{
- const Scene *scene = ss->cache->vc->scene;
+ StrokeCache *cache = ss->cache;
+ const Scene *scene = cache->vc->scene;
MTex *mtex = &br->mtex;
float avg = 1;
float rgba[4];
@@ -966,12 +972,12 @@ static float tex_strength(SculptSession *ss, Brush *br,
* position in order to project it. This insures that the
* brush texture will be oriented correctly. */
- flip_v3_v3(symm_point, point, ss->cache->mirror_symmetry_pass);
+ flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass);
- if (ss->cache->radial_symmetry_pass)
- mul_m4_v3(ss->cache->symm_rot_mat_inv, symm_point);
+ if (cache->radial_symmetry_pass)
+ mul_m4_v3(cache->symm_rot_mat_inv, symm_point);
- ED_view3d_project_float_v2_m4(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat);
+ ED_view3d_project_float_v2_m4(cache->vc->ar, symm_point, point_2d, cache->projection_mat);
/* still no symmetry supported for other paint modes.
* Sculpt does it DIY */
@@ -979,7 +985,7 @@ static float tex_strength(SculptSession *ss, Brush *br,
/* Similar to fixed mode, but projects from brush angle
* rather than view direction */
- mul_m4_v3(ss->cache->brush_local_mat, symm_point);
+ mul_m4_v3(cache->brush_local_mat, symm_point);
x = symm_point[0];
y = symm_point[1];
@@ -1001,7 +1007,7 @@ static float tex_strength(SculptSession *ss, Brush *br,
}
/* Falloff curve */
- avg *= BKE_brush_curve_strength(br, len, ss->cache->radius);
+ avg *= BKE_brush_curve_strength(br, len, cache->radius);
avg *= frontface(br, sculpt_normal, vno, fno);
@@ -1073,8 +1079,9 @@ static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], floa
static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nodes, int totnode)
{
- SculptSession *ss = ob->sculpt;
float out_flip[3] = {0.0f, 0.0f, 0.0f};
+
+ SculptSession *ss = ob->sculpt;
int n, original;
/* Grab brush requires to test on original data (see r33888 and
@@ -2274,7 +2281,10 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
SculptSession *ss = ob->sculpt;
int n;
- float count = 0;
+ int count = 0;
+ int count_flip = 0;
+
+ float fc_flip[3] = {0.0, 0.0, 0.0};
(void)sd; /* unused w/o openmp */
@@ -2286,7 +2296,9 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
SculptBrushTest test;
SculptUndoNode *unode;
float private_fc[3] = {0.0f, 0.0f, 0.0f};
+ float private_fc_flip[3] = {0.0f, 0.0f, 0.0f};
int private_count = 0;
+ int private_count_flip = 0;
unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
sculpt_brush_test_init(ss, &test);
@@ -2295,8 +2307,17 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, unode->co[vd.i])) {
- add_v3_v3(private_fc, unode->co[vd.i]);
- private_count++;
+ float fno[3];
+
+ normal_short_to_float_v3(fno, unode->no[vd.i]);
+ if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
+ add_v3_v3(private_fc, unode->co[vd.i]);
+ private_count++;
+ }
+ else {
+ add_v3_v3(private_fc_flip, unode->co[vd.i]);
+ private_count_flip++;
+ }
}
}
BKE_pbvh_vertex_iter_end;
@@ -2305,8 +2326,31 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, vd.co)) {
- add_v3_v3(private_fc, vd.co);
- private_count++;
+ /* for area normal */
+ if (vd.no) {
+ float fno[3];
+
+ normal_short_to_float_v3(fno, vd.no);
+
+ if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
+ add_v3_v3(private_fc, vd.co);
+ private_count++;
+ }
+ else {
+ add_v3_v3(private_fc_flip, vd.co);
+ private_count_flip++;
+ }
+ }
+ else {
+ if (dot_v3v3(ss->cache->view_normal, vd.fno) > 0) {
+ add_v3_v3(private_fc, vd.co);
+ private_count++;
+ }
+ else {
+ add_v3_v3(private_fc_flip, vd.co);
+ private_count_flip++;
+ }
+ }
}
}
BKE_pbvh_vertex_iter_end;
@@ -2315,11 +2359,17 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
#pragma omp critical
{
add_v3_v3(fc, private_fc);
+ add_v3_v3(fc_flip, private_fc_flip);
count += private_count;
+ count_flip += private_count_flip;
}
}
-
- mul_v3_fl(fc, 1.0f / count);
+ if (count != 0)
+ mul_v3_fl(fc, 1.0f / count);
+ else if (count_flip != 0)
+ mul_v3_v3fl(fc, fc_flip, 1.0f / count_flip);
+ else
+ zero_v3(fc);
}
/* this calculates flatten center and area normal together,
@@ -2333,9 +2383,11 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
/* for area normal */
float out_flip[3] = {0.0f, 0.0f, 0.0f};
+ float fc_flip[3] = {0.0f, 0.0f, 0.0f};
/* for flatten center */
- float count = 0;
+ int count = 0;
+ int count_flipped = 0;
(void)sd; /* unused w/o openmp */
@@ -2353,7 +2405,9 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
float private_an[3] = {0.0f, 0.0f, 0.0f};
float private_out_flip[3] = {0.0f, 0.0f, 0.0f};
float private_fc[3] = {0.0f, 0.0f, 0.0f};
+ float private_fc_flip[3] = {0.0f, 0.0f, 0.0f};
int private_count = 0;
+ int private_count_flip = 0;
unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
sculpt_brush_test_init(ss, &test);
@@ -2366,11 +2420,17 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
float fno[3];
normal_short_to_float_v3(fno, unode->no[vd.i]);
- add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
- /* for flatten center */
- add_v3_v3(private_fc, unode->co[vd.i]);
- private_count++;
+ if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
+ add_v3_v3(private_an, fno);
+ add_v3_v3(private_fc, unode->co[vd.i]);
+ private_count++;
+ }
+ else {
+ add_v3_v3(private_out_flip, fno);
+ add_v3_v3(private_fc_flip, unode->co[vd.i]);
+ private_count_flip++;
+ }
}
}
BKE_pbvh_vertex_iter_end;
@@ -2384,15 +2444,30 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
float fno[3];
normal_short_to_float_v3(fno, vd.no);
- add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
+
+ if (dot_v3v3(ss->cache->view_normal, fno) > 0) {
+ add_v3_v3(private_an, fno);
+ add_v3_v3(private_fc, vd.co);
+ private_count++;
+ }
+ else {
+ add_v3_v3(private_out_flip, fno);
+ add_v3_v3(private_fc_flip, vd.co);
+ private_count_flip++;
+ }
}
else {
- add_norm_if(ss->cache->view_normal, private_an, private_out_flip, vd.fno);
+ if (dot_v3v3(ss->cache->view_normal, vd.fno) > 0) {
+ add_v3_v3(private_an, vd.fno);
+ add_v3_v3(private_fc, vd.co);
+ private_count++;
+ }
+ else {
+ add_v3_v3(private_out_flip, vd.fno);
+ add_v3_v3(private_fc_flip, vd.co);
+ private_count_flip++;
+ }
}
-
- /* for flatten center */
- add_v3_v3(private_fc, vd.co);
- private_count++;
}
}
BKE_pbvh_vertex_iter_end;
@@ -2406,7 +2481,9 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
/* for flatten center */
add_v3_v3(fc, private_fc);
+ add_v3_v3(fc_flip, private_fc);
count += private_count;
+ count_flipped += private_count_flip;
}
}
@@ -2417,12 +2494,12 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
normalize_v3(an);
/* for flatten center */
- if (count != 0) {
+ if (count != 0)
mul_v3_fl(fc, 1.0f / count);
- }
- else {
+ else if (count_flipped != 0)
+ mul_v3_v3fl(fc, fc_flip, 1.0f / count_flipped);
+ else
zero_v3(fc);
- }
}
static void calc_sculpt_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float an[3], float fc[3])
@@ -3422,7 +3499,7 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
/* Need to allocate a bigger buffer for bigger brush size */
ss->texcache_side = 2 * radius;
if (!ss->texcache || ss->texcache_side > ss->texcache_actual) {
- ss->texcache = BKE_brush_gen_texture_cache(brush, radius);
+ ss->texcache = BKE_brush_gen_texture_cache(brush, radius, false);
ss->texcache_actual = ss->texcache_side;
ss->tex_pool = BKE_image_pool_new();
}
@@ -3716,16 +3793,28 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
Brush *brush = BKE_paint_brush(&sd->paint);
ViewContext *vc = paint_stroke_view_context(op->customdata);
Object *ob = CTX_data_active_object(C);
- float rot[3][3], scale[3], loc[3];
+ float mat[3][3];
+ float viewDir[3] = {0.0f, 0.0f, 1.0f};
+ float max_scale;
int i;
int mode;
ss->cache = cache;
/* Set scaling adjustment */
- cache->scale[0] = 1.0f / ob->size[0];
- cache->scale[1] = 1.0f / ob->size[1];
- cache->scale[2] = 1.0f / ob->size[2];
+ if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
+ max_scale = 1.0f;
+ }
+ else {
+ max_scale = 0.0f;
+ for (i = 0; i < 3; i ++) {
+ max_scale = max_ff(max_scale, fabsf(ob->size[i]));
+ }
+ }
+ cache->scale[0] = max_scale / ob->size[0];
+ cache->scale[1] = max_scale / ob->size[1];
+ cache->scale[2] = max_scale / ob->size[2];
+
cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;
@@ -3768,6 +3857,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
brush = br;
cache->saved_smooth_size = BKE_brush_size_get(scene, brush);
BKE_brush_size_set(scene, brush, size);
+ curvemapping_initialize(brush->curve);
}
}
}
@@ -3784,12 +3874,13 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
/* cache projection matrix */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
- mat4_to_loc_rot_size(loc, rot, scale, ob->obmat);
- /* transposing an orthonormal matrix inverts */
- transpose_m3(rot);
- ED_view3d_global_to_vector(cache->vc->rv3d, cache->vc->rv3d->twmat[3], cache->true_view_normal);
- /* This takes care of rotated mesh. Instead of rotating every normal, we inverse rotate view normal. */
- mul_m3_v3(rot, cache->true_view_normal);
+ invert_m4_m4(ob->imat, ob->obmat);
+ copy_m3_m4(mat, cache->vc->rv3d->viewinv);
+ mul_m3_v3(mat, viewDir);
+ copy_m3_m4(mat, ob->imat);
+ mul_m3_v3(mat, viewDir);
+ normalize_v3_v3(cache->true_view_normal, viewDir);
+
/* Initialize layer brush displacements and persistent coords */
if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
/* not supported yet for multires or dynamic topology */
@@ -3823,10 +3914,10 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
cache->original = 1;
}
- if (ELEM8(brush->sculpt_tool,
+ if (ELEM9(brush->sculpt_tool,
SCULPT_TOOL_DRAW, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB,
SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
- SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE))
+ SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE, SCULPT_TOOL_FLATTEN))
{
if (!(brush->flag & BRUSH_ACCUMULATE)) {
cache->original = 1;
@@ -4561,7 +4652,9 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
static void sculpt_dynamic_topology_triangulate(BMesh *bm)
{
- BM_mesh_triangulate(bm, false, false, NULL, NULL);
+ if (bm->totloop != bm->totface * 3) {
+ BM_mesh_triangulate(bm, false, false, NULL, NULL);
+ }
}
void sculpt_pbvh_clear(Object *ob)
@@ -4595,10 +4688,7 @@ void sculpt_dynamic_topology_enable(bContext *C)
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Mesh *me = ob->data;
- const BMAllocTemplate allocsize = {me->totvert,
- me->totedge,
- me->totloop,
- me->totpoly};
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
sculpt_pbvh_clear(ob);
@@ -4800,8 +4890,8 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
/* Symmetrize and re-triangulate */
BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS,
- "symmetrize input=%avef direction=%i",
- sd->symmetrize_direction);
+ "symmetrize input=%avef direction=%i dist=%f",
+ sd->symmetrize_direction, 0.00001f);
sculpt_dynamic_topology_triangulate(ss->bm);
/* Finish undo */
@@ -4849,7 +4939,7 @@ int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
if (mmd && !CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) {
GridPaintMask *gmask;
int level = max_ii(1, mmd->sculptlvl);
- int gridsize = ccg_gridsize(level);
+ int gridsize = BKE_ccg_gridsize(level);
int gridarea = gridsize * gridsize;
int i, j;
@@ -4907,21 +4997,31 @@ int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
return ret;
}
-static int sculpt_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
- Mesh *me = ob->data;
+ const int mode_flag = OB_MODE_SCULPT;
+ const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ Mesh *me;
MultiresModifierData *mmd = 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;
+ }
+ }
+
+ me = BKE_mesh_from_object(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);
- if (ob->mode & OB_MODE_SCULPT) {
+ if (is_mode_set) {
if (mmd)
multires_force_update(ob);
@@ -4936,13 +5036,13 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
}
/* Leave sculptmode */
- ob->mode &= ~OB_MODE_SCULPT;
+ ob->mode &= ~mode_flag;
free_sculptsession(ob);
}
else {
/* Enter sculptmode */
- ob->mode |= OB_MODE_SCULPT;
+ ob->mode |= mode_flag;
/* Remove dynamic-topology flag; this will be enabled if the
* file was saved with dynamic topology on, but we don't
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 9c73d4d9477..7a973d8c1ae 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -45,6 +45,7 @@
#include "BKE_brush.h"
#include "BKE_paint.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_depsgraph.h"
@@ -538,6 +539,8 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
op->customdata = data;
+ curvemapping_initialize(ts->uvsculpt->paint.brush->curve);
+
if (data) {
int counter = 0, i;
ARegion *ar = CTX_wm_region(C);
@@ -662,6 +665,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
int offset1, itmp1 = uv_element_offset_from_face_get(data->elementMap, efa, l, island_index, do_island_optimization);
int offset2, itmp2 = uv_element_offset_from_face_get(data->elementMap, efa, l->next, island_index, do_island_optimization);
+ char *flag;
/* Skip edge if not found(unlikely) or not on valid island */
if (itmp1 == -1 || itmp2 == -1)
@@ -682,8 +686,8 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
edges[counter].uv2 = offset1;
}
/* Hack! Set the value of the key to its flag. Now we can set the flag when an edge exists twice :) */
- if (BLI_ghash_haskey(edgeHash, &edges[counter])) {
- char *flag = BLI_ghash_lookup(edgeHash, &edges[counter]);
+ flag = BLI_ghash_lookup(edgeHash, &edges[counter]);
+ if (flag) {
*flag = 1;
}
else {
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 51e740e539f..8508123f942 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -150,20 +150,31 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
bool valid_particles = ED_texture_context_check_particles(C);
bool valid_others = ED_texture_context_check_others(C);
+ /* this is similar to direct user action, no need to keep "better" ctxt in _prev */
if ((sbuts->mainb == BCONTEXT_WORLD) && valid_world) {
- sbuts->texture_context = SB_TEXC_WORLD;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_WORLD;
}
else if ((sbuts->mainb == BCONTEXT_MATERIAL) && valid_material) {
- sbuts->texture_context = SB_TEXC_MATERIAL;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_MATERIAL;
}
else if ((sbuts->mainb == BCONTEXT_DATA) && valid_lamp) {
- sbuts->texture_context = SB_TEXC_LAMP;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_LAMP;
}
else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) {
- sbuts->texture_context = SB_TEXC_PARTICLES;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_PARTICLES;
}
else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && valid_others) {
- sbuts->texture_context = SB_TEXC_OTHER;
+ sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_OTHER;
+ }
+ /* Else, try to revive a previous "better" ctxt... */
+ else if ((sbuts->texture_context_prev != sbuts->texture_context) &&
+ (((sbuts->texture_context_prev == SB_TEXC_WORLD) && valid_world) ||
+ ((sbuts->texture_context_prev == SB_TEXC_MATERIAL) && valid_material) ||
+ ((sbuts->texture_context_prev == SB_TEXC_LAMP) && valid_lamp) ||
+ ((sbuts->texture_context_prev == SB_TEXC_PARTICLES) && valid_particles) ||
+ ((sbuts->texture_context_prev == SB_TEXC_OTHER) && valid_others)))
+ {
+ sbuts->texture_context = sbuts->texture_context_prev;
}
/* Else, just be sure that current context is valid! */
else if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) ||
@@ -172,13 +183,9 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) ||
((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others))
{
- if (valid_others) {
- sbuts->texture_context = SB_TEXC_OTHER;
- }
- else if (valid_world) {
- sbuts->texture_context = SB_TEXC_WORLD;
- }
- else if (valid_material) {
+ /* this is default fallback, do keep "better" ctxt in _prev */
+ sbuts->texture_context_prev = sbuts->texture_context;
+ if (valid_material) {
sbuts->texture_context = SB_TEXC_MATERIAL;
}
else if (valid_lamp) {
@@ -187,6 +194,12 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if (valid_particles) {
sbuts->texture_context = SB_TEXC_PARTICLES;
}
+ else if (valid_world) {
+ sbuts->texture_context = SB_TEXC_WORLD;
+ }
+ else if (valid_others) {
+ sbuts->texture_context = SB_TEXC_OTHER;
+ }
}
}
}
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 18248f4775b..50bb8a0e061 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -238,7 +238,8 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
{
MarkerUpdateCb *cb = (MarkerUpdateCb *) arg_cb;
MovieTrackingMarker *marker;
- int width, height, ok = FALSE;
+ int width, height;
+ bool ok = false;
BKE_movieclip_get_size(cb->clip, cb->user, &width, &height);
@@ -252,7 +253,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
DAG_id_tag_update(&cb->clip->id, 0);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_PAT_DIM) {
float dim[2], pat_dim[2], pat_min[2], pat_max[2];
@@ -276,7 +277,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
BKE_tracking_marker_clamp(cb->marker, CLAMP_PAT_DIM);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_SEARCH_POS) {
float delta[2], side[2];
@@ -292,7 +293,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_POS);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_SEARCH_DIM) {
float dim[2], search_dim[2];
@@ -313,12 +314,12 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_DIM);
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_FLAG) {
marker->flag = cb->marker_flag;
- ok = TRUE;
+ ok = true;
}
else if (event == B_MARKER_OFFSET) {
float offset[2], delta[2];
@@ -337,7 +338,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
DAG_id_tag_update(&cb->clip->id, 0);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- ok = TRUE;
+ ok = true;
}
if (ok)
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index d1fd5093974..3c9eb1fe79e 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -111,6 +111,62 @@ static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int wid
}
}
+static int generic_track_get_markersnr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track)
+{
+ if (track) {
+ return track->markersnr;
+ }
+ else if (plane_track) {
+ return plane_track->markersnr;
+ }
+
+ return 0;
+}
+
+static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+ int marker_index)
+{
+ if (track) {
+ BLI_assert(marker_index < track->markersnr);
+ return track->markers[marker_index].framenr;
+ }
+ else if (plane_track) {
+ BLI_assert(marker_index < plane_track->markersnr);
+ return plane_track->markers[marker_index].framenr;
+ }
+
+ return 0;
+}
+
+static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+ int marker_index)
+{
+ if (track) {
+ BLI_assert(marker_index < track->markersnr);
+ return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
+ }
+ else if (plane_track) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+ int marker_index)
+{
+ if (track) {
+ BLI_assert(marker_index < track->markersnr);
+ return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
+ }
+ else if (plane_track) {
+ BLI_assert(marker_index < plane_track->markersnr);
+ return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
+ }
+
+ return false;
+}
+
static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
{
float x;
@@ -119,6 +175,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking);
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
+ MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
glEnable(GL_BLEND);
@@ -143,34 +200,31 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
}
/* track */
- if (act_track) {
- MovieTrackingTrack *track = act_track;
-
+ if (act_track || act_plane_track) {
for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
int framenr;
- MovieTrackingMarker *marker;
+ int markersnr = generic_track_get_markersnr(act_track, act_plane_track);
- while (a < track->markersnr) {
- if (track->markers[a].framenr >= i)
+ while (a < markersnr) {
+ int marker_framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
+
+ if (marker_framenr >= i)
break;
- if (a < track->markersnr - 1 && track->markers[a + 1].framenr > i)
+ if (a < markersnr - 1 && generic_track_get_marker_framenr(act_track, act_plane_track, a + 1) > i)
break;
a++;
}
- if (a < track->markersnr)
- marker = &track->markers[a];
- else
- marker = &track->markers[track->markersnr - 1];
+ a = min_ii(a, markersnr - 1);
- if ((marker->flag & MARKER_DISABLED) == 0) {
- framenr = marker->framenr;
+ if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
+ framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
if (framenr != i)
glColor4ub(128, 128, 0, 96);
- else if ((marker->flag & MARKER_TRACKED) == 0)
+ else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a))
glColor4ub(255, 255, 0, 196);
else
glColor4ub(255, 255, 0, 96);
@@ -188,11 +242,11 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
glColor4ub(255, 0, 0, 96);
for (i = sfra, a = 0; i <= efra; i++) {
- int ok = FALSE;
+ bool ok = false;
while (a < n) {
if (cameras[a].framenr == i) {
- ok = TRUE;
+ ok = true;
break;
}
else if (cameras[a].framenr > i) {
@@ -233,11 +287,11 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
char str[256] = {0};
- int block = FALSE;
+ bool block = false;
if (tracking->stats) {
BLI_strncpy(str, tracking->stats->message, sizeof(str));
- block = TRUE;
+ block = true;
}
else {
if (sc->flag & SC_LOCK_SELECTION)
@@ -250,48 +304,52 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
}
}
+static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx, float zoomy)
+{
+ int x, y;
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
+
+ glColor3f(0.0f, 0.0f, 0.0f);
+ glRectf(x, y, x + zoomx * width, y + zoomy * height);
+}
+
static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
int width, int height, float zoomx, float zoomy)
{
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int filter = GL_LINEAR;
int x, y;
/* find window pixel coordinates of origin */
UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
- if (sc->flag & SC_MUTE_FOOTAGE) {
- glColor3f(0.0f, 0.0f, 0.0f);
- glRectf(x, y, x + zoomx * width, y + zoomy * height);
- }
- else {
- MovieClip *clip = ED_space_clip_get_clip(sc);
- int filter = GL_LINEAR;
+ /* checkerboard for case alpha */
+ if (ibuf->planes == 32) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- /* checkerboard for case alpha */
- if (ibuf->planes == 32) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
- }
+ fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
+ }
- /* non-scaled proxy shouldn't use filtering */
- if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
- ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
- {
- filter = GL_NEAREST;
- }
+ /* non-scaled proxy shouldn't use filtering */
+ if ((clip->flag & MCLIP_USE_PROXY) == 0 ||
+ ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100))
+ {
+ filter = GL_NEAREST;
+ }
- /* set zoom */
- glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+ /* set zoom */
+ glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
- /* reset zoom */
- glPixelZoom(1.0f, 1.0f);
+ /* reset zoom */
+ glPixelZoom(1.0f, 1.0f);
- if (ibuf->planes == 32)
- glDisable(GL_BLEND);
- }
+ if (ibuf->planes == 32)
+ glDisable(GL_BLEND);
}
static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy)
@@ -443,7 +501,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
float marker_pos[2], int width, int height)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
- int show_search = FALSE;
+ bool show_search = false;
float px[2];
UI_ThemeColor(TH_MARKER_OUTLINE);
@@ -506,8 +564,8 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
glEnd();
}
- show_search = TRACK_VIEW_SELECTED(sc, track) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
+ show_search = (TRACK_VIEW_SELECTED(sc, track) &&
+ ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
glBegin(GL_LINE_LOOP);
glVertex2f(marker->search_min[0], marker->search_min[1]);
@@ -546,7 +604,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
float marker_pos[2], int width, int height, int act, int sel)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
- int show_search = 0;
+ bool show_search = false;
float col[3], scol[3], px[2];
track_colors(track, act, col, scol);
@@ -661,8 +719,8 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
}
/* search */
- show_search = TRACK_VIEW_SELECTED(sc, track) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0);
+ show_search = (TRACK_VIEW_SELECTED(sc, track) &&
+ ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
if (track->flag & TRACK_LOCKED) {
if (act)
@@ -950,24 +1008,154 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
}
}
-static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony)
+static void plane_track_colors(bool is_active, float color[3], float selected_color[3])
+{
+ UI_GetThemeColor3fv(TH_MARKER, color);
+
+ if (is_active)
+ UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color);
+ else
+ UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color);
+}
+
+static void getArrowEndPoint(const int width, const int height, const float zoom,
+ const float start_corner[2], const float end_corner[2],
+ float end_point[2])
{
- /* express given coordinates as proportional values */
- x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur);
- y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur);
+ float direction[2];
+ float max_length;
+
+ sub_v2_v2v2(direction, end_corner, start_corner);
- /* convert proportional distances to screen coordinates */
- *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask);
- *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
+ direction[0] *= width;
+ direction[1] *= height;
+ max_length = len_v2(direction);
+ normalize_v2(direction);
+ mul_v2_fl(direction, min_ff(32.0f / zoom, max_length));
+ direction[0] /= width;
+ direction[1] /= height;
+
+ add_v2_v2v2(end_point, start_corner, direction);
}
+static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
+ bool draw_outline, int width, int height)
+{
+ bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
+ bool is_selected_track = plane_track->flag & SELECT;
+ float px[2];
+
+ if (draw_outline) {
+ UI_ThemeColor(TH_MARKER_OUTLINE);
+ }
+ else {
+ float color[3], selected_color[3];
+ plane_track_colors(is_active_track, color, selected_color);
+ if (is_selected_track) {
+ glColor3fv(selected_color);
+ }
+ else {
+ glColor3fv(color);
+ }
+ }
+
+ px[0] = 1.0f / width / sc->zoom;
+ px[1] = 1.0f / height / sc->zoom;
+
+ if (draw_outline) {
+ if (!tiny) {
+ glLineWidth(3.0f);
+ }
+ }
+ else if (tiny) {
+ glLineStipple(3, 0xaaaa);
+ glEnable(GL_LINE_STIPPLE);
+ }
+
+ /* Draw rectangle itself. */
+ glBegin(GL_LINE_LOOP);
+ glVertex2fv(plane_marker->corners[0]);
+ glVertex2fv(plane_marker->corners[1]);
+ glVertex2fv(plane_marker->corners[2]);
+ glVertex2fv(plane_marker->corners[3]);
+ glEnd();
+
+ /* Draw axis. */
+ if (!draw_outline) {
+ float end_point[2];
+ glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
+
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
+ glColor3f(1.0, 0.0, 0.0f);
+ glBegin(GL_LINES);
+ glVertex2fv(plane_marker->corners[0]);
+ glVertex2fv(end_point);
+ glEnd();
+
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
+ glColor3f(0.0, 1.0, 0.0f);
+ glBegin(GL_LINES);
+ glVertex2fv(plane_marker->corners[0]);
+ glVertex2fv(end_point);
+ glEnd();
+
+ glPopAttrib();
+ }
+
+ /* Draw sliders. */
+ if (is_selected_track) {
+ int i;
+ for (i = 0; i < 4; i++) {
+ draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
+ 3.0f * px[0], 3.0f * px[1], draw_outline, px);
+ }
+ }
+
+ if (draw_outline) {
+ if (!tiny) {
+ glLineWidth(1.0f);
+ }
+ }
+ else if (tiny) {
+ glDisable(GL_LINE_STIPPLE);
+ }
+}
+
+static void draw_plane_marker_outline(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker, int width, int height)
+{
+ draw_plane_marker_ex(sc, plane_track, plane_marker, false, true, width, height);
+}
+
+static void draw_plane_marker(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
+ int width, int height)
+{
+ draw_plane_marker_ex(sc, plane_track, plane_marker, is_active_track, false, width, height);
+}
+
+static void draw_plane_track(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+ int framenr, bool is_active_track, int width, int height)
+{
+ MovieTrackingPlaneMarker *plane_marker;
+
+ plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+ draw_plane_marker_outline(sc, plane_track, plane_marker, width, height);
+ draw_plane_marker(sc, plane_track, plane_marker, is_active_track, width, height);
+}
+
+/* Draw all kind of tracks. */
static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
int width, int height, float zoomx, float zoomy)
{
float x, y;
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
MovieTrackingTrack *track, *act_track;
+ MovieTrackingPlaneTrack *plane_track, *active_plane_track;
MovieTrackingMarker *marker;
int framenr = ED_space_clip_get_clip_frame_number(sc);
int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
@@ -980,7 +1168,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
* to avoid this flickering, calculate base point in the same way as it happens
* in UI_view2d_to_region_no_clip, but do it in floats here */
- view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
glPushMatrix();
glTranslatef(x, y, 0);
@@ -1160,6 +1348,15 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
glDisable(GL_POINT_SMOOTH);
}
+ /* Draw plane tracks */
+ active_plane_track = BKE_tracking_plane_track_get_active(tracking);
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ draw_plane_track(sc, plane_track, framenr, plane_track == active_plane_track, width, height);
+ }
+
glPopMatrix();
if (sc->flag & SC_SHOW_NAMES) {
@@ -1214,7 +1411,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
return;
- view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
glPushMatrix();
glTranslatef(x, y, 0);
@@ -1409,7 +1606,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
Scene *scene = CTX_data_scene(C);
- ImBuf *ibuf;
+ ImBuf *ibuf = NULL;
int width, height;
float zoomx, zoomy;
@@ -1447,7 +1644,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
mul_serie_m4(sc->unistabmat, smat, sc->stabmat, ismat, NULL, NULL, NULL, NULL, NULL);
}
}
- else {
+ else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
ibuf = ED_space_clip_get_buffer(sc);
zero_v2(sc->loc);
@@ -1460,6 +1657,9 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
IMB_freeImBuf(ibuf);
}
+ else if (sc->flag & SC_MUTE_FOOTAGE) {
+ draw_movieclip_muted(ar, width, height, zoomx, zoomy);
+ }
else {
ED_region_grid_draw(ar, zoomx, zoomy);
}
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 08d0af817a8..0d64a3ce594 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -262,15 +262,15 @@ ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale
/* returns color in SRGB */
/* matching ED_space_image_color_sample() */
-int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
+bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
{
ImBuf *ibuf;
float fx, fy, co[2];
- int ret = FALSE;
+ bool ret = false;
ibuf = ED_space_clip_get_buffer(sc);
if (!ibuf) {
- return FALSE;
+ return false;
}
/* map the mouse coords to the backdrop image space */
@@ -290,12 +290,12 @@ int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
linearrgb_to_srgb_v3_v3(r_col, fp);
- ret = TRUE;
+ ret = true;
}
else if (ibuf->rect) {
cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
rgb_uchar_to_float(r_col, cp);
- ret = TRUE;
+ ret = true;
}
}
@@ -325,11 +325,12 @@ void ED_clip_update_frame(const Main *mainp, int cfra)
}
}
-static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
+static bool selected_boundbox(SpaceClip *sc, float min[2], float max[2])
{
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTrackingTrack *track;
- int width, height, ok = FALSE;
+ int width, height;
+ bool ok = false;
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -362,7 +363,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
minmax_v2v2_v2(min, max, pos);
- ok = TRUE;
+ ok = true;
}
}
@@ -372,7 +373,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
return ok;
}
-int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
+bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit)
{
SpaceClip *sc = CTX_wm_space_clip(C);
int w, h, frame_width, frame_height;
@@ -381,10 +382,10 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
ED_space_clip_get_size(sc, &frame_width, &frame_height);
if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL))
- return FALSE;
+ return false;
if (!selected_boundbox(sc, min, max))
- return FALSE;
+ return false;
/* center view */
clip_view_center_to_point(sc, (max[0] + min[0]) / (2 * frame_width),
@@ -412,7 +413,7 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit)
sc->zoom = newzoom;
}
- return TRUE;
+ return true;
}
void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[2])
@@ -500,22 +501,22 @@ void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, const int mval[2], float co[2
ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &co[0], &co[1]);
}
-int ED_space_clip_check_show_trackedit(SpaceClip *sc)
+bool ED_space_clip_check_show_trackedit(SpaceClip *sc)
{
if (sc) {
return ELEM3(sc->mode, SC_MODE_TRACKING, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION);
}
- return FALSE;
+ return false;
}
-int ED_space_clip_check_show_maskedit(SpaceClip *sc)
+bool ED_space_clip_check_show_maskedit(SpaceClip *sc)
{
if (sc) {
return sc->mode == SC_MODE_MASKEDIT;
}
- return FALSE;
+ return false;
}
/* ******** clip editing functions ******** */
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 973200dc340..173d65ee4fc 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -126,7 +126,7 @@ static void tracking_segment_end_cb(void *UNUSED(userdata))
static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track,
MovieTrackingMarker *marker, int coord, int scene_framenr, float val)
{
- struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } *data = userdata;
+ struct { MovieTrackingTrack *act_track; bool sel; float xscale, yscale, hsize; } *data = userdata;
int sel = 0, sel_flag;
if (track != data->act_track)
@@ -151,7 +151,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
int width, height;
- struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } userdata;
+ struct { MovieTrackingTrack *act_track; bool sel; float xscale, yscale, hsize; } userdata;
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
@@ -160,7 +160,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
/* non-selected knot handles */
userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
- userdata.sel = FALSE;
+ userdata.sel = false;
userdata.act_track = act_track;
UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale);
clip_graph_tracking_values_iterate(sc, sc->flag & SC_SHOW_GRAPH_SEL_ONLY, sc->flag & SC_SHOW_GRAPH_HIDDEN,
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index edc6ac1ecf7..393f92f5af5 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -96,8 +96,8 @@ static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker)
/******************** mouse select operator ********************/
typedef struct {
- int coord, /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
- has_prev; /* if there's valid coordinate of previous point of curve segment */
+ int coord; /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
+ bool has_prev; /* if there's valid coordinate of previous point of curve segment */
float min_dist, /* minimal distance between mouse and currently found entuty */
mouse_co[2], /* mouse coordinate */
@@ -134,7 +134,7 @@ static void find_nearest_tracking_segment_end_cb(void *userdata)
{
MouseSelectUserData *data = userdata;
- data->has_prev = FALSE;
+ data->has_prev = false;
}
static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track,
@@ -163,7 +163,7 @@ static void mouse_select_init_data(MouseSelectUserData *userdata, float *co)
copy_v2_v2(userdata->mouse_co, co);
}
-static int mouse_select_knot(bContext *C, float co[2], int extend)
+static bool mouse_select_knot(bContext *C, float co[2], bool extend)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -200,15 +200,15 @@ static int mouse_select_knot(bContext *C, float co[2], int extend)
else
userdata.marker->flag |= MARKER_GRAPH_SEL_Y;
- return TRUE;
+ return true;
}
}
}
- return FALSE;
+ return false;
}
-static int mouse_select_curve(bContext *C, float co[2], int extend)
+static bool mouse_select_curve(bContext *C, float co[2], bool extend)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -242,15 +242,15 @@ static int mouse_select_curve(bContext *C, float co[2], int extend)
toggle_selection_cb);
}
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-static int mouse_select(bContext *C, float co[2], int extend)
+static int mouse_select(bContext *C, float co[2], bool extend)
{
- int sel = FALSE;
+ bool sel = false;
/* first try to select knot on selected curves */
sel = mouse_select_knot(C, co, extend);
@@ -269,7 +269,7 @@ static int mouse_select(bContext *C, float co[2], int extend)
static int select_exec(bContext *C, wmOperator *op)
{
float co[2];
- int extend = RNA_boolean_get(op->ptr, "extend");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
RNA_float_get_array(op->ptr, "location", co);
@@ -313,7 +313,8 @@ void CLIP_OT_graph_select(wmOperatorType *ot)
typedef struct BorderSelectuserData {
rctf rect;
- int change, mode, extend;
+ int mode;
+ bool change, extend;
} BorderSelectuserData;
static void border_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track),
@@ -352,13 +353,17 @@ static int border_select_graph_exec(bContext *C, wmOperator *op)
BorderSelectuserData userdata;
rcti rect;
+ if (act_track == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
/* get rectangle from operator */
WM_operator_properties_border_to_rcti(op, &rect);
UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &userdata.rect.xmin, &userdata.rect.ymin);
UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &userdata.rect.xmax, &userdata.rect.ymax);
- userdata.change = FALSE;
+ userdata.change = false;
userdata.mode = RNA_int_get(op->ptr, "gesture_mode");
userdata.extend = RNA_boolean_get(op->ptr, "extend");
@@ -466,11 +471,10 @@ static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
if (act_track)
- clip_delete_track(C, clip, tracksbase, act_track);
+ clip_delete_track(C, clip, act_track);
return OPERATOR_FINISHED;
}
@@ -498,7 +502,6 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
if (act_track) {
@@ -508,7 +511,7 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
MovieTrackingMarker *marker = &act_track->markers[a];
if (marker->flag & MARKER_GRAPH_SEL)
- clip_delete_marker(C, clip, tracksbase, act_track, marker);
+ clip_delete_marker(C, clip, act_track, marker);
else
a++;
}
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 51cb83eecad..39af856d280 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -112,6 +112,8 @@ void CLIP_OT_prefetch(struct wmOperatorType *ot);
void CLIP_OT_set_scene_frames(wmOperatorType *ot);
+void CLIP_OT_cursor_set(struct wmOperatorType *ot);
+
/* clip_toolbar.c */
struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa);
void CLIP_OT_tools(struct wmOperatorType *ot);
@@ -132,8 +134,8 @@ void clip_graph_tracking_values_iterate(struct SpaceClip *sc, int selected_only,
void clip_graph_tracking_iterate(struct SpaceClip *sc, int selected_only, int include_hidden, void *userdata,
void (*func)(void *userdata, struct MovieTrackingMarker *marker));
-void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track);
-void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
+void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track);
+void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
void clip_view_center_to_point(SpaceClip *sc, float x, float y);
@@ -193,6 +195,12 @@ void CLIP_OT_tracking_object_remove(struct wmOperatorType *ot);
void CLIP_OT_copy_tracks(struct wmOperatorType *ot);
void CLIP_OT_paste_tracks(struct wmOperatorType *ot);
+void CLIP_OT_create_plane_track(struct wmOperatorType *ot);
+void CLIP_OT_slide_plane_marker(struct wmOperatorType *ot);
+
+void CLIP_OT_keyframe_insert(struct wmOperatorType *ot);
+void CLIP_OT_keyframe_delete(struct wmOperatorType *ot);
+
/* tracking_select.c */
void CLIP_OT_select(struct wmOperatorType *ot);
void CLIP_OT_select_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index de19df9abe2..a76f4364492 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -181,7 +181,7 @@ static int open_exec(bContext *C, wmOperator *op)
PointerRNA fileptr;
PropertyRNA *prop;
char dir_only[FILE_MAX], file_only[FILE_MAX];
- int relative = RNA_boolean_get(op->ptr, "relative_path");
+ bool relative = RNA_boolean_get(op->ptr, "relative_path");
RNA_string_get(op->ptr, "directory", dir_only);
if (relative)
@@ -335,7 +335,7 @@ static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
ViewPanData *vpd;
op->customdata = vpd = MEM_callocN(sizeof(ViewPanData), "ClipViewPanData");
- WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
vpd->x = event->x;
vpd->y = event->y;
@@ -353,7 +353,7 @@ static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
WM_event_add_modal_handler(C, op);
}
-static void view_pan_exit(bContext *C, wmOperator *op, int cancel)
+static void view_pan_exit(bContext *C, wmOperator *op, bool cancel)
{
ViewPanData *vpd = op->customdata;
@@ -363,7 +363,7 @@ static void view_pan_exit(bContext *C, wmOperator *op, int cancel)
ED_region_tag_redraw(CTX_wm_region(C));
}
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(op->customdata);
}
@@ -490,7 +490,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
ViewZoomData *vpd;
op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ClipViewZoomData");
- WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
vpd->x = event->x;
vpd->y = event->y;
@@ -502,7 +502,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
WM_event_add_modal_handler(C, op);
}
-static void view_zoom_exit(bContext *C, wmOperator *op, int cancel)
+static void view_zoom_exit(bContext *C, wmOperator *op, bool cancel)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ViewZoomData *vpd = op->customdata;
@@ -512,7 +512,7 @@ static void view_zoom_exit(bContext *C, wmOperator *op, int cancel)
ED_region_tag_redraw(CTX_wm_region(C));
}
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(op->customdata);
}
@@ -736,7 +736,7 @@ static int view_all_exec(bContext *C, wmOperator *op)
ARegion *ar;
int w, h, width, height;
float aspx, aspy;
- int fit_view = RNA_boolean_get(op->ptr, "fit_view");
+ bool fit_view = RNA_boolean_get(op->ptr, "fit_view");
float zoomx, zoomy;
/* retrieve state */
@@ -782,6 +782,8 @@ static int view_all_exec(bContext *C, wmOperator *op)
void CLIP_OT_view_all(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View All";
ot->idname = "CLIP_OT_view_all";
@@ -792,7 +794,8 @@ void CLIP_OT_view_all(wmOperatorType *ot)
ot->poll = ED_space_clip_view_clip_poll;
/* properties */
- RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/********************** view selected operator *********************/
@@ -943,7 +946,8 @@ typedef struct ProxyBuildJob {
Scene *scene;
struct Main *main;
MovieClip *clip;
- int clip_flag, stop;
+ int clip_flag;
+ bool stop;
struct IndexBuildContext *index_context;
} ProxyJob;
@@ -1123,10 +1127,10 @@ static void *do_proxy_thread(void *data_v)
ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, NULL, "proxy frame");
BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra,
- data->build_sizes, data->build_count, FALSE);
+ data->build_sizes, data->build_count, false);
BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra,
- data->build_undistort_sizes, data->build_undistort_count, TRUE);
+ data->build_undistort_sizes, data->build_undistort_count, true);
IMB_freeImBuf(ibuf);
@@ -1455,6 +1459,59 @@ void CLIP_OT_set_scene_frames(wmOperatorType *ot)
ot->exec = clip_set_scene_frames_exec;
}
+/******************** set 3d cursor operator ********************/
+
+static int clip_set_2d_cursor_exec(bContext *C, wmOperator *op)
+{
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+ bool show_cursor = false;
+
+ show_cursor |= sclip->mode == SC_MODE_MASKEDIT;
+ show_cursor |= sclip->around == V3D_CURSOR;
+
+ if (!show_cursor) {
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_float_get_array(op->ptr, "location", sclip->cursor);
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int clip_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceClip *sclip = CTX_wm_space_clip(C);
+ float location[2];
+
+ ED_clip_mouse_pos(sclip, ar, event->mval, location);
+ RNA_float_set_array(op->ptr, "location", location);
+
+ return clip_set_2d_cursor_exec(C, op);
+}
+
+void CLIP_OT_cursor_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set 2D Cursor";
+ ot->description = "Set 2D cursor location";
+ ot->idname = "CLIP_OT_cursor_set";
+
+ /* api callbacks */
+ ot->exec = clip_set_2d_cursor_exec;
+ ot->invoke = clip_set_2d_cursor_invoke;
+ ot->poll = ED_space_clip_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location",
+ "Cursor location in normalized clip coordinates", -10.0f, 10.0f);
+}
+
/********************** macroses *********************/
void ED_operatormacros_clip(void)
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index d7a9b1c0cb6..635aa388541 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -76,7 +76,8 @@ void clip_graph_tracking_values_iterate_track(
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
for (coord = 0; coord < 2; coord++) {
- int i, open = FALSE, prevfra = 0;
+ int i, prevfra = 0;
+ bool open = false;
float prevval = 0.0f;
for (i = 0; i < track->markersnr; i++) {
@@ -88,7 +89,7 @@ void clip_graph_tracking_values_iterate_track(
if (segment_end)
segment_end(userdata);
- open = FALSE;
+ open = false;
}
continue;
@@ -98,7 +99,7 @@ void clip_graph_tracking_values_iterate_track(
if (segment_start)
segment_start(userdata, track, coord);
- open = TRUE;
+ open = true;
prevval = marker->pos[coord];
}
@@ -175,13 +176,16 @@ void clip_graph_tracking_iterate(SpaceClip *sc, int selected_only, int include_h
}
}
-void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, MovieTrackingTrack *track)
+void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
{
MovieTracking *tracking = &clip->tracking;
MovieTrackingStabilization *stab = &tracking->stabilization;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+ MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+ ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
- int has_bundle = FALSE, update_stab = FALSE;
+ bool has_bundle = false, update_stab = false;
if (track == act_track)
tracking->act_track = NULL;
@@ -189,12 +193,57 @@ void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, Movie
if (track == stab->rot_track) {
stab->rot_track = NULL;
- update_stab = TRUE;
+ update_stab = true;
}
/* handle reconstruction display in 3d viewport */
if (track->flag & TRACK_HAS_BUNDLE)
- has_bundle = TRUE;
+ has_bundle = true;
+
+ /* Make sure no plane will use freed track */
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = next_plane_track)
+ {
+ bool found = false;
+ int i;
+
+ next_plane_track = plane_track->next;
+
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] == track) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ continue;
+ }
+
+ if (plane_track->point_tracksnr > 4) {
+ int track_index;
+ MovieTrackingTrack **new_point_tracks;
+
+ new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * plane_track->point_tracksnr,
+ "new point tracks array");
+
+ for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] != track) {
+ new_point_tracks[track_index++] = plane_track->point_tracks[i];
+ }
+ }
+
+ MEM_freeN(plane_track->point_tracks);
+ plane_track->point_tracks = new_point_tracks;
+ plane_track->point_tracksnr--;
+ }
+ else {
+ /* Delete planes with less than 3 point tracks in it. */
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ }
+ }
BKE_tracking_track_free(track);
BLI_freelinkN(tracksbase, track);
@@ -212,11 +261,11 @@ void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, Movie
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
-void clip_delete_marker(bContext *C, MovieClip *clip, ListBase *tracksbase,
- MovieTrackingTrack *track, MovieTrackingMarker *marker)
+void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track,
+ MovieTrackingMarker *marker)
{
if (track->markersnr == 1) {
- clip_delete_track(C, clip, tracksbase, track);
+ clip_delete_track(C, clip, track);
}
else {
BKE_tracking_marker_delete(track, marker->framenr);
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 562a8584560..3ede63adb72 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -56,6 +56,7 @@
#include "ED_screen.h"
#include "ED_clip.h"
#include "ED_transform.h"
+#include "ED_uvedit.h" /* just for draw_image_cursor */
#include "IMB_imbuf.h"
@@ -442,6 +443,7 @@ static void clip_operatortypes(void)
WM_operatortype_append(CLIP_OT_view_ndof);
WM_operatortype_append(CLIP_OT_prefetch);
WM_operatortype_append(CLIP_OT_set_scene_frames);
+ WM_operatortype_append(CLIP_OT_cursor_set);
/* ** clip_toolbar.c ** */
WM_operatortype_append(CLIP_OT_tools);
@@ -517,6 +519,13 @@ static void clip_operatortypes(void)
WM_operatortype_append(CLIP_OT_copy_tracks);
WM_operatortype_append(CLIP_OT_paste_tracks);
+ /* Plane tracker */
+ WM_operatortype_append(CLIP_OT_create_plane_track);
+ WM_operatortype_append(CLIP_OT_slide_plane_marker);
+
+ WM_operatortype_append(CLIP_OT_keyframe_insert);
+ WM_operatortype_append(CLIP_OT_keyframe_delete);
+
/* ** clip_graph_ops.c ** */
/* graph editing */
@@ -685,6 +694,12 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "CLIP_OT_hide_tracks_clear", HKEY, KM_PRESS, KM_ALT, 0);
+ /* plane tracks */
+ WM_keymap_add_item(keymap, "CLIP_OT_slide_plane_marker", LEFTMOUSE, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "CLIP_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "CLIP_OT_keyframe_delete", IKEY, KM_PRESS, KM_ALT, 0);
+
/* clean-up */
WM_keymap_add_item(keymap, "CLIP_OT_join_tracks", JKEY, KM_PRESS, KM_CTRL, 0);
@@ -717,6 +732,26 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(kmi->ptr, "action", TRACK_CLEAR_ALL);
RNA_boolean_set(kmi->ptr, "clear_active", FALSE);
+ /* Cursor */
+ WM_keymap_add_item(keymap, "CLIP_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
+
+ /* pivot point */
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "BOUNDING_BOX_CENTER");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", COMMAKEY, KM_PRESS, KM_CTRL, 0); /* 2.4x allowed Comma+Shift too, rather not use both */
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "MEDIAN_POINT");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "CURSOR");
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", PERIODKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point");
+ RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS");
+
/* ******** Hotkeys avalaible for preview region only ******** */
keymap = WM_keymap_find(keyconf, "Clip Graph Editor", SPACE_CLIP, 0);
@@ -847,36 +882,36 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ARegion *ar_preview = ED_clip_has_preview_region(C, sa);
ARegion *ar_properties = ED_clip_has_properties_region(sa);
ARegion *ar_channels = ED_clip_has_channels_region(sa);
- int main_visible = FALSE, preview_visible = FALSE, tools_visible = FALSE;
- int tool_props_visible = FALSE, properties_visible = FALSE, channels_visible = FALSE;
- int view_changed = FALSE;
+ bool main_visible = false, preview_visible = false, tools_visible = false;
+ bool tool_props_visible = false, properties_visible = false, channels_visible = false;
+ bool view_changed = false;
switch (sc->view) {
case SC_VIEW_CLIP:
- main_visible = TRUE;
- preview_visible = FALSE;
- tools_visible = TRUE;
- tool_props_visible = TRUE;
- properties_visible = TRUE;
- channels_visible = FALSE;
+ main_visible = true;
+ preview_visible = false;
+ tools_visible = true;
+ tool_props_visible = true;
+ properties_visible = true;
+ channels_visible = false;
break;
case SC_VIEW_GRAPH:
- main_visible = FALSE;
- preview_visible = TRUE;
- tools_visible = FALSE;
- tool_props_visible = FALSE;
- properties_visible = FALSE;
- channels_visible = FALSE;
+ main_visible = false;
+ preview_visible = true;
+ tools_visible = false;
+ tool_props_visible = false;
+ properties_visible = false;
+ channels_visible = false;
reinit_preview_region(C, ar_preview);
break;
case SC_VIEW_DOPESHEET:
- main_visible = FALSE;
- preview_visible = TRUE;
- tools_visible = FALSE;
- tool_props_visible = FALSE;
- properties_visible = FALSE;
- channels_visible = TRUE;
+ main_visible = false;
+ preview_visible = true;
+ tools_visible = false;
+ tool_props_visible = false;
+ properties_visible = false;
+ channels_visible = true;
reinit_preview_region(C, ar_preview);
break;
@@ -886,12 +921,12 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
ar_main->flag &= ~RGN_FLAG_HIDDEN;
ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -899,11 +934,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_main->flag |= RGN_FLAG_HIDDEN;
ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -911,11 +946,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_properties && (ar_properties->flag & RGN_FLAG_HIDDEN)) {
ar_properties->flag &= ~RGN_FLAG_HIDDEN;
ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) {
ar_properties->alignment = RGN_ALIGN_RIGHT;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -923,11 +958,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_properties->flag |= RGN_FLAG_HIDDEN;
ar_properties->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_properties->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) {
ar_properties->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -935,11 +970,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_tools && (ar_tools->flag & RGN_FLAG_HIDDEN)) {
ar_tools->flag &= ~RGN_FLAG_HIDDEN;
ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) {
ar_tools->alignment = RGN_ALIGN_LEFT;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -947,11 +982,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_tools->flag |= RGN_FLAG_HIDDEN;
ar_tools->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_tools->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) {
ar_tools->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -959,11 +994,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_tool_props && (ar_tool_props->flag & RGN_FLAG_HIDDEN)) {
ar_tool_props->flag &= ~RGN_FLAG_HIDDEN;
ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tool_props && (ar_tool_props->alignment != (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) {
ar_tool_props->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -971,11 +1006,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_tool_props->flag |= RGN_FLAG_HIDDEN;
ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_tool_props->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_tool_props && ar_tool_props->alignment != RGN_ALIGN_NONE) {
ar_tool_props->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -984,11 +1019,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_preview->flag &= ~RGN_FLAG_HIDDEN;
ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
ar_preview->v2d.cur = ar_preview->v2d.tot;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
ar_preview->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -996,11 +1031,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_preview->flag |= RGN_FLAG_HIDDEN;
ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
ar_preview->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -1008,11 +1043,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
if (ar_channels && (ar_channels->flag & RGN_FLAG_HIDDEN)) {
ar_channels->flag &= ~RGN_FLAG_HIDDEN;
ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) {
ar_channels->alignment = RGN_ALIGN_LEFT;
- view_changed = TRUE;
+ view_changed = true;
}
}
else {
@@ -1020,11 +1055,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa)
ar_channels->flag |= RGN_FLAG_HIDDEN;
ar_channels->v2d.flag &= ~V2D_IS_INITIALISED;
WM_event_remove_handlers((bContext *)C, &ar_channels->handlers);
- view_changed = TRUE;
+ view_changed = true;
}
if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) {
ar_channels->alignment = RGN_ALIGN_NONE;
- view_changed = TRUE;
+ view_changed = true;
}
}
@@ -1109,6 +1144,9 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
/* draw entirely, view changes should be handled here */
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
+ float aspx, aspy, zoomx, zoomy, x, y;
+ int width, height;
+ bool show_cursor = false;
/* if tracking is in progress, we should synchronize framenr from clipuser
* so latest tracked frame would be shown */
@@ -1140,29 +1178,43 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
clip_draw_main(C, sc, ar);
- if (sc->mode == SC_MODE_MASKEDIT) {
+ /* TODO(sergey): would be nice to find a way to de-duplicate all this space conversions */
+ UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y);
+ ED_space_clip_get_size(sc, &width, &height);
+ ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ if (sc->mode == SC_MODE_MASKEDIT) {
Mask *mask = CTX_data_edit_mask(C);
if (mask) {
ScrArea *sa = CTX_wm_area(C);
- int width, height;
- float aspx, aspy;
- ED_mask_get_size(sa, &width, &height);
- ED_space_clip_get_aspect(sc, &aspx, &aspy);
+ int mask_width, mask_height;
+ ED_mask_get_size(sa, &mask_width, &mask_height);
ED_mask_draw_region(mask, ar,
sc->mask_info.draw_flag, sc->mask_info.draw_type,
- width, height,
+ mask_width, mask_height,
aspx, aspy,
TRUE, TRUE,
sc->stabmat, C);
}
+ }
-
+ show_cursor |= sc->mode == SC_MODE_MASKEDIT;
+ show_cursor |= sc->around == V3D_CURSOR;
+
+ if (show_cursor) {
+ glPushMatrix();
+ glTranslatef(x, y, 0);
+ glScalef(zoomx, zoomy, 0);
+ glMultMatrixf(sc->stabmat);
+ glScalef(width, height, 0);
+ draw_image_cursor(ar, sc->cursor);
+ glPopMatrix();
}
if (sc->flag & SC_SHOW_GPENCIL) {
/* Grease Pencil */
- clip_draw_grease_pencil((bContext *)C, TRUE);
+ clip_draw_grease_pencil((bContext *)C, true);
}
/* reset view matrix */
@@ -1170,7 +1222,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
if (sc->flag & SC_SHOW_GPENCIL) {
/* draw Grease Pencil - screen space only */
- clip_draw_grease_pencil((bContext *)C, FALSE);
+ clip_draw_grease_pencil((bContext *)C, false);
}
}
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index f3d070452a5..246ea7fe140 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -34,6 +34,7 @@
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_object_types.h" /* SELECT */
#include "DNA_scene_types.h"
@@ -55,6 +56,8 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_library.h"
+#include "BKE_mask.h"
+#include "BKE_node.h"
#include "BKE_sound.h"
#include "WM_api.h"
@@ -88,6 +91,7 @@ static bool add_marker(const bContext *C, float x, float y)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
MovieTrackingTrack *track;
int width, height;
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -101,8 +105,10 @@ static bool add_marker(const bContext *C, float x, float y)
track = BKE_tracking_track_add(tracking, tracksbase, x, y, framenr, width, height);
BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, 0);
+ BKE_tracking_plane_tracks_deselect_all(plane_tracks_base);
clip->tracking.act_track = track;
+ clip->tracking.act_plane_track = NULL;
return true;
}
@@ -234,13 +240,31 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
MovieTrackingTrack *track = tracksbase->first, *next;
+ MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+ bool modified = false;
+
+ /* Delete selected plane tracks. */
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = next_plane_track)
+ {
+ next_plane_track = plane_track->next;
+
+ if (plane_track->flag & SELECT) {
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ modified = true;
+ }
+ }
+ /* Remove selected point tracks (they'll also be removed from planes which uses them). */
while (track) {
next = track->next;
if (TRACK_VIEW_SELECTED(sc, track))
- clip_delete_track(C, clip, tracksbase, track);
+ clip_delete_track(C, clip, track);
track = next;
}
@@ -248,6 +272,10 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
/* nothing selected now, unlock view so it can be scrolled nice again */
sc->flag &= ~SC_LOCK_SELECTION;
+ if (modified) {
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+ }
+
return OPERATOR_FINISHED;
}
@@ -274,7 +302,9 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
MovieTrackingTrack *track = tracksbase->first, *next;
+ MovieTrackingPlaneTrack *plane_track, *plane_track_next;
int framenr = ED_space_clip_get_clip_frame_number(sc);
int has_selection = 0;
@@ -287,13 +317,34 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
if (marker) {
has_selection |= track->markersnr > 1;
- clip_delete_marker(C, clip, tracksbase, track, marker);
+ clip_delete_marker(C, clip, track, marker);
}
}
track = next;
}
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track_next)
+ {
+ plane_track_next = plane_track->next;
+
+ if (plane_track->flag & SELECT) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, framenr);
+
+ if (plane_marker) {
+ if (plane_track->markersnr == 1) {
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ }
+ else {
+ BKE_tracking_plane_marker_delete(plane_track, framenr);
+ }
+ }
+ }
+ }
+
if (!has_selection) {
/* nothing selected now, unlock view so it can be scrolled nice again */
sc->flag &= ~SC_LOCK_SELECTION;
@@ -542,14 +593,14 @@ static int mouse_on_tilt(SpaceClip *sc, MovieTrackingMarker *marker, float co[2]
return mouse_on_slide_zone(sc, marker, TRACK_AREA_PAT, co, slider, 0.0f, width, height);
}
-static int slide_check_corners(float (*corners)[2])
+static bool slide_check_corners(float (*corners)[2])
{
int i, next, prev;
float cross = 0.0f;
float p[2] = {0.0f, 0.0f};
if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3]))
- return FALSE;
+ return false;
for (i = 0; i < 4; i++) {
float v1[2], v2[2], cur_cross;
@@ -567,12 +618,12 @@ static int slide_check_corners(float (*corners)[2])
cross = cur_cross;
}
else if (cross * cur_cross < 0.0f) {
- return FALSE;
+ return false;
}
}
}
- return TRUE;
+ return true;
}
static void hide_cursor(bContext *C)
@@ -613,25 +664,25 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even
while (track) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- int ok = FALSE;
+ bool ok = false;
if ((marker->flag & MARKER_DISABLED) == 0) {
if (mouse_on_offset(sc, track, marker, co, width, height)) {
area = TRACK_AREA_POINT;
action = SLIDE_ACTION_POS;
- ok = TRUE;
+ ok = true;
}
if (!ok && (sc->flag & SC_SHOW_MARKER_SEARCH)) {
if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 1, 0.0f, width, height)) {
area = TRACK_AREA_SEARCH;
action = SLIDE_ACTION_OFFSET;
- ok = TRUE;
+ ok = true;
}
else if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 0, 0.0f, width, height)) {
area = TRACK_AREA_SEARCH;
action = SLIDE_ACTION_SIZE;
- ok = TRUE;
+ ok = true;
}
}
@@ -642,7 +693,7 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_POS;
corner = current_corner;
- ok = TRUE;
+ ok = true;
}
else {
#if 0
@@ -651,18 +702,18 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even
if (mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 1, 12.0f, width, height)) {
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_OFFSET;
- ok = TRUE;
+ ok = true;
}
if (!ok && mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 0, 12.0f, width, height)) {
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_SIZE;
- ok = TRUE;
+ ok = true;
}
#endif
if (!ok && mouse_on_tilt(sc, marker, co, width, height)) {
area = TRACK_AREA_PAT;
action = SLIDE_ACTION_TILT_SIZE;
- ok = TRUE;
+ ok = true;
}
}
}
@@ -727,6 +778,7 @@ static int slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event
MovieTracking *tracking = &clip->tracking;
tracking->act_track = slidedata->track;
+ tracking->act_plane_track = NULL;
op->customdata = slidedata;
@@ -760,6 +812,32 @@ static void cancel_mouse_slide(SlideMarkerData *data)
}
}
+static void apply_mouse_slide(bContext *C, SlideMarkerData *data)
+{
+ if (data->area == TRACK_AREA_POINT) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] == data->track) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
static void free_slide_data(SlideMarkerData *data)
{
if (data->old_markers)
@@ -955,6 +1033,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
if (event->val == KM_RELEASE) {
+ apply_mouse_slide(C, op->customdata);
free_slide_data(op->customdata);
show_cursor(C);
@@ -1093,18 +1172,18 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit
*frames_limit_r = frames_limit;
}
-static int track_markers_check_direction(int backwards, int curfra, int efra)
+static bool track_markers_check_direction(int backwards, int curfra, int efra)
{
if (backwards) {
if (curfra < efra)
- return FALSE;
+ return false;
}
else {
if (curfra > efra)
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backwards)
@@ -1215,7 +1294,7 @@ static void track_markers_updatejob(void *tmv)
BKE_tracking_context_sync(tmj->context);
}
-static void track_markers_freejob(void *tmv)
+static void track_markers_endjob(void *tmv)
{
TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
@@ -1224,10 +1303,15 @@ static void track_markers_freejob(void *tmv)
ED_update_for_newframe(tmj->main, tmj->scene, 0);
BKE_tracking_context_sync(tmj->context);
- BKE_tracking_context_free(tmj->context);
+ BKE_tracking_context_finish(tmj->context);
WM_main_add_notifier(NC_SCENE | ND_FRAME, tmj->scene);
+}
+static void track_markers_freejob(void *tmv)
+{
+ TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
+ BKE_tracking_context_free(tmj->context);
MEM_freeN(tmj);
}
@@ -1281,6 +1365,7 @@ static int track_markers_exec(bContext *C, wmOperator *op)
}
BKE_tracking_context_sync(context);
+ BKE_tracking_context_finish(context);
BKE_tracking_context_free(context);
/* update scene current frame to the lastes tracked frame */
@@ -1337,7 +1422,7 @@ static int track_markers_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
else
WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | NA_EVALUATED, 0);
- WM_jobs_callbacks(wm_job, track_markers_startjob, NULL, track_markers_updatejob, NULL);
+ WM_jobs_callbacks(wm_job, track_markers_startjob, NULL, track_markers_updatejob, track_markers_endjob);
G.is_break = FALSE;
@@ -1822,13 +1907,13 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
Object *camera = scene->camera;
Base *base;
- if (camera && BKE_object_movieclip_get(scene, camera, 0) == clip)
+ if (camera && BKE_object_movieclip_get(scene, camera, false) == clip)
return camera;
base = scene->base.first;
while (base) {
if (base->object->type == OB_CAMERA) {
- if (BKE_object_movieclip_get(scene, base->object, 0) == clip) {
+ if (BKE_object_movieclip_get(scene, base->object, false) == clip) {
camera = base->object;
break;
}
@@ -1908,7 +1993,7 @@ static int count_selected_bundles(bContext *C)
static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat[4][4])
{
bConstraint *con;
- int found = FALSE;
+ bool found = false;
for (con = ob->constraints.first; con; con = con->next) {
bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
@@ -1927,7 +2012,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat
mul_m4_m4m4(invmat, invmat, data->invmat);
- found = TRUE;
+ found = true;
}
}
@@ -2047,7 +2132,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
{
Object *camera = get_camera_with_movieclip(scene, clip);
int is_camera = tracking_object->flag & TRACKING_OBJECT_CAMERA;
- int flip = FALSE;
+ bool flip = false;
float mat[4][4], vec[3], obmat[4][4], dvec[3];
BKE_object_to_mat4(ob, obmat);
@@ -2075,7 +2160,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
if (axis == 'X') {
if (fabsf(dvec[1]) < 1e-3f) {
- flip = TRUE;
+ flip = true;
mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f;
mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f;
@@ -2099,7 +2184,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
}
else {
if (fabsf(dvec[0]) < 1e-3f) {
- flip = TRUE;
+ flip = true;
mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f;
mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f;
@@ -2320,7 +2405,7 @@ static int set_axis_exec(bContext *C, wmOperator *op)
track = tracksbase->first;
while (track) {
- if (TRACK_VIEW_SELECTED(sc, track))
+ if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_HAS_BUNDLE))
break;
track = track->next;
@@ -3670,3 +3755,446 @@ void CLIP_OT_paste_tracks(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/********************** Create plane track operator *********************/
+
+static int create_plane_track_tracks_exec(bContext *C, wmOperator *op)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ plane_track = BKE_tracking_plane_track_add(tracking, plane_tracks_base, tracks_base, framenr);
+
+ if (plane_track == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Need at least 4 selected point tracks to create a plane");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ BKE_tracking_tracks_deselect_all(tracks_base);
+
+ plane_track->flag |= SELECT;
+ clip->tracking.act_track = NULL;
+ clip->tracking.act_plane_track = plane_track;
+
+ /* Copute homoraphies and apply them on marker's corner, so we've got
+ * quite nice motion from the very beginning.
+ */
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+ return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_create_plane_track(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Create Plane Track";
+ ot->description = "Create new plane track out of selected point tracks";
+ ot->idname = "CLIP_OT_create_plane_track";
+
+ /* api callbacks */
+ ot->exec = create_plane_track_tracks_exec;
+ ot->poll = ED_space_clip_tracking_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** Slide plane marker corner operator *********************/
+
+typedef struct SlidePlaneMarkerData {
+ MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingPlaneMarker *plane_marker;
+ int width, height;
+ int corner_index;
+ float *corner;
+ int previous_mval[2];
+ float previous_corner[2];
+ float old_corner[2];
+ bool accurate;
+} SlidePlaneMarkerData;
+
+static bool mouse_on_plane_slide_zone(SpaceClip *sc, float co[2], float slide_zone[2], int width, int height)
+{
+ const float size = 12.0f;
+ float dx, dy;
+
+ dx = size / width / sc->zoom;
+ dy = size / height / sc->zoom;
+
+ return IN_RANGE_INCL(co[0], slide_zone[0] - dx, slide_zone[0] + dx) &&
+ IN_RANGE_INCL(co[1], slide_zone[1] - dy, slide_zone[1] + dy);
+}
+
+static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C, const wmEvent *event, int *corner_r)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingPlaneTrack *plane_track;
+ int width, height;
+ float co[2];
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ ED_space_clip_get_size(sc, &width, &height);
+
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
+
+ ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (plane_track->flag & SELECT) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+ bool ok = false;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (mouse_on_plane_slide_zone(sc, co, plane_marker->corners[i], width, height)) {
+ if (corner_r) {
+ *corner_r = i;
+ }
+ ok = true;
+ break;
+ }
+ }
+
+ if (ok) {
+ return plane_track;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void *slide_plane_marker_customdata(bContext *C, const wmEvent *event)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ MovieTrackingPlaneTrack *plane_track;
+ int width, height;
+ float co[2];
+ SlidePlaneMarkerData *customdata = NULL;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+ int corner;
+
+ ED_space_clip_get_size(sc, &width, &height);
+
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
+
+ ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+ plane_track = tracking_plane_marker_check_slide(C, event, &corner);
+ if (plane_track) {
+ MovieTrackingPlaneMarker *plane_marker;
+
+ customdata = MEM_callocN(sizeof(SlidePlaneMarkerData), "slide plane marker data");
+
+ plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+
+ customdata->plane_track = plane_track;
+ customdata->plane_marker = plane_marker;
+ customdata->width = width;
+ customdata->height = height;
+
+ customdata->previous_mval[0] = event->mval[0];
+ customdata->previous_mval[1] = event->mval[1];
+
+ customdata->corner_index = corner;
+ customdata->corner = plane_marker->corners[corner];
+
+ copy_v2_v2(customdata->previous_corner, customdata->corner);
+ copy_v2_v2(customdata->old_corner, customdata->corner);
+ }
+
+ return customdata;
+}
+
+static int slide_plane_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ SlidePlaneMarkerData *slidedata = slide_plane_marker_customdata(C, event);
+
+ if (slidedata) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+
+ tracking->act_plane_track = slidedata->plane_track;
+ tracking->act_track = NULL;
+
+ op->customdata = slidedata;
+
+ hide_cursor(C);
+ WM_event_add_modal_handler(C, op);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+static void cancel_mouse_slide_plane_marker(SlidePlaneMarkerData *data)
+{
+ copy_v2_v2(data->corner, data->old_corner);
+}
+
+static void free_slide_plane_marker_data(SlidePlaneMarkerData *data)
+{
+ MEM_freeN(data);
+}
+
+static void slide_plane_marker_update_homographies(SpaceClip *sc, SlidePlaneMarkerData *data)
+{
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ BKE_tracking_track_plane_from_existing_motion(data->plane_track, framenr);
+}
+
+static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ SlidePlaneMarkerData *data = (SlidePlaneMarkerData *) op->customdata;
+ float dx, dy, mdelta[2];
+ int next_corner_index, prev_corner_index, diag_corner_index;
+ float *next_corner, *prev_corner, *diag_corner;
+ float next_edge[2], prev_edge[2], next_diag_edge[2], prev_diag_edge[2];
+
+ switch (event->type) {
+ case LEFTCTRLKEY:
+ case RIGHTCTRLKEY:
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
+ data->accurate = event->val == KM_PRESS;
+
+ /* fall-through */
+ case MOUSEMOVE:
+ mdelta[0] = event->mval[0] - data->previous_mval[0];
+ mdelta[1] = event->mval[1] - data->previous_mval[1];
+
+ dx = mdelta[0] / data->width / sc->zoom;
+ dy = mdelta[1] / data->height / sc->zoom;
+
+ if (data->accurate) {
+ dx /= 5.0f;
+ dy /= 5.0f;
+ }
+
+ data->corner[0] = data->previous_corner[0] + dx;
+ data->corner[1] = data->previous_corner[1] + dy;
+
+
+ /*
+ prev_edge
+ (Corner 3, current) <----------------------- (Corner 2, previous)
+ | ^
+ | |
+ | |
+ | |
+ next_edge | | next_diag_edge
+ | |
+ | |
+ | |
+ v |
+ (Corner 0, next) -----------------------> (Corner 1, diagonal)
+ prev_diag_edge
+ */
+
+ next_corner_index = (data->corner_index + 1) % 4;
+ prev_corner_index = (data->corner_index + 3) % 4;
+ diag_corner_index = (data->corner_index + 2) % 4;
+
+ next_corner = data->plane_marker->corners[next_corner_index];
+ prev_corner = data->plane_marker->corners[prev_corner_index];
+ diag_corner = data->plane_marker->corners[diag_corner_index];
+
+ sub_v2_v2v2(next_edge, next_corner, data->corner);
+ sub_v2_v2v2(prev_edge, data->corner, prev_corner);
+ sub_v2_v2v2(next_diag_edge, prev_corner, diag_corner);
+ sub_v2_v2v2(prev_diag_edge, diag_corner, next_corner);
+
+ if (cross_v2v2(prev_edge, next_edge) < 0.0f) {
+ closest_to_line_v2(data->corner, data->corner, prev_corner, next_corner);
+ }
+
+ if (cross_v2v2(next_diag_edge, prev_edge) < 0.0f) {
+ closest_to_line_v2(data->corner, data->corner, prev_corner, diag_corner);
+ }
+
+ if (cross_v2v2(next_edge, prev_diag_edge) < 0.0f) {
+ closest_to_line_v2(data->corner, data->corner, next_corner, diag_corner);
+ }
+
+ data->previous_mval[0] = event->mval[0];
+ data->previous_mval[1] = event->mval[1];
+ copy_v2_v2(data->previous_corner, data->corner);
+
+ DAG_id_tag_update(&sc->clip->id, 0);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+
+ break;
+
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ /* Marker is now keyframed. */
+ data->plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+
+ slide_plane_marker_update_homographies(sc, data);
+
+ free_slide_plane_marker_data(op->customdata);
+
+ show_cursor(C);
+
+ DAG_id_tag_update(&sc->clip->id, 0);
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+ return OPERATOR_FINISHED;
+ }
+
+ break;
+
+ case ESCKEY:
+ cancel_mouse_slide_plane_marker(op->customdata);
+
+ free_slide_plane_marker_data(op->customdata);
+
+ show_cursor(C);
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void CLIP_OT_slide_plane_marker(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Slide Plane Marker";
+ ot->description = "Slide plane marker areas";
+ ot->idname = "CLIP_OT_slide_plane_marker";
+
+ /* api callbacks */
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->invoke = slide_plane_marker_invoke;
+ ot->modal = slide_plane_marker_modal;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+}
+
+/********************** Insert track keyframe operator *********************/
+
+static void keyframe_set_flag(bContext *C, bool set)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (track = tracks_base->first; track; track = track->next) {
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ if (set) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
+ marker->flag &= ~MARKER_TRACKED;
+ }
+ else {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
+ if (marker) {
+ marker->flag |= MARKER_TRACKED;
+ }
+ }
+ }
+ }
+
+ for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+ if (plane_track->flag & SELECT) {
+ if (set) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+ if (plane_marker->flag & PLANE_MARKER_TRACKED) {
+ plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+ BKE_tracking_track_plane_from_existing_motion(plane_track, plane_marker->framenr);
+ }
+ }
+ else {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, framenr);
+ if (plane_marker) {
+ if ((plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
+ plane_marker->flag |= PLANE_MARKER_TRACKED;
+ BKE_tracking_retrack_plane_from_existing_motion_at_segment(plane_track, plane_marker->framenr);
+ }
+ }
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+}
+
+static int keyframe_insert_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ keyframe_set_flag(C, true);
+ return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_keyframe_insert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Insert keyframe";
+ ot->description = "Insert a keyframe to selected tracks at current frame";
+ ot->idname = "CLIP_OT_keyframe_insert";
+
+ /* api callbacks */
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->exec = keyframe_insert_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** Delete track keyframe operator *********************/
+
+static int keyframe_delete_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ keyframe_set_flag(C, false);
+ return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_keyframe_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete keyframe";
+ ot->description = "Delete a keyframe from selected tracks at current frame";
+ ot->idname = "CLIP_OT_keyframe_delete";
+
+ /* api callbacks */
+ ot->poll = ED_space_clip_tracking_poll;
+ ot->exec = keyframe_delete_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index b03209173d8..7cb5f9b5dc0 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -169,6 +169,7 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
return sqrtf(min_ffff(d1, d2, d3, d4));
}
+/* Distance to quad defined by it's corners, corners are relative to pos */
static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
{
float d1, d2, d3, d4;
@@ -184,7 +185,22 @@ static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
return sqrtf(min_ffff(d1, d2, d3, d4));
}
-static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2])
+/* Same as above, but all the coordinates are absolute */
+static float dist_to_crns_abs(float co[2], float corners[4][2])
+{
+ float d1, d2, d3, d4;
+ float *v1 = corners[0], *v2 = corners[1];
+ float *v3 = corners[2], *v4 = corners[3];
+
+ d1 = dist_squared_to_line_segment_v2(co, v1, v2);
+ d2 = dist_squared_to_line_segment_v2(co, v2, v3);
+ d3 = dist_squared_to_line_segment_v2(co, v3, v4);
+ d4 = dist_squared_to_line_segment_v2(co, v4, v1);
+
+ return sqrtf(min_ffff(d1, d2, d3, d4));
+}
+
+static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2], float *distance_r)
{
MovieTrackingTrack *track = NULL, *cur;
float mindist = 0.0f;
@@ -221,19 +237,88 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas
cur = cur->next;
}
+ *distance_r = mindist;
+
return track;
}
+static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc, ListBase *plane_tracks_base,
+ float co[2], float *distance_r)
+{
+ MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;
+ float min_distance = 0.0f;
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (current_plane_track = plane_tracks_base->first;
+ current_plane_track;
+ current_plane_track = current_plane_track->next)
+ {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(current_plane_track, framenr);
+
+ if ((current_plane_track->flag & TRACK_HIDDEN) == 0) {
+ float distance = dist_to_crns_abs(co, plane_marker->corners);
+ if (plane_track == NULL || distance < min_distance) {
+ plane_track = current_plane_track;
+ min_distance = distance;
+ }
+ }
+ }
+
+ *distance_r = min_distance;
+
+ return plane_track;
+}
+
+static void delect_all_tracks(ListBase *tracks_base)
+{
+ MovieTrackingTrack *track;
+ for (track = tracks_base->first;
+ track;
+ track = track->next)
+ {
+ BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+ }
+}
+
+static void delect_all_plane_tracks(ListBase *plane_tracks_base)
+{
+ MovieTrackingPlaneTrack *plane_track;
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ plane_track->flag &= ~SELECT;
+ }
+}
+
static int mouse_select(bContext *C, float co[2], int extend)
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingTrack *track = NULL; /* selected marker */
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
+ float distance_to_track, distance_to_plane_track;
+
+ track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
+ plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);
+
+ /* Between track and plane we choose closest to the mouse for selection here. */
+ if (track && plane_track) {
+ if (distance_to_track < distance_to_plane_track) {
+ plane_track = NULL;
+ }
+ else {
+ track = NULL;
+ }
+ }
- track = find_nearest_track(sc, tracksbase, co);
+ if (!extend) {
+ delect_all_plane_tracks(plane_tracks_base);
+ }
if (track) {
int area = track_mouse_area(C, co, track);
@@ -242,10 +327,13 @@ static int mouse_select(bContext *C, float co[2], int extend)
area = TRACK_AREA_ALL;
if (extend && TRACK_AREA_SELECTED(track, area)) {
- if (track == act_track)
+ if (track == act_track) {
BKE_tracking_track_deselect(track, area);
- else
+ }
+ else {
clip->tracking.act_track = track;
+ clip->tracking.act_plane_track = NULL;
+ }
}
else {
if (area == TRACK_AREA_POINT)
@@ -253,8 +341,26 @@ static int mouse_select(bContext *C, float co[2], int extend)
BKE_tracking_track_select(tracksbase, track, area, extend);
clip->tracking.act_track = track;
+ clip->tracking.act_plane_track = NULL;
}
}
+ else if (plane_track) {
+ if (!extend) {
+ delect_all_tracks(tracksbase);
+ }
+
+ if (plane_track->flag & SELECT) {
+ if (extend) {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ else {
+ plane_track->flag |= SELECT;
+ }
+
+ clip->tracking.act_track = NULL;
+ clip->tracking.act_plane_track = plane_track;
+ }
if (!extend) {
sc->xlockof = 0.0f;
@@ -350,10 +456,13 @@ static int border_select_exec(bContext *C, wmOperator *op)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
rcti rect;
rctf rectf;
- int change = FALSE, mode, extend;
+ bool change = false;
+ int mode, extend;
int framenr = ED_space_clip_get_clip_frame_number(sc);
/* get rectangle from operator */
@@ -382,13 +491,40 @@ static int border_select_exec(bContext *C, wmOperator *op)
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
}
- change = TRUE;
+ change = true;
}
}
track = track->next;
}
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ MovieTrackingPlaneMarker *plane_marker =
+ BKE_tracking_plane_marker_get(plane_track, framenr);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (BLI_rctf_isect_pt_v(&rectf, plane_marker->corners[i])) {
+ if (mode == GESTURE_MODAL_SELECT) {
+ plane_track->flag |= SELECT;
+ }
+ else {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ else if (!extend) {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+
+ change = true;
+ }
+ }
+
if (change) {
BKE_tracking_dopesheet_tag_update(tracking);
@@ -430,9 +566,11 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
rcti rect;
- int change = FALSE;
+ bool change = false;
int framenr = ED_space_clip_get_clip_frame_number(sc);
/* get rectangle from operator */
@@ -459,13 +597,44 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
}
- change = TRUE;
+ change = true;
}
}
track = track->next;
}
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ MovieTrackingPlaneMarker *plane_marker =
+ BKE_tracking_plane_marker_get(plane_track, framenr);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ float screen_co[2];
+
+ /* marker in screen coords */
+ ED_clip_point_stable_pos__reverse(sc, ar, plane_marker->corners[i], screen_co);
+
+ if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
+ BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED))
+ {
+ if (select) {
+ plane_track->flag |= SELECT;
+ }
+ else {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ }
+
+ change = true;
+ }
+ }
+
if (change) {
BKE_tracking_dopesheet_tag_update(tracking);
@@ -518,17 +687,22 @@ void CLIP_OT_select_lasso(wmOperatorType *ot)
/********************** circle select operator *********************/
-static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
+static int point_inside_ellipse(float point[2], float offset[2], float ellipse[2])
{
/* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
float x, y;
- x = (marker->pos[0] - offset[0]) * ellipse[0];
- y = (marker->pos[1] - offset[1]) * ellipse[1];
+ x = (point[0] - offset[0]) * ellipse[0];
+ y = (point[1] - offset[1]) * ellipse[1];
return x * x + y * y < 1.0f;
}
+static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
+{
+ return point_inside_ellipse(marker->pos, offset, ellipse);
+}
+
static int circle_select_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
@@ -537,8 +711,11 @@ static int circle_select_exec(bContext *C, wmOperator *op)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int x, y, radius, width, height, mode, change = FALSE;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ int x, y, radius, width, height, mode;
+ bool change = false;
float zoomx, zoomy, offset[2], ellipse[2];
int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -570,13 +747,37 @@ static int circle_select_exec(bContext *C, wmOperator *op)
else
BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
- change = TRUE;
+ change = true;
}
}
track = track->next;
}
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ MovieTrackingPlaneMarker *plane_marker =
+ BKE_tracking_plane_marker_get(plane_track, framenr);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (point_inside_ellipse(plane_marker->corners[i], offset, ellipse)) {
+ if (mode == GESTURE_MODAL_SELECT) {
+ plane_track->flag |= SELECT;
+ }
+ else {
+ plane_track->flag &= ~SELECT;
+ }
+ }
+ }
+
+ change = true;
+ }
+ }
+
if (change) {
BKE_tracking_dopesheet_tag_update(tracking);
@@ -619,16 +820,18 @@ static int select_all_exec(bContext *C, wmOperator *op)
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *track = NULL; /* selected track */
+ MovieTrackingPlaneTrack *plane_track = NULL; /* selected plane track */
MovieTrackingMarker *marker;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
int action = RNA_enum_get(op->ptr, "action");
int framenr = ED_space_clip_get_clip_frame_number(sc);
- int has_selection = FALSE;
+ bool has_selection = false;
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
- track = tracksbase->first;
- while (track) {
+
+ for (track = tracksbase->first; track; track = track->next) {
if (TRACK_VIEW_SELECTED(sc, track)) {
marker = BKE_tracking_marker_get(track, framenr);
@@ -637,13 +840,20 @@ static int select_all_exec(bContext *C, wmOperator *op)
break;
}
}
+ }
- track = track->next;
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (plane_track->flag & SELECT) {
+ action = SEL_DESELECT;
+ break;
+ }
}
}
- track = tracksbase->first;
- while (track) {
+ for (track = tracksbase->first; track; track = track->next) {
if ((track->flag & TRACK_HIDDEN) == 0) {
marker = BKE_tracking_marker_get(track, framenr);
@@ -669,9 +879,30 @@ static int select_all_exec(bContext *C, wmOperator *op)
}
if (TRACK_VIEW_SELECTED(sc, track))
- has_selection = TRUE;
+ has_selection = true;
+ }
- track = track->next;
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+ switch (action) {
+ case SEL_SELECT:
+ plane_track->flag |= SELECT;
+ break;
+ case SEL_DESELECT:
+ plane_track->flag &= ~SELECT;
+ break;
+ case SEL_INVERT:
+ plane_track->flag ^= SELECT;
+ break;
+ }
+ }
+
+ if (plane_track->flag & SELECT) {
+ has_selection = true;
+ }
}
if (!has_selection)
@@ -716,7 +947,7 @@ static int select_groped_exec(bContext *C, wmOperator *op)
track = tracksbase->first;
while (track) {
- int ok = FALSE;
+ bool ok = false;
marker = BKE_tracking_marker_get(track, framenr);
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index c10ea96096f..289986d7fba 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -681,6 +681,7 @@ static int console_clear_exec(bContext *C, wmOperator *op)
if (history) {
while (sc->history.first)
console_history_free(sc, sc->history.first);
+ console_history_verify(C);
}
console_textview_update_rect(sc, ar);
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 88a04197847..5c8d1e84fd5 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -317,6 +317,7 @@ static void console_keymap(struct wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD);
WM_keymap_add_item(keymap, "CONSOLE_OT_clear_line", RETKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "CONSOLE_OT_clear_line", PADENTER, KM_PRESS, KM_SHIFT, 0);
#ifdef WITH_PYTHON
kmi = WM_keymap_add_item(keymap, "CONSOLE_OT_execute", RETKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 240106d37d5..d01286442be 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -65,7 +65,7 @@ void FILE_OT_select_all_toggle(struct wmOperatorType *ot);
void FILE_OT_select_border(struct wmOperatorType *ot);
void FILE_OT_select_bookmark(struct wmOperatorType *ot);
void FILE_OT_bookmark_add(struct wmOperatorType *ot);
-void FILE_OT_delete_bookmark(struct wmOperatorType *ot);
+void FILE_OT_bookmark_delete(struct wmOperatorType *ot);
void FILE_OT_reset_recent(wmOperatorType *ot);
void FILE_OT_hidedot(struct wmOperatorType *ot);
void FILE_OT_execute(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index e3270d9ce8e..a97b3b1d719 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -503,14 +503,14 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void FILE_OT_delete_bookmark(wmOperatorType *ot)
+void FILE_OT_bookmark_delete(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Delete Bookmark";
ot->description = "Delete selected bookmark";
- ot->idname = "FILE_OT_delete_bookmark";
+ ot->idname = "FILE_OT_bookmark_delete";
/* api callbacks */
ot->exec = bookmark_delete_exec;
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index d6f644ab330..f4161c7da1c 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -115,12 +115,13 @@ static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory cat
/* create list item */
but = uiDefIconTextButS(block, LISTROW, 0, icon, dir, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, nr, 0, i, 0, 0, entry);
uiButSetFunc(but, file_panel_cb, entry, NULL);
+ uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
uiButSetFlag(but, UI_ICON_LEFT | UI_TEXT_LEFT);
/* create delete button */
if (allow_delete && fsmenu_can_save(fsmenu, category, i)) {
uiBlockSetEmboss(block, UI_EMBOSSN);
- uiItemIntO(layout, "", ICON_X, "FILE_OT_delete_bookmark", "index", i);
+ uiItemIntO(layout, "", ICON_X, "FILE_OT_bookmark_delete", "index", i);
uiBlockSetEmboss(block, UI_EMBOSS);
}
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 8f25ac38963..19a6296993d 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -152,17 +152,27 @@ static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX];
/* ******************* SORT ******************* */
+static bool compare_is_directory(const struct direntry *entry)
+{
+ /* for library browse .blend files may be treated as directories, but
+ * for sorting purposes they should be considered regular files */
+ if (S_ISDIR(entry->type))
+ return !(entry->flags & (BLENDERFILE | BLENDERFILE_BACKUP));
+
+ return false;
+}
+
static int compare_name(const void *a1, const void *a2)
{
const struct direntry *entry1 = a1, *entry2 = a2;
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
@@ -188,11 +198,11 @@ static int compare_date(const void *a1, const void *a2)
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
@@ -221,11 +231,11 @@ static int compare_size(const void *a1, const void *a2)
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
@@ -262,11 +272,11 @@ static int compare_extension(const void *a1, const void *a2)
/* type is equal to stat.st_mode */
- if (S_ISDIR(entry1->type)) {
- if (S_ISDIR(entry2->type) == 0) return (-1);
+ if (compare_is_directory(entry1)) {
+ if (compare_is_directory(entry2) == 0) return (-1);
}
else {
- if (S_ISDIR(entry2->type)) return (1);
+ if (compare_is_directory(entry2)) return (1);
}
if (S_ISREG(entry1->type)) {
if (S_ISREG(entry2->type) == 0) return (-1);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 85e4d255603..9d762c80405 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -59,6 +59,7 @@
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
+#include "BLI_fnmatch.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -81,12 +82,6 @@
#include "file_intern.h"
#include "filelist.h"
-#if defined WIN32 && !defined _LIBC
-# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
-#else
-# include <fnmatch.h>
-#endif
-
FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
{
if (!sfile->params) {
@@ -115,6 +110,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
/* set the parameters from the operator, if it exists */
if (op) {
+ PropertyRNA *prop;
const short is_files = (RNA_struct_find_property(op->ptr, "files") != NULL);
const short is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != NULL);
const short is_filename = (RNA_struct_find_property(op->ptr, "filename") != NULL);
@@ -163,30 +159,30 @@ short ED_fileselect_set_params(SpaceFile *sfile)
}
params->filter = 0;
- if (RNA_struct_find_property(op->ptr, "filter_blender"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_backup"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_backup") ? BLENDERFILE_BACKUP : 0;
- if (RNA_struct_find_property(op->ptr, "filter_image"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_movie"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_movie") ? MOVIEFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_python"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_python") ? PYSCRIPTFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_font"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_font") ? FTFONTFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_sound"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_sound") ? SOUNDFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_text"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_text") ? TEXTFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_folder"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_folder") ? FOLDERFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_btx"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_btx") ? BTXFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_collada"))
- params->filter |= RNA_boolean_get(op->ptr, "filter_collada") ? COLLADAFILE : 0;
- if (RNA_struct_find_property(op->ptr, "filter_glob")) {
- RNA_string_get(op->ptr, "filter_glob", params->filter_glob);
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_blender")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_backup")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE_BACKUP : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_image")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? IMAGEFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_movie")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? MOVIEFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_python")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? PYSCRIPTFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_font")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FTFONTFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_sound")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? SOUNDFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_text")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? TEXTFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_folder")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FOLDERFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_btx")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BTXFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? COLLADAFILE : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
+ RNA_property_string_get(op->ptr, prop, params->filter_glob);
params->filter |= (OPERATORFILE | FOLDERFILE);
}
else {
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 6f3d0367574..1a8565a58b1 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -148,7 +148,6 @@ static void file_free(SpaceLink *sl)
static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
- //printf("file_init\n");
/* refresh system directory list */
fsmenu_refresh_system_category(fsmenu_get());
@@ -313,7 +312,6 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
/* draw entirely, view changes should be handled here */
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
- FileLayout *layout = NULL;
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
@@ -323,15 +321,14 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
if (!sfile->files || filelist_empty(sfile->files))
file_refresh(C, NULL);
- layout = ED_fileselect_get_layout(sfile, ar);
-
/* clear and setup matrix */
UI_GetThemeColor3fv(TH_BACK, col);
glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/* Allow dynamically sliders to be set, saves notifiers etc. */
- if (layout && (layout->flag == FILE_LAYOUT_VER)) {
+
+ if (params->display == FILE_IMGDISPLAY) {
v2d->scroll = V2D_SCROLL_RIGHT;
v2d->keepofs &= ~V2D_LOCKOFS_Y;
v2d->keepofs |= V2D_LOCKOFS_X;
@@ -390,7 +387,7 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_refresh);
WM_operatortype_append(FILE_OT_bookmark_toggle);
WM_operatortype_append(FILE_OT_bookmark_add);
- WM_operatortype_append(FILE_OT_delete_bookmark);
+ WM_operatortype_append(FILE_OT_bookmark_delete);
WM_operatortype_append(FILE_OT_reset_recent);
WM_operatortype_append(FILE_OT_hidedot);
WM_operatortype_append(FILE_OT_filenum);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 7610f7a9192..23c39a5e99a 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -951,7 +951,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
/* 1) draw curve line */
{
/* set color/drawing style for curve itself */
- if (((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED)) {
+ if (BKE_fcurve_is_protected(fcu)) {
/* protected curves (non editable) are drawn with dotted lines */
setlinestyle(2);
}
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 9d22d6fcc95..274c06bf871 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -214,7 +214,8 @@ void GRAPH_OT_previewrange_set(wmOperatorType *ot)
/* ****************** View-All Operator ****************** */
-static int graphkeys_viewall(bContext *C, const short do_sel_only, const short include_handles)
+static int graphkeys_viewall(bContext *C, const short do_sel_only, const short include_handles,
+ const int smooth_viewtx)
{
bAnimContext ac;
rctf cur_new;
@@ -231,7 +232,7 @@ static int graphkeys_viewall(bContext *C, const short do_sel_only, const short i
BLI_rctf_scale(&cur_new, 1.1f);
- UI_view2d_smooth_view(C, ac.ar, &cur_new);
+ UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -240,18 +241,20 @@ static int graphkeys_viewall(bContext *C, const short do_sel_only, const short i
static int graphkeys_viewall_exec(bContext *C, wmOperator *op)
{
- short include_handles = RNA_boolean_get(op->ptr, "include_handles");
+ const short include_handles = RNA_boolean_get(op->ptr, "include_handles");
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* whole range */
- return graphkeys_viewall(C, FALSE, include_handles);
+ return graphkeys_viewall(C, false, include_handles, smooth_viewtx);
}
static int graphkeys_view_selected_exec(bContext *C, wmOperator *op)
{
- short include_handles = RNA_boolean_get(op->ptr, "include_handles");
+ const short include_handles = RNA_boolean_get(op->ptr, "include_handles");
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* only selected */
- return graphkeys_viewall(C, TRUE, include_handles);
+ return graphkeys_viewall(C, true, include_handles, smooth_viewtx);
}
void GRAPH_OT_view_all(wmOperatorType *ot)
@@ -882,8 +885,12 @@ static void delete_graph_keys(bAnimContext *ac)
delete_fcurve_keys(fcu);
/* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
+ if ((fcu->totvert == 0) &&
+ (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
+ (fcu->driver == NULL))
+ {
ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
+ }
}
/* free filtered list */
@@ -1676,7 +1683,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
/* FIXME: there are more complicated methods that will be needed to fix more cases than just some */
for (f = 0; f < 3; f++) {
FCurve *fcu = euf->fcurves[f];
- BezTriple *bezt, *prev = NULL;
+ BezTriple *bezt, *prev;
unsigned int i;
/* skip if not enough vets to do a decent analysis of... */
@@ -1684,29 +1691,19 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
continue;
/* prev follows bezt, bezt = "current" point to be fixed */
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, prev = bezt, bezt++) {
- /* our method depends on determining a "difference" from the previous vert */
- if (prev == NULL)
- continue;
+ /* our method depends on determining a "difference" from the previous vert */
+ for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) {
+ const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f;
/* > 180 degree flip? */
- if (fabs(prev->vec[1][1] - bezt->vec[1][1]) >= M_PI) {
+ if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
/* 360 degrees to add/subtract frame value until difference is acceptably small that there's no more flip */
- const float fac = 2.0f * (float)M_PI;
+ const float fac = sign * 2.0f * (float)M_PI;
- if (prev->vec[1][1] > bezt->vec[1][1]) {
- while (fabsf(bezt->vec[1][1] - prev->vec[1][1]) >= (float)M_PI) {
- bezt->vec[0][1] += fac;
- bezt->vec[1][1] += fac;
- bezt->vec[2][1] += fac;
- }
- }
- else { /* if (prev->vec[1][1] < bezt->vec[1][1]) */
- while (fabsf(bezt->vec[1][1] - prev->vec[1][1]) >= (float)M_PI) {
- bezt->vec[0][1] -= fac;
- bezt->vec[1][1] -= fac;
- bezt->vec[2][1] -= fac;
- }
+ while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
+ bezt->vec[0][1] += fac;
+ bezt->vec[1][1] += fac;
+ bezt->vec[2][1] += fac;
}
}
}
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index cbec3072c44..d87bd9a5077 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -149,17 +149,37 @@ static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short d
static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ bAnimListElem *ale_active = NULL;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
-
+
+ /* find active F-Curve, and preserve this for later
+ * or else it becomes annoying with the current active
+ * curve keeps fading out even while you're editing it
+ */
+ ale_active = get_active_fcurve_channel(&ac);
+
/* 'standard' behavior - check if selected, then apply relevant selection */
if (RNA_boolean_get(op->ptr, "invert"))
deselect_graph_keys(&ac, 0, SELECT_INVERT, TRUE);
else
deselect_graph_keys(&ac, 1, SELECT_ADD, TRUE);
+ /* restore active F-Curve... */
+ if (ale_active) {
+ FCurve *fcu = (FCurve *)ale_active->data;
+
+ /* all others should not be disabled, so we should be able to just set this directly...
+ * - selection needs to be set too, or else this won't work...
+ */
+ fcu->flag |= (FCURVE_SELECTED | FCURVE_ACTIVE);
+
+ MEM_freeN(ale_active);
+ ale_active = NULL;
+ }
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -1049,10 +1069,7 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
/* if list only has 1 item, remove it from the list and return */
if (matches->first == matches->last) {
/* need to remove from the list, otherwise it gets freed and then we can't return it */
- nvi = matches->first;
- BLI_remlink(matches, nvi);
-
- return nvi;
+ return BLI_pophead(matches);
}
/* try to find the first selected F-Curve vert, then take the one after it */
@@ -1075,9 +1092,7 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches)
/* if we're still here, this means that we failed to find anything appropriate in the first pass,
* so just take the first item now...
*/
- nvi = matches->first;
- BLI_remlink(matches, nvi);
- return nvi;
+ return BLI_pophead(matches);
}
/* Find the nearest vertices (either a handle or the keyframe) that are nearest to the mouse cursor (in area coordinates)
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 23c85699b00..89e57955339 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -268,8 +268,6 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
else
rgba[3] = linearcol[3];
- (void)color_manage;
-
if (use_default_view)
IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
else
@@ -360,14 +358,8 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
dx += BLF_width(blf_mono_font, str);
}
else if (channels >= 3) {
- if (fp) {
- rgb_to_hsv(fp[0], fp[1], fp[2], &hue, &sat, &val);
- rgb_to_yuv(fp[0], fp[1], fp[2], &lum, &u, &v);
- }
- else if (cp) {
- rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &hue, &sat, &val);
- rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &lum, &u, &v);
- }
+ rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
+ rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v);
BLI_snprintf(str, sizeof(str), "H:%-.4f", hue);
BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 2da3f3adb67..710d5c8cd81 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -245,7 +245,7 @@ static void image_view_pan_init(bContext *C, wmOperator *op, const wmEvent *even
ViewPanData *vpd;
op->customdata = vpd = MEM_callocN(sizeof(ViewPanData), "ImageViewPanData");
- WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
vpd->x = event->x;
vpd->y = event->y;
@@ -267,7 +267,7 @@ static void image_view_pan_exit(bContext *C, wmOperator *op, int cancel)
ED_region_tag_redraw(CTX_wm_region(C));
}
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(op->customdata);
}
@@ -391,7 +391,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve
ViewZoomData *vpd;
op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData");
- WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
+ WM_cursor_modal_set(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR);
vpd->origx = event->x;
vpd->origy = event->y;
@@ -425,7 +425,7 @@ static void image_view_zoom_exit(bContext *C, wmOperator *op, int cancel)
if (vpd->timer)
WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer);
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(op->customdata);
}
@@ -646,12 +646,13 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
* Default behavior is to reset the position of the image and set the zoom to 1
* If the image will not fit within the window rectangle, the zoom is adjusted */
-static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int image_view_all_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima;
ARegion *ar;
float aspx, aspy, zoomx, zoomy, w, h;
int width, height;
+ int fit_view = RNA_boolean_get(op->ptr, "fit_view");
/* retrieve state */
sima = CTX_wm_space_image(C);
@@ -667,14 +668,25 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op))
width = BLI_rcti_size_x(&ar->winrct) + 1;
height = BLI_rcti_size_y(&ar->winrct) + 1;
- if ((w >= width || h >= height) && (width > 0 && height > 0)) {
- /* find the zoom value that will fit the image in the image space */
- zoomx = width / w;
- zoomy = height / h;
- sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL);
+ if (fit_view) {
+ const int margin = 5; /* margin from border */
+
+ zoomx = (float) width / (w + 2 * margin);
+ zoomy = (float) height / (h + 2 * margin);
+
+ sima_zoom_set(sima, ar, min_ff(zoomx, zoomy), NULL);
+ }
+ else {
+ if ((w >= width || h >= height) && (width > 0 && height > 0)) {
+ zoomx = (float) width / w;
+ zoomy = (float) height / h;
+
+ /* find the zoom value that will fit the image in the image space */
+ sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL);
+ }
+ else
+ sima_zoom_set(sima, ar, 1.0f, NULL);
}
- else
- sima_zoom_set(sima, ar, 1.0f, NULL);
sima->xof = sima->yof = 0.0f;
@@ -685,6 +697,8 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op))
void IMAGE_OT_view_all(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "View All";
ot->idname = "IMAGE_OT_view_all";
@@ -693,6 +707,10 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_view_all_exec;
ot->poll = space_image_main_area_poll;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/********************** view selected operator *********************/
@@ -1318,7 +1336,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path"));
const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy"));
- const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
+ const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
ImageFormatData *imf = &simopts->im_format;
short ok = FALSE;
@@ -1344,7 +1362,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
}
}
- colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, TRUE, &imf->view_settings, &imf->display_settings, imf);
+ colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
Scene *scene = CTX_data_scene(C);
@@ -1786,6 +1804,8 @@ static int image_new_exec(bContext *C, wmOperator *op)
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+ WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+
return OPERATOR_FINISHED;
}
@@ -2397,6 +2417,9 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
hist->co[1][0] = x2f;
hist->co[1][1] = y2f;
+ /* enable line drawing */
+ hist->flag |= HISTO_FLAG_SAMPLELINE;
+
BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings);
/* reset y zoom */
@@ -2539,7 +2562,7 @@ static void image_record_composite_exit(bContext *C, wmOperator *op)
scene->r.cfra = rcd->old_cfra;
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
if (rcd->timer)
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rcd->timer);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index c0ef59e9e25..5a8292abcab 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -277,6 +277,10 @@ static void image_keymap(struct wmKeyConfig *keyconf)
keymap = WM_keymap_find(keyconf, "Image", SPACE_IMAGE, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+
+ kmi = WM_keymap_add_item(keymap, "IMAGE_OT_view_all", FKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "fit_view", TRUE);
+
WM_keymap_add_item(keymap, "IMAGE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
@@ -670,7 +674,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
}
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
- draw_image_cursor(sima, ar);
+ draw_image_cursor(ar, sima->cursor);
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -719,7 +723,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
ED_mask_draw_frames(mask, ar, CFRA, mask->sfra, mask->efra);
- draw_image_cursor(sima, ar);
+ draw_image_cursor(ar, sima->cursor);
}
/* scrollers? */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 98c9c8d15fe..9686c6dfc29 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -115,8 +115,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
{
int totv = 0, totf = 0, tottri = 0;
- if (ob->disp.first)
- BKE_displist_count(&ob->disp, &totv, &totf, &tottri);
+ if (ob->curve_cache && ob->curve_cache->disp.first)
+ BKE_displist_count(&ob->curve_cache->disp, &totv, &totf, &tottri);
totv *= totob;
totf *= totob;
@@ -194,9 +194,9 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
a = nu->pntsu;
while (a--) {
stats->totvert += 3;
- if (bezt->f1) stats->totvertsel++;
- if (bezt->f2) stats->totvertsel++;
- if (bezt->f3) stats->totvertsel++;
+ if (bezt->f1 & SELECT) stats->totvertsel++;
+ if (bezt->f2 & SELECT) stats->totvertsel++;
+ if (bezt->f3 & SELECT) stats->totvertsel++;
bezt++;
}
}
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index e53cbdd04af..d4d45af6431 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -57,6 +57,7 @@ static void console_font_begin(TextViewContext *sc)
typedef struct ConsoleDrawContext {
int cwidth;
int lheight;
+ int lofs; /* text vertical offset */
int console_width; /* number of characters that fit into the width of the console (fixed width) */
int winx;
int ymin, ymax;
@@ -122,7 +123,6 @@ static int console_wrap_offsets(const char *str, int len, int width, int *lines,
static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str_len,
const unsigned char fg[3], const unsigned char bg[3], const unsigned char bg_sel[4])
{
- int rct_ofs = cdc->lheight / 4;
int tot_lines; /* total number of lines for wrapping */
int *offsets; /* offsets of line beginnings for wrapping */
int y_next;
@@ -186,13 +186,13 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
if (bg) {
glColor3ubv(bg);
- glRecti(0, cdc->xy[1] - rct_ofs, cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines)) + rct_ofs);
+ glRecti(0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines)));
}
glColor3ubv(fg);
/* last part needs no clipping */
- BLF_position(mono, cdc->xy[0], cdc->xy[1], 0);
+ BLF_position(mono, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
BLF_draw_mono(mono, s, len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
@@ -208,7 +208,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
len = offsets[i] - offsets[i - 1];
s = str + offsets[i - 1];
- BLF_position(mono, cdc->xy[0], cdc->xy[1], 0);
+ BLF_position(mono, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
BLF_draw_mono(mono, s, len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
@@ -234,12 +234,12 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
if (bg) {
glColor3ubv(bg);
- glRecti(0, cdc->xy[1] - rct_ofs, cdc->winx, cdc->xy[1] + cdc->lheight - rct_ofs);
+ glRecti(0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight);
}
glColor3ubv(fg);
- BLF_position(mono, cdc->xy[0], cdc->xy[1], 0);
+ BLF_position(mono, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
BLF_draw_mono(mono, str, str_len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
@@ -291,6 +291,7 @@ int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mous
cdc.cwidth = (int)BLF_fixed_width(mono);
assert(cdc.cwidth > 0);
cdc.lheight = tvc->lheight;
+ cdc.lofs = -BLF_descender(mono);
/* note, scroll bar must be already subtracted () */
cdc.console_width = (tvc->winx - (CONSOLE_DRAW_MARGIN * 2) ) / cdc.cwidth;
CLAMP(cdc.console_width, 1, INT_MAX); /* avoid divide by zero on small windows */
diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h
index 653c9b83a50..2f9e518ed47 100644
--- a/source/blender/editors/space_info/textview.h
+++ b/source/blender/editors/space_info/textview.h
@@ -24,6 +24,8 @@
* \ingroup spinfo
*/
+#ifndef __TEXTVIEW_H__
+#define __TEXTVIEW_H__
typedef struct TextViewContext {
int lheight;
@@ -59,3 +61,5 @@ int textview_draw(struct TextViewContext *tvc, const int draw, int mval[2], void
#define TVC_LINE_FG (1<<0)
#define TVC_LINE_BG (1<<1)
+
+#endif /* __TEXTVIEW_H__ */
diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c
index fadf4c0b113..fac564f33fb 100644
--- a/source/blender/editors/space_logic/logic_ops.c
+++ b/source/blender/editors/space_logic/logic_ops.c
@@ -739,16 +739,17 @@ static void LOGIC_OT_texface_convert(wmOperatorType *ot)
/* ************************ view ********************* */
-static int logic_view_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int logic_view_all_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
rctf cur_new = ar->v2d.tot;
float aspect = BLI_rctf_size_y(&ar->v2d.cur) / BLI_rctf_size_x(&ar->v2d.cur);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* force the view2d code to zoom to width, not height */
cur_new.ymin = cur_new.ymax - BLI_rctf_size_x(&cur_new) * aspect;
- UI_view2d_smooth_view(C, ar, &cur_new);
+ UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 2957edd941b..2c89d6f6448 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -427,8 +427,6 @@ static const char *sensor_name(int type)
switch (type) {
case SENS_ALWAYS:
return "Always";
- case SENS_TOUCH:
- return "Touch";
case SENS_NEAR:
return "Near";
case SENS_KEYBOARD:
@@ -1233,11 +1231,6 @@ static void draw_sensor_ray(uiLayout *layout, PointerRNA *ptr, bContext *C)
uiItemR(row, ptr, "use_x_ray", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
}
-static void draw_sensor_touch(uiLayout *layout, PointerRNA *ptr)
-{
- uiItemR(layout, ptr, "material", 0, NULL, ICON_NONE);
-}
-
static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
{
uiLayout *box;
@@ -1292,9 +1285,6 @@ static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C)
case SENS_RAY:
draw_sensor_ray(box, ptr, C);
break;
- case SENS_TOUCH:
- draw_sensor_touch(box, ptr);
- break;
}
}
@@ -1465,6 +1455,7 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
row = uiLayoutRow(layout, FALSE);
uiItemR(row, ptr, "layer", 0, NULL, ICON_NONE);
uiItemR(row, ptr, "layer_weight", 0, NULL, ICON_NONE);
+ uiItemR(row, ptr, "blend_mode", 0, "", ICON_NONE);
uiItemPointerR(layout, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index cf3c0454e6b..f562212f1e2 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -571,7 +571,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
*/
#if 0
/* body */
- uiSetRoundBox(15);
+ uiSetRoundBox(UI_CNR_ALL);
UI_ThemeColor4(TH_NODE);
glEnable(GL_BLEND);
uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
@@ -709,6 +709,8 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin
{
uiLayout *row;
+ uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
uiItemL(layout, IFACE_("Location:"), ICON_NONE);
row = uiLayoutRow(layout, TRUE);
uiItemR(row, ptr, "translation", 0, "", ICON_NONE);
@@ -737,7 +739,7 @@ static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), Po
static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiItemR(layout, ptr, "convert_from", 0, "", ICON_NONE);
uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE);
}
@@ -809,9 +811,13 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
}
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
+{
+ uiItemR(layout, ptr, "sky_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE);
uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE);
+
+ if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW)
+ uiItemR(layout, ptr, "ground_albedo", 0, NULL, ICON_NONE);
}
static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -907,11 +913,29 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
}
+static void node_shader_buts_subsurface(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ /* SSS does not work on GPU yet */
+ PointerRNA scene = CTX_data_pointer_get(C, "scene");
+ if (scene.data) {
+ PointerRNA cscene = RNA_pointer_get(&scene, "cycles");
+ if (cscene.data && RNA_enum_get(&cscene, "device") == 1)
+ uiItemL(layout, IFACE_("SSS not supported on GPU"), ICON_ERROR);
+ }
+
+ uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
}
+static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row;
@@ -1039,9 +1063,15 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_BSDF_REFRACTION:
ntype->uifunc = node_shader_buts_glossy;
break;
+ case SH_NODE_SUBSURFACE_SCATTERING:
+ ntype->uifunc = node_shader_buts_subsurface;
+ break;
case SH_NODE_BSDF_TOON:
ntype->uifunc = node_shader_buts_toon;
break;
+ case SH_NODE_BSDF_HAIR:
+ ntype->uifunc = node_shader_buts_hair;
+ break;
case SH_NODE_SCRIPT:
ntype->uifunc = node_shader_buts_script;
ntype->uifuncbut = node_shader_buts_script_details;
@@ -1620,12 +1650,14 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
active_index = RNA_int_get(ptr, "active_input_index");
/* using different collection properties if multilayer format is enabled */
if (multilayer) {
- uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index",
+ 0, 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
active_index, &active_input_ptr);
}
else {
- uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index",
+ 0, 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
active_index, &active_input_ptr);
}
@@ -2225,6 +2257,39 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
}
}
+static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+
+ uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
+
+ if (node->id) {
+ MovieClip *clip = (MovieClip *) node->id;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
+ uiLayout *col;
+ PointerRNA tracking_ptr;
+ NodeTrackPosData *data = node->storage;
+
+ RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
+
+ col = uiLayoutColumn(layout, FALSE);
+ uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
+
+ object = BKE_tracking_object_get_named(tracking, data->tracking_object);
+ if (object) {
+ PointerRNA object_ptr;
+
+ RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
+
+ uiItemPointerR(col, ptr, "plane_track_name", &object_ptr, "plane_tracks", "", ICON_ANIM_DATA);
+ }
+ else {
+ uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
+ }
+ }
+}
+
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
@@ -2444,6 +2509,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_TRACKPOS:
ntype->uifunc = node_composit_buts_trackpos;
break;
+ case CMP_NODE_PLANETRACKDEFORM:
+ ntype->uifunc = node_composit_buts_planetrackdeform;
+ break;
}
}
@@ -3025,7 +3093,16 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
{
float dist, vec[4][2];
float deltax, deltay;
+ float cursor[2] = {0.0f, 0.0f};
int toreroute, fromreroute;
+
+ /* this function can be called with snode null (via cut_links_intersect) */
+ /* XXX map snode->cursor back to view space */
+ if (snode) {
+ cursor[0] = snode->cursor[0] * UI_DPI_FAC;
+ cursor[1] = snode->cursor[1] * UI_DPI_FAC;
+ }
+
/* in v0 and v3 we put begin/end points */
if (link->fromsock) {
vec[0][0] = link->fromsock->locx;
@@ -3034,7 +3111,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
}
else {
if (snode == NULL) return 0;
- copy_v2_v2(vec[0], snode->cursor);
+ copy_v2_v2(vec[0], cursor);
fromreroute = 0;
}
if (link->tosock) {
@@ -3044,7 +3121,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
}
else {
if (snode == NULL) return 0;
- copy_v2_v2(vec[3], snode->cursor);
+ copy_v2_v2(vec[3], cursor);
toreroute = 0;
}
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index c9618daa7c5..00769975893 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -84,10 +84,6 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
node->locy = locy + 60.0f; /* arbitrary... so its visible, (0,0) is top of node */
nodeSetSelected(node, TRUE);
- /* node location is mapped */
- locx /= UI_DPI_FAC;
- locy /= UI_DPI_FAC;
-
node->locx = locx;
node->locy = locy + 60.0f;
@@ -215,7 +211,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
int i = 0;
/* Get the cut path */
- RNA_BEGIN(op->ptr, itemptr, "path")
+ RNA_BEGIN (op->ptr, itemptr, "path")
{
float loc[2];
@@ -417,9 +413,8 @@ static int node_add_mask_poll(bContext *C)
return ED_operator_node_editable(C) && snode->nodetree->type == NTREE_COMPOSIT;
}
-static int node_add_mask_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int node_add_mask_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
ID *mask = NULL;
@@ -435,9 +430,6 @@ static int node_add_mask_invoke(bContext *C, wmOperator *op, const wmEvent *even
ED_preview_kill_jobs(C);
- /* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
- &snode->cursor[0], &snode->cursor[1]);
node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]);
if (!node) {
@@ -462,7 +454,7 @@ void NODE_OT_add_mask(wmOperatorType *ot)
ot->idname = "NODE_OT_add_mask";
/* callbacks */
- ot->invoke = node_add_mask_invoke;
+ ot->exec = node_add_mask_exec;
ot->poll = node_add_mask_poll;
/* flags */
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index f95e895bef2..53b373e728e 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -145,13 +145,15 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
split = uiLayoutRow(row, TRUE);
col = uiLayoutColumn(split, TRUE);
uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
- uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", 0, 0, 0);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input",
+ 0, 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_IN);
col = uiLayoutColumn(split, TRUE);
uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
- uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", 0, 0, 0);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output",
+ 0, 0, 0, 0);
opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_OUT);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index dce04bb8c42..b991a2c3b5f 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -923,10 +923,13 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
}
/* preview */
- if (node->flag & NODE_PREVIEW) {
- bNodePreview *preview = previews ? BKE_node_instance_hash_lookup(previews, key) : NULL;
- if (preview && preview->rect && !BLI_rctf_is_empty(&node->prvr))
- node_draw_preview(preview, &node->prvr);
+ if (node->flag & NODE_PREVIEW && previews) {
+ bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
+ if (preview && (preview->xsize && preview->ysize)) {
+ if (preview->rect && !BLI_rctf_is_empty(&node->prvr)) {
+ node_draw_preview(preview, &node->prvr);
+ }
+ }
}
UI_ThemeClearColor(color_id);
@@ -1075,31 +1078,31 @@ int node_get_resize_cursor(int directions)
return CURSOR_EDIT;
}
-void node_set_cursor(wmWindow *win, SpaceNode *snode)
+void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
{
bNodeTree *ntree = snode->edittree;
bNode *node;
bNodeSocket *sock;
- int cursor = CURSOR_STD;
+ int wmcursor = CURSOR_STD;
if (ntree) {
- if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN | SOCK_OUT)) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) {
/* pass */
}
else {
/* check nodes front to back */
for (node = ntree->nodes.last; node; node = node->prev) {
- if (BLI_rctf_isect_pt(&node->totr, snode->cursor[0], snode->cursor[1]))
+ if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1]))
break; /* first hit on node stops */
}
if (node) {
- int dir = node->typeinfo->resize_area_func(node, snode->cursor[0], snode->cursor[1]);
- cursor = node_get_resize_cursor(dir);
+ int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]);
+ wmcursor = node_get_resize_cursor(dir);
}
}
}
- WM_cursor_set(win, cursor);
+ WM_cursor_set(win, wmcursor);
}
void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
@@ -1238,7 +1241,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
/* shade node groups to separate them visually */
UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
glEnable(GL_BLEND);
- uiSetRoundBox(0);
+ uiSetRoundBox(UI_CNR_NONE);
uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
glDisable(GL_BLEND);
@@ -1251,6 +1254,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
void drawnodespace(const bContext *C, ARegion *ar)
{
+ wmWindow *win = CTX_wm_window(C);
View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
View2D *v2d = &ar->v2d;
@@ -1259,7 +1263,13 @@ void drawnodespace(const bContext *C, ARegion *ar)
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(v2d);
-
+
+ /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */
+ UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin,
+ &snode->cursor[0], &snode->cursor[1]);
+ snode->cursor[0] /= UI_DPI_FAC;
+ snode->cursor[1] /= UI_DPI_FAC;
+
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
/* only set once */
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index b7e9cb0268f..bc0a518b1b0 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -854,14 +854,14 @@ static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(
nsw->oldminiwidth = node->miniwidth;
nsw->directions = dir;
- WM_cursor_modal(CTX_wm_window(C), node_get_resize_cursor(dir));
+ WM_cursor_modal_set(CTX_wm_window(C), node_get_resize_cursor(dir));
/* add modal handler */
WM_event_add_modal_handler(C, op);
}
static void node_resize_exit(bContext *C, wmOperator *op, int UNUSED(cancel))
{
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(op->customdata);
op->customdata = NULL;
@@ -1056,7 +1056,7 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
/* checks snode->mouse position, and returns found node/socket */
/* type is SOCK_IN and/or SOCK_OUT */
-int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out)
+int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out)
{
bNode *node;
bNodeSocket *sock;
@@ -1068,10 +1068,10 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
/* check if we click in a socket */
for (node = snode->edittree->nodes.first; node; node = node->next) {
- rect.xmin = snode->cursor[0] - (NODE_SOCKSIZE + 4);
- rect.ymin = snode->cursor[1] - (NODE_SOCKSIZE + 4);
- rect.xmax = snode->cursor[0] + (NODE_SOCKSIZE + 4);
- rect.ymax = snode->cursor[1] + (NODE_SOCKSIZE + 4);
+ rect.xmin = cursor[0] - (NODE_SOCKSIZE + 4);
+ rect.ymin = cursor[1] - (NODE_SOCKSIZE + 4);
+ rect.xmax = cursor[0] + (NODE_SOCKSIZE + 4);
+ rect.ymax = cursor[1] + (NODE_SOCKSIZE + 4);
if (!(node->flag & NODE_HIDDEN)) {
/* extra padding inside and out - allow dragging on the text areas too */
@@ -1731,7 +1731,7 @@ static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
node = nodeGetActive(snode->edittree);
}
- if (!node)
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE)
return OPERATOR_CANCELLED;
RNA_string_get(op->ptr, "file_path", file_path);
@@ -1777,7 +1777,7 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U
node = nodeGetActive(snode->edittree);
}
- if (!node)
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE)
return OPERATOR_CANCELLED;
if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
@@ -1819,7 +1819,7 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
else if (snode && snode->edittree)
node = nodeGetActive(snode->edittree);
- if (!node)
+ if (!node || node->type != CMP_NODE_OUTPUT_FILE)
return OPERATOR_CANCELLED;
nimf = node->storage;
@@ -2087,17 +2087,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
-
- /* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
-
- return node_clipboard_paste_exec(C, op);
-}
-
void NODE_OT_clipboard_paste(wmOperatorType *ot)
{
/* identifiers */
@@ -2107,7 +2096,6 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
/* api callbacks */
ot->exec = node_clipboard_paste_exec;
- ot->invoke = node_clipboard_paste_invoke;
ot->poll = ED_operator_node_editable;
/* flags */
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 1a2e90e5522..176b81f9503 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -84,7 +84,7 @@ void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct Spa
struct bNodeTree *ntree, bNodeInstanceKey parent_key);
void drawnodespace(const bContext *C, ARegion *ar);
-void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode);
+void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]);
/* DPI scaled coords */
void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry);
void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -122,13 +122,15 @@ void NODE_OT_select_same_type_step(struct wmOperatorType *ot);
void NODE_OT_find_node(struct wmOperatorType *ot);
/* node_view.c */
-int space_node_view_flag(struct bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag);
+int space_node_view_flag(struct bContext *C, SpaceNode *snode, ARegion *ar,
+ const int node_flag, const int smooth_viewtx);
void NODE_OT_view_all(struct wmOperatorType *ot);
void NODE_OT_view_selected(struct wmOperatorType *ot);
void NODE_OT_backimage_move(struct wmOperatorType *ot);
void NODE_OT_backimage_zoom(struct wmOperatorType *ot);
+void NODE_OT_backimage_fit(struct wmOperatorType *ot);
void NODE_OT_backimage_sample(struct wmOperatorType *ot);
/* drawnode.c */
@@ -182,7 +184,7 @@ int composite_node_editable(struct bContext *C);
int node_has_hidden_sockets(bNode *node);
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
int node_render_changed_exec(bContext *, struct wmOperator *);
-int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, int in_out);
+int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, float cursor[2], int in_out);
void NODE_OT_duplicate(struct wmOperatorType *ot);
void NODE_OT_delete(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 566bb1600cc..f0d3deb24df 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -98,6 +98,7 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_backimage_move);
WM_operatortype_append(NODE_OT_backimage_zoom);
+ WM_operatortype_append(NODE_OT_backimage_fit);
WM_operatortype_append(NODE_OT_backimage_sample);
WM_operatortype_append(NODE_OT_add_file);
@@ -249,6 +250,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_float_set(kmi->ptr, "factor", 0.83333f);
kmi = WM_keymap_add_item(keymap, "NODE_OT_backimage_zoom", VKEY, KM_PRESS, KM_ALT, 0);
RNA_float_set(kmi->ptr, "factor", 1.2f);
+ WM_keymap_add_item(keymap, "NODE_OT_backimage_fit", HOMEKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "NODE_OT_backimage_sample", ACTIONMOUSE, KM_PRESS, KM_ALT, 0);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 244b222811e..4b5cc9e42b6 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -443,18 +443,19 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
bNodeSocket *tsock = NULL;
bNodeLink *link;
LinkData *linkdata;
+ float cursor[2];
int in_out;
in_out = nldrag->in_out;
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
- &snode->cursor[0], &snode->cursor[1]);
+ &cursor[0], &cursor[1]);
switch (event->type) {
case MOUSEMOVE:
if (in_out == SOCK_OUT) {
- if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
+ if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
@@ -480,7 +481,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
else {
- if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
+ if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
@@ -550,7 +551,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* return 1 when socket clicked */
-static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
+static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], int detach)
{
bNode *node;
bNodeSocket *sock;
@@ -560,7 +561,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
int num_links;
/* output indicated? */
- if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
num_links = nodeCountSocketLinks(snode->edittree, sock);
@@ -596,7 +597,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
}
}
/* or an input? */
- else if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
+ else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
num_links = nodeCountSocketLinks(snode->edittree, sock);
@@ -644,14 +645,16 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
bNodeLinkDrag *nldrag;
+ float cursor[2];
+
int detach = RNA_boolean_get(op->ptr, "detach");
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
- &snode->cursor[0], &snode->cursor[1]);
+ &cursor[0], &cursor[1]);
ED_preview_kill_jobs(C);
- nldrag = node_link_init(snode, detach);
+ nldrag = node_link_init(snode, cursor, detach);
if (nldrag) {
op->customdata = nldrag;
@@ -762,7 +765,7 @@ static int cut_links_exec(bContext *C, wmOperator *op)
float mcoords[256][2];
int i = 0;
- RNA_BEGIN(op->ptr, itemptr, "path")
+ RNA_BEGIN (op->ptr, itemptr, "path")
{
float loc[2];
@@ -1065,18 +1068,23 @@ void NODE_OT_join(wmOperatorType *ot)
/* ****************** Attach ******************* */
-static int node_attach_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
+ ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
bNode *frame;
+ float cursor[2];
+
+ /* convert mouse coordinates to v2d space */
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
/* check nodes front to back */
for (frame = ntree->nodes.last; frame; frame = frame->prev) {
/* skip selected, those are the nodes we want to attach */
if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
continue;
- if (BLI_rctf_isect_pt(&frame->totr, snode->cursor[0], snode->cursor[1]))
+ if (BLI_rctf_isect_pt(&frame->totr, cursor[0], cursor[1]))
break;
}
if (frame) {
@@ -1116,16 +1124,6 @@ static int node_attach_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int node_attach_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- SpaceNode *snode = CTX_wm_space_node(C);
-
- /* convert mouse coordinates to v2d space */
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
-
- return node_attach_exec(C, op);
-}
void NODE_OT_attach(wmOperatorType *ot)
{
@@ -1135,7 +1133,7 @@ void NODE_OT_attach(wmOperatorType *ot)
ot->idname = "NODE_OT_attach";
/* api callbacks */
- ot->exec = node_attach_exec;
+
ot->invoke = node_attach_invoke;
ot->poll = ED_operator_node_editable;
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index e17699309ef..958a3433337 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -306,24 +306,21 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
{
bNode *node, *tnode;
bNodeSocket *sock, *tsock;
- float mx, my;
+ float cursor[2];
int selected = 0;
/* get mouse coordinates in view2d space */
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
- /* node_find_indicated_socket uses snode->mx/my */
- snode->cursor[0] = mx;
- snode->cursor[1] = my;
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
if (extend) {
/* first do socket selection, these generally overlap with nodes.
* socket selection only in extend mode.
*/
- if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
+ if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
node_socket_toggle(node, sock, 1);
selected = 1;
}
- else if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
+ else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
if (sock->flag & SELECT) {
node_socket_deselect(node, sock, 1);
}
@@ -341,7 +338,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
}
else {
/* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, mx, my);
+ node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
if (node) {
if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) {
@@ -362,7 +359,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
else { /* extend == 0 */
/* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, mx, my);
+ node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
if (node) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
@@ -834,7 +831,8 @@ static int node_select_same_type_step_exec(bContext *C, wmOperator *op)
if (active->totr.xmax < ar->v2d.cur.xmin || active->totr.xmin > ar->v2d.cur.xmax ||
active->totr.ymax < ar->v2d.cur.ymin || active->totr.ymin > ar->v2d.cur.ymax)
{
- space_node_view_flag(C, snode, CTX_wm_region(C), NODE_SELECT);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ space_node_view_flag(C, snode, ar, NODE_SELECT, smooth_viewtx);
}
}
@@ -898,7 +896,7 @@ static void node_find_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2
if (active->totr.xmax < ar->v2d.cur.xmin || active->totr.xmin > ar->v2d.cur.xmax ||
active->totr.ymax < ar->v2d.cur.ymin || active->totr.ymin > ar->v2d.cur.ymax)
{
- space_node_view_flag(C, snode, ar, NODE_SELECT);
+ space_node_view_flag(C, snode, ar, NODE_SELECT, U.smooth_viewtx);
}
}
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 9e6e1e628f6..f889a8ec97b 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -66,7 +66,8 @@
/* **************** View All Operator ************** */
-int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag)
+int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar,
+ const int node_flag, const int smooth_viewtx)
{
bNode *node;
rctf cur_new;
@@ -125,22 +126,23 @@ int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, const int n
BLI_rctf_scale(&cur_new, 1.1f);
}
- UI_view2d_smooth_view(C, ar, &cur_new);
+ UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
}
return (tot != 0);
}
-static int node_view_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_view_all_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* is this really needed? */
snode->xof = 0;
snode->yof = 0;
- if (space_node_view_flag(C, snode, ar, 0)) {
+ if (space_node_view_flag(C, snode, ar, 0, smooth_viewtx)) {
return OPERATOR_FINISHED;
}
else {
@@ -163,12 +165,13 @@ void NODE_OT_view_all(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int node_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_view_selected_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- if (space_node_view_flag(C, snode, ar, NODE_SELECT)) {
+ if (space_node_view_flag(C, snode, ar, NODE_SELECT, smooth_viewtx)) {
return OPERATOR_FINISHED;
}
else {
@@ -327,6 +330,60 @@ void NODE_OT_backimage_zoom(wmOperatorType *ot)
RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f);
}
+static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ Image *ima;
+ ImBuf *ibuf;
+
+ const float pad = 32.0f;
+
+ void *lock;
+
+ float facx, facy;
+
+ ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ return OPERATOR_CANCELLED;
+ }
+
+ facx = 1.0f * (ar->sizex - pad) / (ibuf->x * snode->zoom);
+ facy = 1.0f * (ar->sizey - pad) / (ibuf->y * snode->zoom);
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+
+ snode->zoom *= min_ff(facx, facy);
+
+ snode->xof = 0;
+ snode->yof = 0;
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_backimage_fit(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Background Image Fit";
+ ot->idname = "NODE_OT_backimage_fit";
+ ot->description = "Fit the background image to the view";
+
+ /* api callbacks */
+ ot->exec = backimage_fit_exec;
+ ot->poll = composite_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+
+}
+
/******************** sample backdrop operator ********************/
typedef struct ImageSampleInfo {
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 922912fa540..6ae8a1f94b1 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -307,10 +307,12 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
snode->zoom = 1.0f;
/* select the first tree type for valid type */
- NODE_TREE_TYPES_BEGIN(treetype)
+ NODE_TREE_TYPES_BEGIN (treetype)
+ {
strcpy(snode->tree_idname, treetype->idname);
break;
- NODE_TREE_TYPES_END
+ }
+ NODE_TREE_TYPES_END;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for node");
@@ -602,8 +604,14 @@ static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin,
&snode->cursor[0], &snode->cursor[1]);
+
+ /* here snode->cursor is used to detect the node edge for sizing */
+ node_set_cursor(win, snode, snode->cursor);
- node_set_cursor(win, snode);
+ /* XXX snode->cursor is in placing new nodes space */
+ snode->cursor[0] /= UI_DPI_FAC;
+ snode->cursor[1] /= UI_DPI_FAC;
+
}
/* Initialize main area, setting handlers. */
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 44d5672e7da..fe706ce2365 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -363,6 +363,9 @@ void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag)
if (group_restrict_flag(gr, flag)) {
for (gob = gr->gobject.first; gob; gob = gob->next) {
+ if (gob->ob->id.lib)
+ continue;
+
gob->ob->restrictflag &= ~flag;
if (flag == OB_RESTRICT_VIEW)
@@ -372,6 +375,9 @@ void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag)
}
else {
for (gob = gr->gobject.first; gob; gob = gob->next) {
+ if (gob->ob->id.lib)
+ continue;
+
/* not in editmode */
if (scene->obedit != gob->ob) {
gob->ob->restrictflag |= flag;
@@ -565,7 +571,11 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
}
if (tselem->type == 0 && te->idcode == ID_GR) {
int restrict_bool;
+ int but_flag = UI_BUT_DRAG_LOCK;
gr = (Group *)tselem->id;
+
+ if (gr->id.lib)
+ but_flag |= UI_BUT_DISABLED;
uiBlockSetEmboss(block, UI_EMBOSSN);
@@ -574,21 +584,21 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View"));
uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ uiButSetFlag(bt, but_flag);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Restrict/Allow selection in the 3D View"));
uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ uiButSetFlag(bt, but_flag);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr);
- uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
+ uiButSetFlag(bt, but_flag);
uiBlockSetEmboss(block, UI_EMBOSS);
}
@@ -1035,48 +1045,37 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo
}
-static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
+static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te)
{
uiBut *bt;
- TreeElement *te;
TreeStoreElem *tselem;
int spx, dx, len;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
-
- if (tselem->flag & TSE_TEXTBUT) {
-
- /* If we add support to rename Sequence.
- * need change this.
- */
- // prevent crash when trying to rename 'pose' entry of armature
- if (tselem->type == TSE_POSE_BASE) continue;
-
- if (tselem->type == TSE_EBONE) len = sizeof(((EditBone *) 0)->name);
- else if (tselem->type == TSE_MODIFIER) len = sizeof(((ModifierData *) 0)->name);
- else if (tselem->id && GS(tselem->id->name) == ID_LI) len = sizeof(((Library *) 0)->name);
- else len = MAX_ID_NAME - 2;
-
- dx = (int)UI_GetStringWidth(te->name);
- if (dx < 5 * UI_UNIT_X) dx = 5 * UI_UNIT_X;
- spx = te->xs + 1.8f * UI_UNIT_X;
- if (spx + dx + 0.5f * UI_UNIT_X > ar->v2d.cur.xmax) dx = ar->v2d.cur.xmax - spx - 0.5f * UI_UNIT_X;
+ tselem = TREESTORE(te);
- bt = uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, te->ys, dx + UI_UNIT_X, UI_UNIT_Y - 1, (void *)te->name,
- 1.0, (float)len, 0, 0, "");
- uiButSetRenameFunc(bt, namebutton_cb, tselem);
-
- /* returns false if button got removed */
- if (false == uiButActiveOnly(C, ar, block, bt)) {
- tselem->flag &= ~TSE_TEXTBUT;
- }
- }
- }
-
- if (TSELEM_OPEN(tselem, soops)) outliner_buttons(C, block, ar, soops, &te->subtree);
+ BLI_assert(tselem->flag & TSE_TEXTBUT);
+ /* If we add support to rename Sequence.
+ * need change this.
+ */
+
+ if (tselem->type == TSE_EBONE) len = sizeof(((EditBone *) 0)->name);
+ else if (tselem->type == TSE_MODIFIER) len = sizeof(((ModifierData *) 0)->name);
+ else if (tselem->id && GS(tselem->id->name) == ID_LI) len = sizeof(((Library *) 0)->name);
+ else len = MAX_ID_NAME - 2;
+
+ spx = te->xs + 1.8f * UI_UNIT_X;
+ dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X);
+
+ bt = uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name,
+ 1.0, (float)len, 0, 0, "");
+ uiButSetRenameFunc(bt, namebutton_cb, tselem);
+
+ /* returns false if button got removed */
+ if (false == uiButActiveOnly(C, ar, block, bt)) {
+ tselem->flag &= ~TSE_TEXTBUT;
+
+ /* bad! (notifier within draw) without this, we don't get a refesh */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
}
}
@@ -1389,6 +1388,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
case ID_LI:
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
+ case ID_LS:
+ tselem_draw_icon_uibut(&arg, ICON_BRUSH_DATA); break; /* FIXME proper icon */
}
}
}
@@ -1472,7 +1473,7 @@ static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, i
static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, int startx, int *starty)
+ TreeElement *te, int startx, int *starty, TreeElement **te_edit)
{
TreeElement *ten;
TreeStoreElem *tselem;
@@ -1485,6 +1486,10 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
int xmax = ar->v2d.cur.xmax;
unsigned char alpha = 128;
+ if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) {
+ *te_edit = te;
+ }
+
/* icons can be ui buts, we don't want it to overlap with restrict */
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
xmax -= OL_TOGW + UI_UNIT_X;
@@ -1665,7 +1670,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
*starty -= UI_UNIT_Y;
for (ten = te->subtree.first; ten; ten = ten->next)
- outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx + UI_UNIT_X, starty);
+ outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
}
else {
for (ten = te->subtree.first; ten; ten = ten->next)
@@ -1749,7 +1754,8 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb,
}
-static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops)
+static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar,
+ SpaceOops *soops, TreeElement **te_edit)
{
TreeElement *te;
int starty, startx;
@@ -1781,7 +1787,7 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
for (te = soops->tree.first; te; te = te->next) {
- outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty);
+ outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty, te_edit);
}
}
@@ -1851,6 +1857,7 @@ void draw_outliner(const bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
uiBlock *block;
int sizey = 0, sizex = 0, sizex_rna = 0;
+ TreeElement *te_edit = NULL;
outliner_build_tree(mainvar, scene, soops); // always
@@ -1904,7 +1911,7 @@ void draw_outliner(const bContext *C)
/* draw outliner stuff (background, hierachy lines and names) */
outliner_back(ar);
block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- outliner_draw_tree((bContext *)C, block, scene, ar, soops);
+ outliner_draw_tree((bContext *)C, block, scene, ar, soops, &te_edit);
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
/* draw rna buttons */
@@ -1921,7 +1928,9 @@ void draw_outliner(const bContext *C)
}
/* draw edit buttons if nessecery */
- outliner_buttons(C, block, ar, soops, &soops->tree);
+ if (te_edit) {
+ outliner_buttons(C, block, ar, te_edit);
+ }
uiEndBlock(C, block);
uiDrawBlock(C, block);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 1e9b681197c..559fb6f932e 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -227,7 +227,7 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
else if (tselem->id->lib) {
- // XXX error_libdata();
+ BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
}
else if (te->idcode == ID_LI && te->parent) {
BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
@@ -1102,7 +1102,7 @@ static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem,
/* item is part of an array, so must set the array_index */
*array_index = te->index;
}
- else if (RNA_property_array_length(ptr, prop)) {
+ else if (RNA_property_array_check(prop)) {
/* entire array was selected, so keyframe all */
*flag |= KSP_FLAG_WHOLE_ARRAY;
}
@@ -1469,7 +1469,7 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "child", childname);
ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
- ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE);
+ ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL);
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -1525,7 +1525,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
- if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE)) {
+ if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL)) {
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index c1950e62817..a0af9340fe2 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -57,6 +57,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
+#include "BKE_treehash.h"
#include "ED_armature.h"
#include "ED_object.h"
@@ -113,7 +114,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
case ID_LA: case ID_AR: case ID_CA: case ID_SPK:
case ID_MA: case ID_TE: case ID_IP: case ID_IM:
case ID_SO: case ID_KE: case ID_WO: case ID_AC:
- case ID_NLA: case ID_TXT: case ID_GR:
+ case ID_NLA: case ID_TXT: case ID_GR: case ID_LS:
if (*idlevel == 0) *idlevel = idcode;
else if (*idlevel != idcode) *idlevel = -1;
break;
@@ -299,17 +300,13 @@ static void object_delete_cb(bContext *C, Scene *scene, TreeElement *te,
if (base == NULL)
base = BKE_scene_base_find(scene, (Object *)tselem->id);
if (base) {
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
// check also library later
if (scene->obedit == base->object)
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
te->directdata = NULL;
- BLI_ghash_remove(soops->treehash, tselem, NULL, NULL);
tselem->id = NULL;
- BLI_ghash_insert(soops->treehash, tselem, tselem);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 514bfc43ac7..10890a305fb 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -32,15 +32,6 @@
#include <math.h>
#include <string.h>
-#if defined WIN32 && !defined _LIBC || defined __sun
-# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
-#else
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-# endif
-# include <fnmatch.h>
-#endif
-
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
@@ -59,12 +50,14 @@
#include "DNA_sequence_types.h"
#include "DNA_speaker_types.h"
#include "DNA_object_types.h"
+#include "DNA_linestyle_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_ghash.h"
#include "BLI_mempool.h"
+#include "BLI_fnmatch.h"
#include "BLF_translation.h"
@@ -74,6 +67,7 @@
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
#include "BKE_idcode.h"
+#include "BKE_treehash.h"
#include "ED_armature.h"
#include "ED_screen.h"
@@ -116,9 +110,8 @@ static void outliner_storage_cleanup(SpaceOops *soops)
if (BLI_mempool_count(ts) == unused) {
BLI_mempool_destroy(ts);
soops->treestore = NULL;
-
if (soops->treehash) {
- BLI_ghash_free(soops->treehash, NULL, NULL);
+ BKE_treehash_free(soops->treehash);
soops->treehash = NULL;
}
}
@@ -135,14 +128,9 @@ static void outliner_storage_cleanup(SpaceOops *soops)
}
BLI_mempool_destroy(ts);
soops->treestore = new_ts;
-
if (soops->treehash) {
/* update hash table to fix broken pointers */
- BLI_ghash_clear(soops->treehash, NULL, NULL);
- BLI_mempool_iternew(soops->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- BLI_ghash_insert(soops->treehash, tselem, tselem);
- }
+ BKE_treehash_rebuild_from_treestore(soops->treehash, soops->treestore);
}
}
}
@@ -150,53 +138,23 @@ static void outliner_storage_cleanup(SpaceOops *soops)
}
}
-static unsigned int tse_hash(const void *ptr)
-{
- const TreeStoreElem *tse = (const TreeStoreElem *)ptr;
- unsigned int hash;
- BLI_assert(tse->type || !tse->nr);
- hash = BLI_ghashutil_inthash(SET_INT_IN_POINTER((tse->nr << 16) + tse->type));
- hash ^= BLI_ghashutil_inthash(tse->id);
- return hash;
-}
-
-static int tse_cmp(const void *a, const void *b)
-{
- const TreeStoreElem *tse_a = (const TreeStoreElem *)a;
- const TreeStoreElem *tse_b = (const TreeStoreElem *)b;
- return tse_a->type != tse_b->type || tse_a->nr != tse_b->nr || tse_a->id != tse_b->id;
-}
-
static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short type, short nr)
{
- /* When treestore comes directly from readfile.c, treehash is empty;
- * In this case we don't want to get TSE_CLOSED while adding elements one by one,
- * that is why this function restores treehash */
- bool restore_treehash = (soops->treestore && !soops->treehash);
- TreeStoreElem *tselem, elem_template;
+ TreeStoreElem *tselem;
if (soops->treestore == NULL) {
/* if treestore was not created in readfile.c, create it here */
soops->treestore = BLI_mempool_create(sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
+
}
if (soops->treehash == NULL) {
- soops->treehash = BLI_ghash_new(tse_hash, tse_cmp, "treehash");
- }
-
- if (restore_treehash) {
- BLI_mempool_iter iter;
- BLI_mempool_iternew(soops->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- BLI_ghash_insert(soops->treehash, tselem, tselem);
- }
+ soops->treehash = BKE_treehash_create_from_treestore(soops->treestore);
}
- /* check if 'te' is in treestore */
- elem_template.type = type;
- elem_template.nr = type ? nr : 0; // we're picky! :)
- elem_template.id = id;
- tselem = BLI_ghash_lookup(soops->treehash, &elem_template);
- if (tselem && !tselem->used) {
+ /* find any unused tree element in treestore and mark it as used
+ * (note that there may be multiple unused elements in case of linked objects) */
+ tselem = BKE_treehash_lookup_unused(soops->treehash, type, nr, id);
+ if (tselem) {
te->store_elem = tselem;
tselem->used = 1;
return;
@@ -210,7 +168,7 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty
tselem->used = 0;
tselem->flag = TSE_CLOSED;
te->store_elem = tselem;
- BLI_ghash_insert(soops->treehash, tselem, tselem);
+ BKE_treehash_add_element(soops->treehash, tselem);
}
/* ********************************************************* */
@@ -250,16 +208,12 @@ static TreeElement *outliner_find_tree_element(ListBase *lb, TreeStoreElem *stor
/* tse is not in the treestore, we use its contents to find a match */
TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse)
{
- GHash *th = soops->treehash;
- TreeStoreElem *tselem, tselem_template;
+ TreeStoreElem *tselem;
if (tse->id == NULL) return NULL;
/* check if 'tse' is in treestore */
- tselem_template.id = tse->id;
- tselem_template.type = tse->type;
- tselem_template.nr = tse->type ? tse->nr : 0;
- tselem = BLI_ghash_lookup(th, &tselem_template);
+ tselem = BKE_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
if (tselem)
return outliner_find_tree_element(&soops->tree, tselem);
@@ -423,6 +377,32 @@ static bool outliner_animdata_test(AnimData *adt)
return false;
}
+static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
+{
+ SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
+
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ if (linestyle) {
+ linestyle->id.flag |= LIB_DOIT;
+ }
+ }
+ }
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ if (linestyle) {
+ if (!(linestyle->id.flag & LIB_DOIT))
+ continue;
+ linestyle->id.flag &= ~LIB_DOIT;
+ outliner_add_element(soops, lb, linestyle, te, 0, 0);
+ }
+ }
+ }
+}
+
static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
{
SceneRenderLayer *srl;
@@ -448,6 +428,8 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0);
outliner_add_element(soops, lb, sce->world, te, 0, 0);
+
+ outliner_add_line_styles(soops, lb, sce, te);
}
// can be inlined if necessary
@@ -806,6 +788,14 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
break;
}
+ case ID_LS:
+ {
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
+
+ if (outliner_animdata_test(linestyle->adt))
+ outliner_add_element(soops, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0);
+ break;
+ }
}
}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 874852ee320..d695ffa46d5 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -43,6 +43,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_treehash.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -435,7 +436,7 @@ static void outliner_free(SpaceLink *sl)
BLI_mempool_destroy(soutliner->treestore);
}
if (soutliner->treehash) {
- BLI_ghash_free(soutliner->treehash, NULL, NULL);
+ BKE_treehash_free(soutliner->treehash);
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 68fd09f5fb7..dca1b481334 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -926,13 +926,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* stop all running jobs, except screen one. currently previews frustrate Render
* needed to make so sequencer's rendering doesn't conflict with compositor
*/
- WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE);
+ WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_COMPOSITE);
if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
/* in case of final rendering used for preview, kill all previews,
* otherwise threading conflict will happen in rendering module
*/
- WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_RENDER_PREVIEW);
+ WM_jobs_kill_type(CTX_wm_manager(C), NULL, WM_JOB_TYPE_RENDER_PREVIEW);
}
}
@@ -1086,10 +1086,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
type = GL_FLOAT;
if (ibuf->float_colorspace) {
- glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, TRUE);
+ glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, true);
}
else {
- glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, TRUE);
+ glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, true);
}
}
else if (ibuf->rect) {
@@ -1097,7 +1097,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
- glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, FALSE);
+ glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, false);
}
else {
format = GL_RGBA;
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 955a9c78c56..8b2e7067eb9 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -2155,12 +2155,13 @@ void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
}
/* view_all operator */
-static int sequencer_view_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int sequencer_view_all_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
View2D *v2d = UI_view2d_fromcontext(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- UI_view2d_smooth_view(C, ar, &v2d->tot);
+ UI_view2d_smooth_view(C, ar, &v2d->tot, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -2322,7 +2323,7 @@ void SEQUENCER_OT_view_toggle(wmOperatorType *ot)
/* view_selected operator */
-static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
+static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
@@ -2355,6 +2356,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
}
if (ymax != 0) {
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
xmax += xmargin;
xmin -= xmargin;
@@ -2377,7 +2379,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
cur_new.ymax = ymid + (orig_height / 2);
}
- UI_view2d_smooth_view(C, ar, &cur_new);
+ UI_view2d_smooth_view(C, ar, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -2958,7 +2960,7 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot)
/* identifiers */
ot->name = "Border Offset View";
ot->idname = "SEQUENCER_OT_view_ghost_border";
- ot->description = "Enable border select mode";
+ ot->description = "Set the boundaries of the border used for offset-view";
/* api callbacks */
ot->invoke = WM_border_select_invoke;
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index 51df21e509a..c8fd6e4b6ea 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -99,7 +99,7 @@ void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
/* identifiers */
ot->name = "Add Strip Modifier";
ot->idname = "SEQUENCER_OT_strip_modifier_add";
- ot->description = "Add a modifier to strip";
+ ot->description = "Add a modifier to the strip";
/* api callbacks */
ot->exec = strip_modifier_add_exec;
@@ -142,7 +142,7 @@ void SEQUENCER_OT_strip_modifier_remove(wmOperatorType *ot)
/* identifiers */
ot->name = "Remove Strip Modifier";
ot->idname = "SEQUENCER_OT_strip_modifier_remove";
- ot->description = "Add a modifier to strip";
+ ot->description = "Remove a modifier from the strip";
/* api callbacks */
ot->exec = strip_modifier_remove_exec;
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 254d15341cd..45f05d56076 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -892,7 +892,7 @@ void SEQUENCER_OT_select_border(wmOperatorType *ot)
/* identifiers */
ot->name = "Border Select";
ot->idname = "SEQUENCER_OT_select_border";
- ot->description = "Enable border select mode";
+ ot->description = "Select strips using border selection";
/* api callbacks */
ot->invoke = WM_border_select_invoke;
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 68428cd890f..deb37f8d943 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -152,7 +152,8 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
info->colfp = info->colf;
/* sequencer's image buffers are in non-linear space, need to make them linear */
- BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->colf);
+ copy_v4_v4(info->linearcol, info->colf);
+ BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->linearcol);
info->color_manage = TRUE;
}
@@ -219,7 +220,8 @@ static int sample_cancel(bContext *C, wmOperator *op)
static int sample_poll(bContext *C)
{
- return BKE_sequencer_editing_get(CTX_data_scene(C), FALSE) != NULL;
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+ return sseq && BKE_sequencer_editing_get(CTX_data_scene(C), FALSE) != NULL;
}
void SEQUENCER_OT_sample(wmOperatorType *ot)
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 04b2a21bf79..84c6329db53 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -491,6 +491,7 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
case ND_MARKERS:
case ND_RENDER_OPTIONS: /* for FPS and FPS Base */
case ND_SEQUENCER:
+ case ND_RENDER_RESULT:
ED_region_tag_redraw(ar);
break;
}
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index b04d2b16e8d..c668c8063a8 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -309,6 +309,8 @@ static void text_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "selection", TRUE);
}
+ WM_keymap_add_item(keymap, "TEXT_OT_properties", TKEY, KM_PRESS, KM_CTRL, 0);
+
WM_keymap_add_item(keymap, "TEXT_OT_jump", JKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 95fd7fce878..e92cab72042 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1133,23 +1133,23 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
- y1 = ar->winy - 2 - (vsell - offl) * lheight;
- y2 = y1 - (lheight * visible_lines + TXT_LINE_SPACING);
+ y1 = ar->winy - (vsell - offl) * lheight;
+ y2 = y1 - (lheight * visible_lines);
}
else {
- y1 = ar->winy - 2 - vsell * lheight;
- y2 = y1 - (lheight + TXT_LINE_SPACING);
+ y1 = ar->winy - vsell * lheight;
+ y2 = y1 - (lheight);
}
if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */
- x1 = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
x2 = x1 + ar->winx;
glColor4ub(255, 255, 255, 32);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glRecti(x1 - 4, y1, x2, y2 + TXT_LINE_SPACING);
+ glRecti(x1 - 4, y1, x2, y2);
glDisable(GL_BLEND);
}
}
@@ -1317,15 +1317,13 @@ void draw_text_main(SpaceText *st, ARegion *ar)
int wraplinecount = 0, wrap_skip = 0;
int margin_column_x;
- /* dpi controlled line height and font size */
- st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
-
- if (st->lheight_dpi) st->viewlines = (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING);
- else st->viewlines = 0;
-
/* if no text, nothing to do */
if (!text)
return;
+
+ /* dpi controlled line height and font size */
+ st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
+ st->viewlines = (st->lheight_dpi) ? (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING) : 0;
text_update_drawcache(st, ar);
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index 371ccfd9bd9..5d0c7181e77 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -53,11 +53,10 @@ void text_update_character_width(struct SpaceText *st);
void text_scroll_to_cursor(struct SpaceText *st, struct ScrArea *sa);
void text_update_cursor_moved(struct bContext *C);
- /* TXT_OFFSET used to be 35 when the scrollbar was on the left... */
-#define TXT_OFFSET ((int)(0.75f * U.widget_unit))
+#define TXT_OFFSET ((int)(0.5f * U.widget_unit))
#define TXT_SCROLL_WIDTH U.widget_unit
#define TXT_SCROLL_SPACE ((int)(0.1f * U.widget_unit))
-#define TXT_LINE_SPACING ((int)(0.2f * U.widget_unit)) /* space between lines */
+#define TXT_LINE_SPACING ((int)(0.3f * st->lheight_dpi)) /* space between lines */
#define TEXTXLOC (st->cwidth * st->linenrs_tot)
#define SUGG_LIST_SIZE 7
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index dec61a0e1ca..c078e612d68 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -949,7 +949,7 @@ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
if (txt_has_sel(text)) {
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_indent(text);
}
else
@@ -983,7 +983,7 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_unindent(text);
text_update_edited(text);
@@ -1063,7 +1063,7 @@ 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);
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_comment(text);
text_update_edited(text);
@@ -1096,7 +1096,7 @@ 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);
- txt_order_cursors(text);
+ txt_order_cursors(text, false);
txt_uncomment(text);
text_update_edited(text);
@@ -1861,11 +1861,23 @@ static int text_move_cursor(bContext *C, int type, int select)
break;
case PREV_CHAR:
- txt_move_left(text, select);
+ if (txt_has_sel(text) && !select) {
+ txt_order_cursors(text, false);
+ txt_pop_sel(text);
+ }
+ else {
+ txt_move_left(text, select);
+ }
break;
case NEXT_CHAR:
- txt_move_right(text, select);
+ if (txt_has_sel(text) && !select) {
+ txt_order_cursors(text, true);
+ txt_pop_sel(text);
+ }
+ else {
+ txt_move_right(text, select);
+ }
break;
case PREV_LINE:
@@ -1931,7 +1943,7 @@ void TEXT_OT_move_select(wmOperatorType *ot)
/* identifiers */
ot->name = "Move Select";
ot->idname = "TEXT_OT_move_select";
- ot->description = "Make selection from current cursor position to new cursor position type";
+ ot->description = "Move the cursor while selecting";
/* api callbacks */
ot->exec = text_move_select_exec;
@@ -2086,10 +2098,17 @@ void TEXT_OT_overwrite_toggle(wmOperatorType *ot)
static void txt_screen_clamp(SpaceText *st, ARegion *ar)
{
- int last;
- last = text_get_total_lines(st, ar);
- last = last - (st->viewlines / 2);
- CLAMP(st->top, 0, last);
+ if (st->top <= 0) {
+ st->top = 0;
+ }
+ else {
+ int last;
+ last = text_get_total_lines(st, ar);
+ last = last - (st->viewlines / 2);
+ if (last > 0 && st->top > last) {
+ st->top = last;
+ }
+ }
}
/* Moves the view vertically by the specified number of lines */
@@ -2272,7 +2291,7 @@ void TEXT_OT_scroll(wmOperatorType *ot)
* scroll_bar. Both do basically the same thing (aside
* from keymaps).*/
ot->idname = "TEXT_OT_scroll";
- ot->description = "Scroll text screen";
+ ot->description = "";
/* api callbacks */
ot->exec = text_scroll_exec;
@@ -2282,7 +2301,7 @@ void TEXT_OT_scroll(wmOperatorType *ot)
ot->poll = text_scroll_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
@@ -2366,7 +2385,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot)
* scroll. Both do basically the same thing (aside
* from keymaps).*/
ot->idname = "TEXT_OT_scroll_bar";
- ot->description = "Scroll text screen";
+ ot->description = "";
/* api callbacks */
ot->invoke = text_scroll_bar_invoke;
@@ -2375,7 +2394,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot)
ot->poll = text_region_scroll_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index d3d8868520d..2634dd3ec08 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -34,7 +34,6 @@
#include <string.h>
#include <math.h>
-
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -1099,12 +1098,14 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth,
if ((segments > 1) && (pchan)) {
float dlen = length / (float)segments;
- Mat4 *bbone = b_bone_spline_setup(pchan, 0);
+ Mat4 bbone[MAX_BBONE_SUBDIV];
int a;
-
- for (a = 0; a < segments; a++, bbone++) {
+
+ b_bone_spline_setup(pchan, 0, bbone);
+
+ for (a = 0; a < segments; a++) {
glPushMatrix();
- glMultMatrixf(bbone->mat);
+ glMultMatrixf(bbone[a].mat);
if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
else drawcube_size(xwidth, dlen, zwidth);
glPopMatrix();
@@ -1235,6 +1236,7 @@ static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float len
static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
+ Mat4 bbones_array[MAX_BBONE_SUBDIV];
Mat4 *bbones = NULL;
int segments = 0;
float length;
@@ -1243,8 +1245,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
segments = pchan->bone->segments;
length = pchan->bone->length;
- if (segments > 1)
- bbones = b_bone_spline_setup(pchan, 0);
+ if (segments > 1) {
+ b_bone_spline_setup(pchan, 0, bbones_array);
+ bbones = bbones_array;
+ }
}
else
length = ebone->length;
@@ -1534,7 +1538,7 @@ static void draw_pose_dofs(Object *ob)
if (bone->flag & BONE_SELECTED) {
if (bone->layer & arm->layer) {
if (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_ZLIMIT)) {
- if (ED_pose_channel_in_IK_chain(ob, pchan)) {
+ if (BKE_pose_channel_in_IK_chain(ob, pchan)) {
float corner[4][3], posetrans[3], mat[4][4];
float phi = 0.0f, theta = 0.0f, scale;
int a, i;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 62e3f8471a3..23b80fc5bea 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -1672,7 +1672,7 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
int i;
float drawsize;
const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
- MovieClip *clip = BKE_object_movieclip_get(scene, base->object, 0);
+ MovieClip *clip = BKE_object_movieclip_get(scene, base->object, false);
/* draw data for movie clip set as active for scene */
if (clip) {
@@ -1900,9 +1900,9 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
const bool is_edit = (lt->editlatt != NULL);
/* now we default make displist, this will modifiers work for non animated case */
- if (ob->disp.first == NULL)
+ if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
BKE_lattice_modifiers_calc(scene, ob);
- dl = BKE_displist_find(&ob->disp, DL_VERTS);
+ dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
if (is_edit) {
lt = lt->editlatt->latt;
@@ -2552,6 +2552,11 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
}
}
+static int draw_dm_override_material_color(int UNUSED(nr), void *UNUSED(attribs))
+{
+ return 1;
+}
+
/* Second section of routines: Combine first sets to form fancy
* drawing routines (for example rendering twice to get overlays).
*
@@ -3094,9 +3099,6 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
BMVert *eve_act = NULL;
bool use_occlude_wire = (v3d->flag2 & V3D_OCCLUDE_WIRE) && (dt > OB_WIRE);
- // BLI_assert(!cageDM || !(cageDM->dirty & DM_DIRTY_NORMALS));
- BLI_assert(!finalDM || !(finalDM->dirty & DM_DIRTY_NORMALS));
-
if (em->bm->selected.last) {
BMEditSelection *ese = em->bm->selected.last;
/* face is handeled above */
@@ -3369,8 +3371,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (!dm)
return;
- if (dm) BLI_assert(!(dm->dirty & DM_DIRTY_NORMALS));
-
/* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
* Note: Last "preview-active" modifier in stack will win! */
if (DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL) && modifiers_isPreview(ob))
@@ -3473,7 +3473,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
- dm->drawMappedFaces(dm, NULL, GPU_enable_material, NULL, NULL, DM_DRAW_USE_COLORS);
+ dm->drawMappedFaces(dm, NULL, draw_dm_override_material_color, NULL, NULL, DM_DRAW_USE_COLORS);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
@@ -3803,12 +3803,16 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
glEnable(GL_LIGHTING);
glEnableClientState(GL_VERTEX_ARRAY);
- if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
- else glFrontFace(GL_CCW);
if (ob->type == OB_MBALL) { /* mball always smooth shaded */
+ if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
+ else glFrontFace(GL_CCW);
glShadeModel(GL_SMOOTH);
}
+ else {
+ if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CCW);
+ else glFrontFace(GL_CW);
+ }
dl = lb->first;
while (dl) {
@@ -3971,7 +3975,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
case OB_CURVE:
cu = ob->data;
- lb = &ob->disp;
+ lb = &ob->curve_cache->disp;
if (solid) {
dl = lb->first;
@@ -4021,7 +4025,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
break;
case OB_SURF:
- lb = &ob->disp;
+ lb = &ob->curve_cache->disp;
if (solid) {
dl = lb->first;
@@ -4049,8 +4053,11 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
case OB_MBALL:
if (BKE_mball_is_basis(ob)) {
- lb = &ob->disp;
- if (lb->first == NULL) BKE_displist_make_mball(scene, ob);
+ lb = ob->curve_cache ? &ob->curve_cache->disp : NULL;
+ if (ELEM(lb, lb->first, NULL)) {
+ BKE_displist_make_mball(scene, ob);
+ lb = &ob->curve_cache->disp;
+ }
if (lb->first == NULL) {
return true;
}
@@ -4087,7 +4094,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba
if (v3d->flag2 & V3D_BACKFACE_CULLING) {
/* not all displists use same in/out normal direction convention */
glEnable(GL_CULL_FACE);
- glCullFace((base->object->type == OB_MBALL || base->object->derivedFinal) ? GL_BACK : GL_FRONT);
+ glCullFace(GL_BACK);
}
retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
@@ -4566,7 +4573,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pdd->ma_col = ma_col;
}
- psys->lattice = psys_get_lattice(&sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
/* circles don't use drawdata, so have to add a special case here */
if ((pdd || draw_as == PART_DRAW_CIRC) && draw_as != PART_DRAW_PATH) {
@@ -4892,9 +4899,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
}
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice = NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
if (pdd) {
@@ -5642,7 +5649,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
UI_ThemeColor(TH_WIRE_EDIT);
- for (bl = cu->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
+ for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
BevPoint *bevp = (BevPoint *)(bl + 1);
int nr = bl->nr;
int skip = nu->resolu / 16;
@@ -6065,7 +6072,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
}
else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
Curve *cu = ob->data;
- if ((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+ if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
float mindist, guidevec1[4], guidevec2[3];
//if (has_ipo_code(ob->ipo, OB_PD_FSTR))
@@ -6248,7 +6255,7 @@ static void draw_bounding_volume(Scene *scene, Object *ob, char type)
bb = BKE_mesh_boundbox_get(ob);
}
else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- bb = ob->bb ? ob->bb : ( (Curve *)ob->data)->bb;
+ bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
@@ -6283,9 +6290,7 @@ static void drawtexspace(Object *ob)
BKE_mesh_texspace_get(ob->data, loc, NULL, size);
}
else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- Curve *cu = ob->data;
- copy_v3_v3(size, cu->size);
- copy_v3_v3(loc, cu->loc);
+ BKE_curve_texspace_get(ob->data, loc, NULL, size);
}
else if (ob->type == OB_MBALL) {
MetaBall *mb = ob->data;
@@ -6323,7 +6328,6 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glDepthMask(0);
if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
DerivedMesh *dm = ob->derivedFinal;
bool has_faces = false;
@@ -6331,16 +6335,16 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
has_faces = dm->getNumTessFaces(dm);
}
else {
- has_faces = BKE_displist_has_faces(&ob->disp);
+ has_faces = BKE_displist_has_faces(&ob->curve_cache->disp);
}
- if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
draw_index_wire = false;
if (dm) {
draw_mesh_object_outline(v3d, ob, dm);
}
else {
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
draw_index_wire = true;
}
@@ -6348,7 +6352,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
if ((base->flag & OB_FROMDUPLI) == 0)
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
}
else if (ob->type == OB_ARMATURE) {
@@ -6375,8 +6379,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
- if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
if (ob->type == OB_CURVE)
draw_index_wire = false;
@@ -6384,7 +6387,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
drawCurveDMWired(ob);
}
else {
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
if (ob->type == OB_CURVE)
@@ -6393,7 +6396,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
- drawDispListwire(&ob->disp);
+ drawDispListwire(&ob->curve_cache->disp);
}
}
@@ -6662,23 +6665,17 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* faceselect exception: also draw solid when (dt == wire), except in editmode */
if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
- if (ob->type == OB_MESH) {
-
- if (ob->mode & OB_MODE_EDIT) {
- /* pass */
+ if (ob->type == OB_MESH) {
+ if (dt < OB_SOLID) {
+ zbufoff = 1;
+ dt = OB_SOLID;
}
- else {
- if (dt < OB_SOLID) {
- zbufoff = 1;
- dt = OB_SOLID;
- }
- if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
- dt = OB_PAINT;
- }
-
- glEnable(GL_DEPTH_TEST);
+ if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
+ dt = OB_PAINT;
}
+
+ glEnable(GL_DEPTH_TEST);
}
else {
if (dt < OB_SOLID) {
@@ -6703,7 +6700,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* bad exception, solve this! otherwise outline shows too late */
if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
/* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
- if (ob->disp.first == NULL) BKE_displist_make_curveTypes(scene, ob, 0);
+ if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first)) {
+ BKE_displist_make_curveTypes(scene, ob, 0);
+ }
}
/* draw outline for selected objects, mesh does itself */
@@ -6807,7 +6806,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_bounding_volume(scene, ob, ob->boundtype);
}
}
- else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
@@ -6825,7 +6824,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_bounding_volume(scene, ob, ob->boundtype);
}
}
- else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
//XXX old animsys if (cu->path)
@@ -7050,6 +7049,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
// get view vector
copy_v3_v3(viewnormal, rv3d->viewinv[2]);
+ invert_m4_m4(ob->imat, ob->obmat);
mul_mat3_m4_v3(ob->imat, viewnormal);
normalize_v3(viewnormal);
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 542ed7af0e6..a7940faa47d 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -83,6 +83,7 @@ struct GPUTexture;
#ifdef DEBUG_DRAW_TIME
# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
#endif
static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3])
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 6c61c2af816..58c0df6b6bd 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -44,6 +44,7 @@
#include "BKE_context.h"
#include "BKE_icons.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_screen.h"
@@ -258,6 +259,25 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
}
#endif
+void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+{
+ wmWindowManager *wm = bmain->wm.first;
+
+ if (v3d->drawtype != OB_RENDER) {
+ ARegion *ar;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d && rv3d->render_engine) {
+ WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
+ RE_engine_free(rv3d->render_engine);
+ rv3d->render_engine = NULL;
+ }
+ }
+ }
+}
+
/* ******************** default callbacks for view3d space ***************** */
static SpaceLink *view3d_new(const bContext *C)
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 75e7605df6b..eea084b4750 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -682,7 +682,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
}
BKE_nurb_test2D(nu);
- BKE_nurb_handles_test(nu); /* test for bezier too */
+ BKE_nurb_handles_test(nu, true); /* test for bezier too */
nu = nu->next;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index fa8d43b1756..b737dba1a3b 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -220,10 +220,10 @@ void ED_view3d_clipping_enable(void)
static bool view3d_clipping_test(const float co[3], float clip[6][4])
{
- if (0.0f < clip[0][3] + dot_v3v3(co, clip[0]))
- if (0.0f < clip[1][3] + dot_v3v3(co, clip[1]))
- if (0.0f < clip[2][3] + dot_v3v3(co, clip[2]))
- if (0.0f < clip[3][3] + dot_v3v3(co, clip[3]))
+ if (plane_point_side_v3(clip[0], co) > 0.0f)
+ if (plane_point_side_v3(clip[1], co) > 0.0f)
+ if (plane_point_side_v3(clip[2], co) > 0.0f)
+ if (plane_point_side_v3(clip[3], co) > 0.0f)
return false;
return true;
@@ -1662,7 +1662,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
if (scene->camera)
- clip = BKE_object_movieclip_get(scene, scene->camera, 1);
+ clip = BKE_object_movieclip_get(scene, scene->camera, true);
}
else {
clip = bgpic->clip;
@@ -2073,7 +2073,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
bb = *bb_tmp; /* must make a copy */
/* disable boundbox check for list creation */
- BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
+ BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1);
/* need this for next part of code */
unit_m4(dob->ob->obmat); /* obmat gets restored */
@@ -2083,7 +2083,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
glEndList();
use_displist = true;
- BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
+ BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
}
}
if (use_displist) {
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 7b8c197f3e6..67c9ea4599c 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -85,26 +85,23 @@
/* for ndof prints */
// #define DEBUG_NDOF_MOTION
-static void view3d_offset_lock_report(ReportList *reports)
-{
- BKE_report(reports, RPT_WARNING, "View offset is locked");
-}
-
bool ED_view3d_offset_lock_check(struct View3D *v3d, struct RegionView3D *rv3d)
{
return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
}
-#define VIEW3D_OP_OFS_LOCK_TEST(C, op) \
- { \
- View3D *v3d_tmp = CTX_wm_view3d(C); \
- RegionView3D *rv3d_tmp = CTX_wm_region_view3d(C); \
- if (ED_view3d_offset_lock_check(v3d_tmp, rv3d_tmp)) { \
- view3d_offset_lock_report((op)->reports); \
- return OPERATOR_CANCELLED; \
- } \
- } (void)0
-
+static bool view3d_operator_offset_lock_check(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (ED_view3d_offset_lock_check(v3d, rv3d)) {
+ BKE_report(op->reports, RPT_WARNING, "View offset is locked");
+ return true;
+ }
+ else {
+ return false;
+ }
+}
/* ********************** view3d_edit: view manipulations ********************* */
@@ -182,6 +179,27 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
}
}
+/**
+ * For viewport operators that exit camera persp.
+ *
+ * \note This differs from simply setting ``rv3d->persp = persp`` because it
+ * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
+ * otherwise switching out of camera view may jump to a different part of the scene.
+ */
+static void view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp)
+{
+ BLI_assert(rv3d->persp == RV3D_CAMOB);
+ BLI_assert(persp != RV3D_CAMOB);
+
+ if (v3d->camera) {
+ rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ }
+
+ if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
+ rv3d->persp = persp;
+ }
+}
/* ********************* box view support ***************** */
@@ -378,6 +396,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
/* ************************** init for view ops **********************************/
typedef struct ViewOpsData {
+ /* context pointers (assigned by viewops_data_alloc) */
ScrArea *sa;
ARegion *ar;
View3D *v3d;
@@ -435,10 +454,17 @@ static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
}
-static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event)
+/* -------------------------------------------------------------------- */
+/* ViewOpsData */
+
+/** \name Generic View Operator Custom-Data.
+ * \{ */
+
+/**
+ * Allocate and fill in context pointers for #ViewOpsData
+ */
+static void viewops_data_alloc(bContext *C, wmOperator *op)
{
- static float lastofs[3] = {0, 0, 0};
- RegionView3D *rv3d;
ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data");
/* store data */
@@ -446,7 +472,17 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
vod->sa = CTX_wm_area(C);
vod->ar = CTX_wm_region(C);
vod->v3d = vod->sa->spacedata.first;
- vod->rv3d = rv3d = vod->ar->regiondata;
+ vod->rv3d = vod->ar->regiondata;
+}
+
+/**
+ * Calculate the values for #ViewOpsData
+ */
+static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod = op->customdata;
+ static float lastofs[3] = {0, 0, 0};
+ RegionView3D *rv3d = vod->rv3d;
/* set the view from the camera, if view locking is enabled.
* we may want to make this optional but for now its needed always */
@@ -489,10 +525,15 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
}
else if (U.uiflag & USER_ZBUF_ORBIT) {
Scene *scene = CTX_data_scene(C);
+ float fallback_depth_pt[3];
view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
- if ((vod->use_dyn_ofs = ED_view3d_autodist(scene, vod->ar, vod->v3d, event->mval, vod->dyn_ofs, true))) {
+ negate_v3_v3(fallback_depth_pt, rv3d->ofs);
+
+ if ((vod->use_dyn_ofs = ED_view3d_autodist(scene, vod->ar, vod->v3d,
+ event->mval, vod->dyn_ofs, true, fallback_depth_pt)))
+ {
if (rv3d->is_persp) {
float my_origin[3]; /* original G.vd->ofs */
float my_pivot[3]; /* view */
@@ -522,6 +563,14 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
negate_v3_v3(rv3d->ofs, dvec);
}
+ else {
+ float mval_ar_mid[2] = {
+ (float)vod->ar->winx / 2.0f,
+ (float)vod->ar->winy / 2.0f};
+
+ ED_view3d_win_to_3d(vod->ar, vod->dyn_ofs, mval_ar_mid, rv3d->ofs);
+ negate_v3(rv3d->ofs);
+ }
negate_v3(vod->dyn_ofs);
copy_v3_v3(vod->ofs, rv3d->ofs);
}
@@ -576,6 +625,8 @@ static void viewops_data_free(bContext *C, wmOperator *op)
if (p && (p->flags & PAINT_FAST_NAVIGATE))
ED_region_tag_redraw(ar);
}
+/** \} */
+
/* ************************** viewrotate **********************************/
@@ -928,37 +979,27 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
- RegionView3D *rv3d;
/* makes op->customdata */
+ viewops_data_alloc(C, op);
viewops_data_create(C, op, event);
vod = op->customdata;
- rv3d = vod->rv3d;
- if (rv3d->viewlock) { /* poll should check but in some cases fails, see poll func for details */
+ if (vod->rv3d->viewlock) { /* poll should check but in some cases fails, see poll func for details */
viewops_data_free(C, op);
return OPERATOR_PASS_THROUGH;
}
/* switch from camera view when: */
- if (rv3d->persp != RV3D_PERSP) {
+ if (vod->rv3d->persp != RV3D_PERSP) {
if (U.uiflag & USER_AUTOPERSP) {
if (!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
- rv3d->persp = RV3D_PERSP;
+ vod->rv3d->persp = RV3D_PERSP;
}
}
- else if (rv3d->persp == RV3D_CAMOB) {
-
- /* changed since 2.4x, use the camera view */
- if (vod->v3d->camera) {
- rv3d->dist = ED_view3d_offset_distance(vod->v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(vod->v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
- }
-
- if (!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
- rv3d->persp = rv3d->lpersp;
- }
+ else if (vod->rv3d->persp == RV3D_CAMOB) {
+ view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, vod->rv3d->lpersp);
}
ED_region_tag_redraw(vod->ar);
}
@@ -970,7 +1011,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else
viewrotate_apply(vod, event->prevx, event->prevy);
- ED_view3d_depth_tag_update(rv3d);
+ ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -979,7 +1020,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else if (event->type == MOUSEROTATE) {
/* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
viewrotate_apply(vod, event->prevx, event->y);
- ED_view3d_depth_tag_update(rv3d);
+ ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -1012,9 +1053,13 @@ static int view3d_camera_user_poll(bContext *C)
static int view3d_lock_poll(bContext *C)
{
View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
- return ED_view3d_offset_lock_check(v3d, rv3d);
+ if (v3d) {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d) {
+ return ED_view3d_offset_lock_check(v3d, rv3d);
+ }
+ }
+ return false;
}
static int viewrotate_cancel(bContext *C, wmOperator *op)
@@ -1143,8 +1188,9 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, RegionView3D
static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type != NDOF_MOTION)
+ if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
+ }
else {
View3D *v3d = CTX_wm_view3d(C);
ViewOpsData *vod;
@@ -1153,6 +1199,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_view3d_camera_lock_init(v3d, rv3d);
+ viewops_data_alloc(C, op);
viewops_data_create(C, op, event);
vod = op->customdata;
@@ -1210,7 +1257,7 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Orbit View";
- ot->description = "Explore every angle of an object using the 3D mouse";
+ ot->description = "Orbit the view using the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_orbit";
/* api callbacks */
@@ -1225,8 +1272,9 @@ 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)
+ if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
+ }
else {
ViewOpsData *vod;
View3D *v3d = CTX_wm_view3d(C);
@@ -1237,6 +1285,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
+ viewops_data_alloc(C, op);
viewops_data_create(C, op, event);
vod = op->customdata;
@@ -1306,7 +1355,7 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Orbit View with Zoom";
- ot->description = "Explore every angle of an object using the 3D mouse";
+ ot->description = "Orbit and zoom the view using the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
/* api callbacks */
@@ -1322,14 +1371,16 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
*/
static int ndof_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type != NDOF_MOTION)
+ if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
+ }
else {
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
- VIEW3D_OP_OFS_LOCK_TEST(C, op);
+ if (view3d_operator_offset_lock_check(C, op))
+ return OPERATOR_CANCELLED;
ED_view3d_camera_lock_init(v3d, rv3d);
@@ -1401,7 +1452,7 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Pan View";
- ot->description = "Position your viewpoint with the 3D mouse";
+ ot->description = "Pan the view with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_pan";
/* api callbacks */
@@ -1422,13 +1473,13 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
else {
-
ViewOpsData *vod;
RegionView3D *rv3d;
View3D *v3d = CTX_wm_view3d(C);
wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
+ viewops_data_alloc(C, op);
viewops_data_create(C, op, event);
vod = op->customdata;
rv3d = vod->rv3d;
@@ -1492,7 +1543,7 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Move View";
- ot->description = "Position your viewpoint with the 3D mouse";
+ ot->description = "Pan and rotate the view with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_all";
/* api callbacks */
@@ -1627,6 +1678,7 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ViewOpsData *vod;
/* makes op->customdata */
+ viewops_data_alloc(C, op);
viewops_data_create(C, op, event);
vod = op->customdata;
@@ -1993,6 +2045,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ViewOpsData *vod;
/* makes op->customdata */
+ viewops_data_alloc(C, op);
viewops_data_create(C, op, event);
vod = op->customdata;
@@ -2207,12 +2260,34 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
- VIEW3D_OP_OFS_LOCK_TEST(C, op);
+ if (view3d_operator_offset_lock_check(C, op))
+ return OPERATOR_CANCELLED;
/* makes op->customdata */
- viewops_data_create(C, op, event);
+ viewops_data_alloc(C, op);
vod = op->customdata;
+ if (vod->rv3d->viewlock) { /* poll should check but in some cases fails, see poll func for details */
+ viewops_data_free(C, op);
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
+ /* switch from camera view when: */
+ if (vod->rv3d->persp != RV3D_PERSP) {
+ if (vod->rv3d->persp == RV3D_CAMOB) {
+ /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
+ view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
+ }
+ else {
+ vod->rv3d->persp = RV3D_PERSP;
+ }
+ ED_region_tag_redraw(vod->ar);
+ }
+
+ viewops_data_create(C, op, event);
+
+
/* if one or the other zoom position aren't set, set from event */
if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
RNA_int_set(op->ptr, "mx", event->x);
@@ -2257,25 +2332,6 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
-/* like ED_operator_region_view3d_active but check its not in ortho view */
-static int viewdolly_poll(bContext *C)
-{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
- if (rv3d) {
- if (rv3d->persp == RV3D_PERSP) {
- return 1;
- }
- else {
- View3D *v3d = CTX_wm_view3d(C);
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- return 1;
- }
- }
- }
- return 0;
-}
-
static int viewdolly_cancel(bContext *C, wmOperator *op)
{
viewops_data_free(C, op);
@@ -2294,7 +2350,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
ot->invoke = viewdolly_invoke;
ot->exec = viewdolly_exec;
ot->modal = viewdolly_modal;
- ot->poll = viewdolly_poll;
+ ot->poll = ED_operator_region_view3d_active;
ot->cancel = viewdolly_cancel;
/* flags */
@@ -2306,8 +2362,8 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
}
static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
- const float min[3], const float max[3],
- bool ok_dist)
+ const float min[3], const float max[3],
+ bool ok_dist, const int smooth_viewtx)
{
RegionView3D *rv3d = ar->regiondata;
float afm[3];
@@ -2369,10 +2425,14 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) {
rv3d->persp = RV3D_PERSP;
- view3d_smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL);
+ ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL,
+ new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL,
+ smooth_viewtx);
}
else {
- view3d_smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL);
+ ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
+ new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL,
+ smooth_viewtx);
}
/* smooth view does viewlock RV3D_BOXVIEW copy */
@@ -2381,7 +2441,7 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
/* 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],
- const bool ok_dist)
+ const bool ok_dist, const int smooth_viewtx)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar;
@@ -2391,7 +2451,7 @@ static void view3d_from_minmax_multi(bContext *C, View3D *v3d,
/* when using all regions, don't jump out of camera view,
* but _do_ allow locked cameras to be moved */
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
- view3d_from_minmax(C, v3d, ar, min, max, ok_dist);
+ view3d_from_minmax(C, v3d, ar, min, max, ok_dist, smooth_viewtx);
}
}
}
@@ -2409,6 +2469,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
/* any one of the regions may be locked */
(use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
const bool center = RNA_boolean_get(op->ptr, "center");
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
float min[3], max[3];
bool change = false;
@@ -2448,10 +2509,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
}
if (use_all_regions) {
- view3d_from_minmax_multi(C, v3d, min, max, true);
+ view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
}
else {
- view3d_from_minmax(C, v3d, ar, min, max, true);
+ view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx);
}
return OPERATOR_FINISHED;
@@ -2493,6 +2554,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
/* any one of the regions may be locked */
(use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
INIT_MINMAX(min, max);
@@ -2568,10 +2630,10 @@ static int viewselected_exec(bContext *C, wmOperator *op)
}
if (use_all_regions) {
- view3d_from_minmax_multi(C, v3d, min, max, ok_dist);
+ view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx);
}
else {
- view3d_from_minmax(C, v3d, ar, min, max, ok_dist);
+ view3d_from_minmax(C, v3d, ar, min, max, ok_dist, smooth_viewtx);
}
// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
@@ -2683,7 +2745,7 @@ void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot)
ot->flag = 0;
}
-static int viewcenter_cursor_exec(bContext *C, wmOperator *UNUSED(op))
+static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -2691,11 +2753,14 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *UNUSED(op))
if (rv3d) {
ARegion *ar = CTX_wm_region(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* non camera center */
float new_ofs[3];
negate_v3_v3(new_ofs, give_cursor(scene, v3d));
- view3d_smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, NULL, NULL);
+ ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
+ new_ofs, NULL, NULL, NULL,
+ smooth_viewtx);
/* smooth view does viewlock RV3D_BOXVIEW copy */
}
@@ -2718,7 +2783,7 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
ot->flag = 0;
}
-static int viewcenter_pick_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -2727,10 +2792,11 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *UNUSED(op), const wmE
if (rv3d) {
float new_ofs[3];
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(scene, ar, v3d, event->mval, new_ofs, false)) {
+ if (ED_view3d_autodist(scene, ar, v3d, event->mval, new_ofs, false, NULL)) {
/* pass */
}
else {
@@ -2739,7 +2805,9 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *UNUSED(op), const wmE
ED_view3d_win_to_3d_int(ar, new_ofs, event->mval, new_ofs);
}
negate_v3(new_ofs);
- view3d_smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, NULL, NULL);
+ ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
+ new_ofs, NULL, NULL, NULL,
+ smooth_viewtx);
}
return OPERATOR_FINISHED;
@@ -2988,6 +3056,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
Scene *scene = CTX_data_scene(C);
int gesture_mode;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* Zooms in on a border drawn by the user */
rcti rect;
@@ -3119,7 +3188,9 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
new_dist = dist_range_min;
}
- view3d_smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, &new_dist, NULL);
+ ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
+ new_ofs, NULL, &new_dist, NULL,
+ smooth_viewtx);
if (rv3d->viewlock & RV3D_BOXVIEW)
view3d_boxview_sync(CTX_wm_area(C), ar);
@@ -3224,7 +3295,8 @@ static EnumPropertyItem prop_view_items[] = {
static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
float q1, float q2, float q3, float q4,
- short view, int perspo, bool align_active)
+ short view, int perspo, bool align_active,
+ const int smooth_viewtx)
{
RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
float new_quat[4];
@@ -3285,14 +3357,18 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
if (U.uiflag & USER_AUTOPERSP) rv3d->persp = view ? RV3D_ORTHO : RV3D_PERSP;
else if (rv3d->persp == RV3D_CAMOB) rv3d->persp = perspo;
- view3d_smooth_view(C, v3d, ar, v3d->camera, NULL, rv3d->ofs, new_quat, NULL, NULL);
+ ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL,
+ rv3d->ofs, new_quat, NULL, NULL,
+ smooth_viewtx);
}
else {
if (U.uiflag & USER_AUTOPERSP) rv3d->persp = view ? RV3D_ORTHO : RV3D_PERSP;
else if (rv3d->persp == RV3D_CAMOB) rv3d->persp = perspo;
- view3d_smooth_view(C, v3d, ar, NULL, NULL, NULL, new_quat, NULL, NULL);
+ ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
+ NULL, new_quat, NULL, NULL,
+ smooth_viewtx);
}
}
@@ -3306,6 +3382,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
static int perspo = RV3D_PERSP;
int viewnum, nextperspo;
bool align_active;
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* no NULL check is needed, poll checks */
ED_view3d_context_user_region(C, &v3d, &ar);
@@ -3330,32 +3407,32 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
switch (viewnum) {
case RV3D_VIEW_BOTTOM:
axis_set_view(C, v3d, ar, 0.0, -1.0, 0.0, 0.0,
- viewnum, nextperspo, align_active);
+ viewnum, nextperspo, align_active, smooth_viewtx);
break;
case RV3D_VIEW_BACK:
axis_set_view(C, v3d, ar, 0.0, 0.0, -M_SQRT1_2, -M_SQRT1_2,
- viewnum, nextperspo, align_active);
+ viewnum, nextperspo, align_active, smooth_viewtx);
break;
case RV3D_VIEW_LEFT:
axis_set_view(C, v3d, ar, 0.5, -0.5, 0.5, 0.5,
- viewnum, nextperspo, align_active);
+ viewnum, nextperspo, align_active, smooth_viewtx);
break;
case RV3D_VIEW_TOP:
axis_set_view(C, v3d, ar, 1.0, 0.0, 0.0, 0.0,
- viewnum, nextperspo, align_active);
+ viewnum, nextperspo, align_active, smooth_viewtx);
break;
case RV3D_VIEW_FRONT:
axis_set_view(C, v3d, ar, M_SQRT1_2, -M_SQRT1_2, 0.0, 0.0,
- viewnum, nextperspo, align_active);
+ viewnum, nextperspo, align_active, smooth_viewtx);
break;
case RV3D_VIEW_RIGHT:
axis_set_view(C, v3d, ar, 0.5, -0.5, -0.5, -0.5,
- viewnum, nextperspo, align_active);
+ viewnum, nextperspo, align_active, smooth_viewtx);
break;
case RV3D_VIEW_CAMERA:
@@ -3411,7 +3488,9 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
/* finally do snazzy view zooming */
rv3d->persp = RV3D_CAMOB;
- view3d_smooth_view(C, v3d, ar, NULL, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens);
+ ED_view3d_smooth_view(C, v3d, ar, NULL, v3d->camera,
+ rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens,
+ smooth_viewtx);
}
else {
@@ -3419,7 +3498,8 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
/* does view3d_smooth_view too */
axis_set_view(C, v3d, ar,
rv3d->lviewquat[0], rv3d->lviewquat[1], rv3d->lviewquat[2], rv3d->lviewquat[3],
- rv3d->lview, rv3d->lpersp, 0);
+ rv3d->lview, rv3d->lpersp, 0,
+ smooth_viewtx);
}
}
break;
@@ -3479,6 +3559,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
if (rv3d->viewlock == 0) {
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
float angle = DEG2RADF((float)U.pad_rot_angle);
float quat_mul[4];
float quat_new[4];
@@ -3506,7 +3587,9 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul);
rv3d->view = RV3D_VIEW_USER;
- view3d_smooth_view(C, CTX_wm_view3d(C), ar, NULL, NULL, NULL, quat_new, NULL, NULL);
+ ED_view3d_smooth_view(C, CTX_wm_view3d(C), ar, NULL, NULL,
+ NULL, quat_new, NULL, NULL,
+ smooth_viewtx);
return OPERATOR_FINISHED;
}
@@ -3533,6 +3616,190 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
}
+
+/* ************************ viewroll ******************************** */
+
+static void view_roll_angle(ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ float quat_mul[4];
+
+ /* camera axis */
+ axis_angle_to_quat(quat_mul, dvec, angle);
+
+ mul_qt_qtqt(quat, orig_quat, quat_mul);
+ rv3d->view = RV3D_VIEW_USER;
+}
+
+static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
+{
+ float angle = 0.0;
+
+ {
+ float len1, len2, tot;
+
+ tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin;
+ len1 = (vod->ar->winrct.xmax - x) / tot;
+ len2 = (vod->ar->winrct.xmax - vod->origx) / 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);
+
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ view3d_boxview_sync(vod->sa, vod->ar);
+
+ ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod = op->customdata;
+ short event_code = VIEW_PASS;
+
+ /* execute the events */
+ if (event->type == MOUSEMOVE) {
+ event_code = VIEW_APPLY;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case VIEW_MODAL_CONFIRM:
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_MOVE:
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ case VIEWROT_MODAL_SWITCH_ROTATE:
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ event_code = VIEW_CONFIRM;
+ break;
+ }
+ }
+ else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ event_code = VIEW_CONFIRM;
+ }
+
+ if (event_code == VIEW_APPLY) {
+ viewroll_apply(vod, event->x, event->y);
+ }
+ else if (event_code == VIEW_CONFIRM) {
+ ED_view3d_depth_tag_update(vod->rv3d);
+ viewops_data_free(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int viewroll_exec(bContext *C, wmOperator *op)
+{
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *ar;
+
+ if (op->customdata) {
+ ViewOpsData *vod = op->customdata;
+ ar = vod->ar;
+ v3d = vod->v3d;
+ }
+ else {
+ ar = CTX_wm_region(C);
+ v3d = CTX_wm_view3d(C);
+ }
+
+ rv3d = ar->regiondata;
+ if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
+ const float angle = RNA_float_get(op->ptr, "angle");
+ float mousevec[3];
+ float quat_new[4];
+
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
+ normalize_v3_v3(mousevec, rv3d->viewinv[2]);
+ negate_v3(mousevec);
+ view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle);
+
+ ED_view3d_smooth_view(C, v3d, ar, NULL, NULL,
+ NULL, quat_new, NULL, NULL,
+ smooth_viewtx);
+
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ viewops_data_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewOpsData *vod;
+
+ /* makes op->customdata */
+ viewops_data_alloc(C, op);
+ viewops_data_create(C, op, event);
+ vod = op->customdata;
+
+ if (RNA_struct_property_is_set(op->ptr, "angle")) {
+ viewroll_exec(C, op);
+ }
+ else {
+ /* overwrite the mouse vector with the view direction */
+ normalize_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]);
+ negate_v3(vod->mousevec);
+
+ if (event->type == MOUSEROTATE) {
+ vod->origx = vod->oldx = event->x;
+ viewroll_apply(vod, event->prevx, event->prevy);
+ ED_view3d_depth_tag_update(vod->rv3d);
+
+ viewops_data_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* add temp handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_FINISHED;
+}
+
+static int viewroll_cancel(bContext *C, wmOperator *op)
+{
+ viewops_data_free(C, op);
+
+ return OPERATOR_CANCELLED;
+}
+
+void VIEW3D_OT_view_roll(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Roll";
+ ot->description = "Roll the view";
+ ot->idname = "VIEW3D_OT_view_roll";
+
+ /* api callbacks */
+ ot->invoke = viewroll_invoke;
+ ot->exec = viewroll_exec;
+ ot->modal = viewroll_modal;
+ ot->poll = ED_operator_rv3d_user_region_poll;
+ ot->cancel = viewroll_cancel;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ ot->prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
+}
+
static EnumPropertyItem prop_view_pan_items[] = {
{V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"},
{V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"},
@@ -3553,7 +3820,8 @@ static int viewpan_exec(bContext *C, wmOperator *op)
float zfac;
int pandir;
- VIEW3D_OP_OFS_LOCK_TEST(C, op);
+ if (view3d_operator_offset_lock_check(C, op))
+ return OPERATOR_CANCELLED;
pandir = RNA_enum_get(op->ptr, "type");
@@ -3855,6 +4123,11 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
float zfac;
bool flip;
+ /* normally the caller should ensure this,
+ * but this is called from areas that aren't already dealing with the viewport */
+ if (rv3d == NULL)
+ return;
+
zfac = ED_view3d_calc_zfac(rv3d, fp, &flip);
/* reset the depth based on the view offset (we _know_ the offset is infront of us) */
@@ -3869,7 +4142,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(scene, ar, v3d, mval, fp, true))
+ if (ED_view3d_autodist(scene, ar, v3d, mval, fp, true, NULL))
depth_used = true;
}
@@ -4041,7 +4314,9 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
}
/* XXX todo Zooms in on a border drawn by the user */
-bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2], float mouse_worldloc[3], bool alphaoverride)
+bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d,
+ const int mval[2], float mouse_worldloc[3],
+ const bool alphaoverride, const float fallback_depth_pt[3])
{
bglMats mats; /* ZBuffer depth vars */
float depth_close;
@@ -4053,22 +4328,27 @@ bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2
depth_close = view_autodist_depth_margin(ar, mval, 4);
- if (depth_close == FLT_MAX)
- return false;
+ if (depth_close != FLT_MAX) {
+ cent[0] = (double)mval[0];
+ cent[1] = (double)mval[1];
- cent[0] = (double)mval[0];
- cent[1] = (double)mval[1];
+ if (gluUnProject(cent[0], cent[1], depth_close,
+ mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
+ {
+ mouse_worldloc[0] = (float)p[0];
+ mouse_worldloc[1] = (float)p[1];
+ mouse_worldloc[2] = (float)p[2];
+ return true;
+ }
+ }
- if (!gluUnProject(cent[0], cent[1], depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
- {
+ if (fallback_depth_pt) {
+ ED_view3d_win_to_3d_int(ar, fallback_depth_pt, mval, mouse_worldloc);
+ return true;
+ }
+ else {
return false;
}
-
- mouse_worldloc[0] = (float)p[0];
- mouse_worldloc[1] = (float)p[1];
- mouse_worldloc[2] = (float)p[2];
- return true;
}
void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode)
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index a1a13130b27..9341ea9d3e6 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -159,6 +159,11 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_UP);
WM_modalkeymap_add_item(keymap, FKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_DOWN);
+ WM_modalkeymap_add_item(keymap, UPARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_FORWARD);
+ WM_modalkeymap_add_item(keymap, DOWNARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_BACKWARD);
+ WM_modalkeymap_add_item(keymap, LEFTARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_LEFT);
+ WM_modalkeymap_add_item(keymap, RIGHTARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_RIGHT);
+
WM_modalkeymap_add_item(keymap, XKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_X);
WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_Z);
@@ -580,6 +585,12 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
double time_currwheel;
float time_wheel;
+ /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
+ if (fly->axis == -1) {
+ fly->axis = 2;
+ fly->speed = fabsf(fly->speed);
+ }
+
time_currwheel = PIL_check_seconds_timer();
time_wheel = (float)(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
@@ -599,6 +610,12 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
double time_currwheel;
float time_wheel;
+ /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
+ if (fly->axis == -1) {
+ fly->axis = 2;
+ fly->speed = -fabsf(fly->speed);
+ }
+
time_currwheel = PIL_check_seconds_timer();
time_wheel = (float)(time_currwheel - fly->time_lastwheel);
fly->time_lastwheel = time_currwheel;
@@ -806,9 +823,10 @@ static void flyMoveCamera(bContext *C, RegionView3D *rv3d, FlyInfo *fly,
static int flyApply(bContext *C, FlyInfo *fly)
{
-#define FLY_ROTATE_FAC 2.5f /* more is faster */
+#define FLY_ROTATE_FAC 10.0f /* more is faster */
#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
#define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */
+#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */
/* fly mode - Shift+F
* a fly loop where the user can move move the view as if they are flying
@@ -1052,7 +1070,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
}
/* impose a directional lag */
- interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * 5.0f))));
+ interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
if (rv3d->persp == RV3D_CAMOB) {
Object *lock_ob = fly->root_parent ? fly->root_parent : fly->v3d->camera;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 085af4e5c18..a496bbba72f 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -95,6 +95,7 @@ void VIEW3D_OT_view_persportho(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_add(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_remove(struct wmOperatorType *ot);
void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_view_roll(struct wmOperatorType *ot);
void VIEW3D_OT_clip_border(struct wmOperatorType *ot);
void VIEW3D_OT_cursor3d(struct wmOperatorType *ot);
void VIEW3D_OT_manipulator(struct wmOperatorType *ot);
@@ -186,8 +187,9 @@ void VIEW3D_OT_game_start(struct wmOperatorType *ot);
bool ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], const struct BoundBox *bb);
-void view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegion *ar, struct Object *, struct Object *,
- float *ofs, float *quat, float *dist, float *lens);
+void ED_view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegion *ar, struct Object *, struct Object *,
+ float *ofs, float *quat, float *dist, float *lens,
+ const int smooth_viewtx);
void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect);
void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d);
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index d13ab15d837..2023513ad92 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -368,7 +368,7 @@ void lattice_foreachScreenVert(
Object *obedit = vc->obedit;
Lattice *lt = obedit->data;
BPoint *bp = lt->editlatt->latt->def;
- DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
+ DispList *dl = obedit->curve_cache ? BKE_displist_find(&obedit->curve_cache->disp, DL_VERTS) : NULL;
float *co = dl ? dl->verts : NULL;
int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 6780b71c906..dec9085baeb 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -138,6 +138,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_view_all);
WM_operatortype_append(VIEW3D_OT_viewnumpad);
WM_operatortype_append(VIEW3D_OT_view_orbit);
+ WM_operatortype_append(VIEW3D_OT_view_roll);
WM_operatortype_append(VIEW3D_OT_view_pan);
WM_operatortype_append(VIEW3D_OT_view_persportho);
WM_operatortype_append(VIEW3D_OT_background_image_add);
@@ -283,7 +284,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD6, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANUP);
-
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / -12);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD6, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / 12);
+
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_PANUP);
@@ -294,6 +297,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELUPMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPUP);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPDOWN);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELUPMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / -12);
+ RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / 12);
+
/* active aligned, replaces '*' key in 2.4x */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
@@ -371,6 +377,11 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_string_set(kmi->ptr, "value_1", "SOLID");
RNA_string_set(kmi->ptr, "value_2", "TEXTURED");
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "data_path", "space_data.viewport_shade");
+ RNA_string_set(kmi->ptr, "value_1", "SOLID");
+ RNA_string_set(kmi->ptr, "value_2", "RENDERED");
+
/* selection*/
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", FALSE);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 5e71913ea4a..28ffdea0e6c 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -405,15 +405,15 @@ void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float
float line_end[3];
if (rv3d->is_persp) {
- float mousevec[3];
+ float mousevec[3], lambda;
copy_v3_v3(line_sta, rv3d->viewinv[3]);
ED_view3d_win_to_vector(ar, mval, mousevec);
add_v3_v3v3(line_end, line_sta, mousevec);
- if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], true) == 0) {
- /* highly unlikely to ever happen, mouse vector parallel with view plane */
- zero_v3(out);
- }
+ /* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the
+ * view no matter what, so apply the unsigned factor instead */
+ lambda = line_plane_factor_v3(depth_pt, rv3d->viewinv[2], line_sta, line_end);
+ interp_v3_v3v3(out, line_sta, line_end, fabsf(lambda));
}
else {
float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f;
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index b2f2d5849a4..bca162d156b 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -803,7 +803,7 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
view3d_ruler_header_update(sa);
- WM_cursor_modal(win, BC_CROSSCURSOR);
+ WM_cursor_modal_set(win, BC_CROSSCURSOR);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -1029,7 +1029,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
exit:
if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
- WM_cursor_restore(ruler_info->win);
+ WM_cursor_modal_restore(ruler_info->win);
view3d_ruler_end(C, ruler_info);
view3d_ruler_free(ruler_info);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 19426ab2dfa..8553791e229 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1462,7 +1462,7 @@ static bool mouse_select(bContext *C, const int mval[2], bool extend, bool desel
/* index of bundle is 1<<16-based. if there's no "bone" index
* in height word, this buffer value belongs to camera. not to bundle */
if (buffer[4 * i + 3] & 0xFFFF0000) {
- MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, 0);
+ MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase;
MovieTrackingTrack *track;
@@ -2406,12 +2406,12 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons
{
Object *ob = vc->obact;
Mesh *me = ob ? ob->data : NULL;
- /* int bbsel; */ /* UNUSED */
+ bool bbsel;
- if (me) {
- bm_vertoffs = me->totpoly + 1; /* max index array */
+ bm_vertoffs = me->totpoly + 1; /* max index array */
- /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ if (bbsel) {
edbm_backbuf_check_and_select_tfaces(me, select);
EDBM_backbuf_free();
paintface_flush_flags(ob);
@@ -2431,15 +2431,17 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons
const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
Object *ob = vc->obact;
Mesh *me = ob->data;
- /* int bbsel; */ /* UNUSED */
+ bool bbsel;
/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
if (use_zbuf) {
bm_vertoffs = me->totvert + 1; /* max index array */
- /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- edbm_backbuf_check_and_select_verts_obmode(me, select);
- EDBM_backbuf_free();
+ bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ if (bbsel) {
+ edbm_backbuf_check_and_select_verts_obmode(me, select);
+ EDBM_backbuf_free();
+ }
}
else {
CircleSelectUserData data;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 0f2f07a1053..7c29ab01c24 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -143,7 +143,7 @@ static void special_transvert_update(Object *obedit)
}
BKE_nurb_test2D(nu);
- BKE_nurb_handles_test(nu); /* test for bezier too */
+ BKE_nurb_handles_test(nu, true); /* test for bezier too */
nu = nu->next;
}
}
@@ -882,7 +882,7 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
{
- MovieClip *clip = BKE_object_movieclip_get(scene, ob, 0);
+ MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
MovieTracking *tracking;
MovieTrackingObject *object;
int ok = 0;
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 44c338d22b9..74d72061995 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -40,6 +40,7 @@
#include "BLI_rect.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_callbacks.h"
#include "BKE_anim.h"
#include "BKE_action.h"
@@ -152,8 +153,9 @@ static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms
/* will start timer if appropriate */
/* the arguments are the desired situation */
-void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera, Object *camera,
- float *ofs, float *quat, float *dist, float *lens)
+void ED_view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera, Object *camera,
+ float *ofs, float *quat, float *dist, float *lens,
+ const int smooth_viewtx)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
@@ -202,7 +204,7 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
}
/* skip smooth viewing for render engine draw */
- if (U.smooth_viewtx && v3d->drawtype != OB_RENDER) {
+ if (smooth_viewtx && v3d->drawtype != OB_RENDER) {
bool changed = false; /* zero means no difference */
if (oldcamera != camera)
@@ -231,7 +233,7 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
rv3d->view = RV3D_VIEW_USER;
}
- sms.time_allowed = (double)U.smooth_viewtx / 1000.0;
+ sms.time_allowed = (double)smooth_viewtx / 1000.0;
/* if this is view rotation only
* we can decrease the time allowed by
@@ -376,12 +378,15 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot)
/* identifiers */
ot->name = "Smooth View";
+ ot->description = "";
ot->idname = "VIEW3D_OT_smoothview";
- ot->description = "The time to animate the change of view (in milliseconds)";
/* api callbacks */
ot->invoke = view3d_smoothview_invoke;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+
ot->poll = ED_operator_view3d_active;
}
@@ -505,7 +510,7 @@ void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot)
}
-static int view3d_setobjectascamera_exec(bContext *C, wmOperator *UNUSED(op))
+static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
ARegion *ar;
@@ -514,6 +519,8 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+
/* no NULL check is needed, poll checks */
ED_view3d_context_user_region(C, &v3d, &ar);
rv3d = ar->regiondata;
@@ -525,8 +532,11 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *UNUSED(op))
if (v3d->scenelock)
scene->camera = ob;
- if (camera_old != ob) /* unlikely but looks like a glitch when set to the same */
- view3d_smooth_view(C, v3d, ar, camera_old, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens);
+ if (camera_old != ob) { /* unlikely but looks like a glitch when set to the same */
+ ED_view3d_smooth_view(C, v3d, ar, camera_old, v3d->camera,
+ rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens,
+ smooth_viewtx);
+ }
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS | NC_OBJECT | ND_DRAW, CTX_data_scene(C));
}
@@ -617,7 +627,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], const BoundB
int a, flag = -1, fl;
if (bb == NULL) return true;
- if (bb->flag & OB_BB_DISABLED) return true;
+ if (bb->flag & BOUNDBOX_DISABLED) return true;
mul_m4_m4m4(mat, rv3d->persmat, obmat);
@@ -1170,7 +1180,7 @@ static bool view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, Report
return ok;
}
-static void restore_localviewdata(ScrArea *sa, int free)
+static void restore_localviewdata(Main *bmain, ScrArea *sa, int free)
{
ARegion *ar;
View3D *v3d = sa->spacedata.first;
@@ -1207,12 +1217,7 @@ static void restore_localviewdata(ScrArea *sa, int free)
}
}
- if (v3d->drawtype != OB_RENDER) {
- if (rv3d->render_engine) {
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
- }
+ ED_view3d_shade_update(bmain, v3d, sa);
}
}
}
@@ -1227,7 +1232,7 @@ static bool view3d_localview_exit(Main *bmain, Scene *scene, ScrArea *sa)
locallay = v3d->lay & 0xFF000000;
- restore_localviewdata(sa, 1); /* 1 = free */
+ restore_localviewdata(bmain, sa, 1); /* 1 = free */
/* for when in other window the layers have changed */
if (v3d->scenelock) v3d->lay = scene->lay;
@@ -1433,6 +1438,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
{
#ifdef WITH_GAMEENGINE
Scene *startscene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
ScrArea /* *sa, */ /* UNUSED */ *prevsa = CTX_wm_area(C);
ARegion *ar, *prevar = CTX_wm_region(C);
wmWindow *prevwin = CTX_wm_window(C);
@@ -1449,6 +1455,8 @@ static int game_engine_exec(bContext *C, wmOperator *op)
* the window manager until after this operator exits */
WM_redraw_windows(C);
+ BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_PRE);
+
rv3d = CTX_wm_region_view3d(C);
/* sa = CTX_wm_area(C); */ /* UNUSED */
ar = CTX_wm_region(C);
@@ -1504,6 +1512,8 @@ static int game_engine_exec(bContext *C, wmOperator *op)
BKE_scene_set_background(CTX_data_main(C), startscene);
//XXX BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST);
+
return OPERATOR_FINISHED;
#else
(void)C; /* unused */
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index d5a9d0f9f93..ce2f07f1813 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1749,29 +1749,32 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
// If modal, save settings back in scene if not set as operator argument
if (t->flag & T_MODAL) {
-
/* save settings if not set in operator */
- if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- if (t->obedit)
- ts->proportional = proportional;
- else if (t->options & CTX_MASK)
- ts->proportional_mask = (proportional != PROP_EDIT_OFF);
- else
- ts->proportional_objects = (proportional != PROP_EDIT_OFF);
- }
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- ts->proportional_size = t->prop_size;
- }
+ /* skip saving proportional edit if it was not actually used */
+ if (!(t->options & CTX_NO_PET)) {
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional")) &&
+ !RNA_property_is_set(op->ptr, prop))
+ {
+ if (t->obedit)
+ ts->proportional = proportional;
+ else if (t->options & CTX_MASK)
+ ts->proportional_mask = (proportional != PROP_EDIT_OFF);
+ else
+ ts->proportional_objects = (proportional != PROP_EDIT_OFF);
+ }
- if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
- !RNA_property_is_set(op->ptr, prop))
- {
- ts->prop_mode = t->prop_mode;
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
+ !RNA_property_is_set(op->ptr, prop))
+ {
+ ts->proportional_size = t->prop_size;
+ }
+
+ if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
+ !RNA_property_is_set(op->ptr, prop))
+ {
+ ts->prop_mode = t->prop_mode;
+ }
}
/* do we check for parameter? */
@@ -1851,7 +1854,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
options |= CTX_TEXTURE;
}
}
-
+
t->options = options;
t->mode = mode;
@@ -1893,6 +1896,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
else if (t->spacetype == SPACE_CLIP) {
unit_m3(t->spacemtx);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
+ t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_NODE) {
unit_m3(t->spacemtx);
@@ -3005,7 +3009,12 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
copy_v3_v3(center, td->center);
}
else if (t->options & CTX_MOVIECLIP) {
- copy_v3_v3(center, td->center);
+ if (td->flag & TD_INDIVIDUAL_SCALE) {
+ copy_v3_v3(center, td->center);
+ }
+ else {
+ copy_v3_v3(center, t->center);
+ }
}
else {
copy_v3_v3(center, t->center);
@@ -4795,6 +4804,26 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
return NULL;
}
+/* interpoaltes along a line made up of 2 segments (used for edge slide) */
+static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float t)
+{
+ float t_mid, t_delta;
+
+ /* could be pre-calculated */
+ t_mid = line_point_factor_v3(v2, v1, v3);
+
+ t_delta = t - t_mid;
+ if (fabsf(t_delta) < FLT_EPSILON) {
+ copy_v3_v3(p, v2);
+ }
+ else if (t_delta < 0.0f) {
+ interp_v3_v3v3(p, v1, v2, t / t_mid);
+ }
+ else {
+ interp_v3_v3v3(p, v2, v3, (t - t_mid) / (1.0f - t_mid));
+ }
+}
+
static void len_v3_ensure(float v[3], const float length)
{
normalize_v3(v);
@@ -4820,7 +4849,7 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp,
float tvec[3];
if (isect_line_plane_v3(tvec,
l_iter->v->co, l_iter->next->v->co,
- l_tmp->v->co, plane_no, false))
+ l_tmp->v->co, plane_no))
{
const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co);
/* allow some overlap to avoid missing the intersection because of float precision */
@@ -5707,20 +5736,16 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
/* Non-Prop mode */
if (sld && sld->is_proportional == FALSE) {
View3D *v3d = CTX_wm_view3d(C);
- float marker[3];
- float v1[3], v2[3];
- float interp_v;
+ float co_a[3], co_b[3], co_mark[3];
TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const float fac = (sld->perc + 1.0f) / 2.0f;
const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
const float guide_size = ctrl_size - 0.5f;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
const int alpha_shade = -30;
- add_v3_v3v3(v1, curr_sv->v_co_orig, curr_sv->dir_a);
- add_v3_v3v3(v2, curr_sv->v_co_orig, curr_sv->dir_b);
-
- interp_v = (sld->perc + 1.0f) / 2.0f;
- interp_v3_v3v3(marker, v2, v1, interp_v);
+ add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_a);
+ add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_b);
if (v3d && v3d->zbuf)
glDisable(GL_DEPTH_TEST);
@@ -5761,7 +5786,12 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t)
UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
glPointSize(guide_size);
bglBegin(GL_POINTS);
- bglVertex3fv(marker);
+#if 0
+ interp_v3_v3v3(co_mark, co_b, co_a, fac);
+ bglVertex3fv(co_mark);
+#endif
+ interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
+ bglVertex3fv(co_mark);
bglEnd();
@@ -5823,10 +5853,10 @@ static int doEdgeSlide(TransInfo *t, float perc)
add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_b);
if (sld->flipped_vtx) {
- interp_v3_v3v3(sv->v->co, co_b, co_a, fac);
+ interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
}
else {
- interp_v3_v3v3(sv->v->co, co_a, co_b, fac);
+ interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac);
}
}
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 4a1c4203a43..a4828317604 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -341,7 +341,9 @@ typedef struct TransInfo {
float auto_values[4];
float axis[3];
float axis_orig[3]; /* TransCon can change 'axis', store the original value here */
-
+
+ short remove_on_cancel; /* remove elements if operator is cancelled */
+
void *view;
struct bContext *context; /* Only valid (non null) during an operator called function. */
struct ScrArea *sa;
@@ -350,6 +352,7 @@ typedef struct TransInfo {
struct ToolSettings *settings;
struct wmTimer *animtimer;
struct wmKeyMap *keymap; /* so we can do lookups for header text */
+ struct ReportList *reports; /* assign from the operator, or can be NULL */
int mval[2]; /* current mouse position */
float zfac; /* use for 3d view */
struct Object *obedit;
@@ -455,7 +458,7 @@ typedef struct TransInfo {
#define TD_USEQUAT (1 << 3)
#define TD_NOTCONNECTED (1 << 4)
#define TD_SINGLESIZE (1 << 5) /* used for scaling of MetaElem->rad */
-/*#define TD_TIMEONLY (1 << 8) */ /*UNUSED*/
+#define TD_INDIVIDUAL_SCALE (1 << 8) /* Scale relative to individual element center */
#define TD_NOCENTER (1 << 9)
#define TD_NO_EXT (1 << 10) /* ext abused for particle key timing */
#define TD_SKIP (1 << 11) /* don't transform this data */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index fd8fba91fc9..a73bf86feb1 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -727,6 +727,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float tmat[4][4], imat[4][4];
float center[3];
+ int depth_test_enabled;
UI_ThemeColor(TH_GRID);
@@ -759,10 +760,17 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
glScalef(1.0f / aspx, 1.0f / aspy, 1.0);
}
+ depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
+ if (depth_test_enabled)
+ glDisable(GL_DEPTH_TEST);
+
set_inverted_drawing(1);
drawcircball(GL_LINE_LOOP, center, t->prop_size, imat);
set_inverted_drawing(0);
+ if (depth_test_enabled)
+ glEnable(GL_DEPTH_TEST);
+
glPopMatrix();
}
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 95ec20a0c2b..f5a12fed076 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -58,9 +58,12 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_smallhash.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_string.h"
+#include "BLI_rect.h"
#include "BKE_DerivedMesh.h"
#include "BKE_action.h"
@@ -120,7 +123,19 @@
#include "transform.h"
#include "bmesh.h"
-#include "BLI_sys_types.h" // for intptr_t support
+/**
+ * Transforming around ourselves is no use, fallback to individual origins,
+ * useful for curve/armatures.
+ */
+static void transform_around_single_fallback(TransInfo *t)
+{
+ if ((t->total == 1) &&
+ (ELEM3(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
+ (ELEM3(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
+ {
+ t->around = V3D_LOCAL;
+ }
+}
/* when transforming islands */
struct TransIslandData {
@@ -274,6 +289,13 @@ static void createTransTexspace(TransInfo *t)
id = ob->data;
if (id == NULL || !ELEM3(GS(id->name), ID_ME, ID_CU, ID_MB)) {
+ BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
+ t->total = 0;
+ return;
+ }
+
+ if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
t->total = 0;
return;
}
@@ -989,8 +1011,7 @@ static void createTransPose(TransInfo *t, Object *ob)
if (arm->flag & ARM_RESTPOS) {
if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) {
- // XXX use transform operator reports
- // BKE_report(op->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled");
+ BKE_report(t->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled");
return;
}
}
@@ -1030,8 +1051,7 @@ static void createTransPose(TransInfo *t, Object *ob)
}
if (td != (t->data + t->total)) {
- // XXX use transform operator reports
- // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error");
+ BKE_report(t->reports, RPT_DEBUG, "Bone selection count error");
}
/* initialize initial auto=ik chainlen's? */
@@ -1078,6 +1098,8 @@ static void createTransArmatureVerts(TransInfo *t)
if (!t->total) return;
+ transform_around_single_fallback(t);
+
copy_m3_m4(mtx, t->obedit->obmat);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
@@ -1402,6 +1424,8 @@ static void createTransCurveVerts(TransInfo *t)
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
+ transform_around_single_fallback(t);
+
copy_m3_m4(mtx, t->obedit->obmat);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
@@ -1437,7 +1461,9 @@ static void createTransCurveVerts(TransInfo *t)
{
copy_v3_v3(td->iloc, bezt->vec[0]);
td->loc = bezt->vec[0];
- copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1 : 0]);
+ copy_v3_v3(td->center, bezt->vec[(hide_handles ||
+ (t->around == V3D_LOCAL) ||
+ (bezt->f2 & SELECT)) ? 1 : 0]);
if (hide_handles) {
if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
else td->flag = 0;
@@ -1505,7 +1531,9 @@ static void createTransCurveVerts(TransInfo *t)
{
copy_v3_v3(td->iloc, bezt->vec[2]);
td->loc = bezt->vec[2];
- copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1 : 2]);
+ copy_v3_v3(td->center, bezt->vec[(hide_handles ||
+ (t->around == V3D_LOCAL) ||
+ (bezt->f2 & SELECT)) ? 1 : 2]);
if (hide_handles) {
if (bezt->f2 & SELECT) td->flag = TD_SELECTED;
else td->flag = 0;
@@ -1546,7 +1574,7 @@ static void createTransCurveVerts(TransInfo *t)
* but for now just don't change handle types */
if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) {
/* sets the handles based on their selection, do this after the data is copied to the TransData */
- BKE_nurb_handles_test(nu);
+ BKE_nurb_handles_test(nu, !hide_handles);
}
}
else {
@@ -1848,15 +1876,13 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
/* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__);
- BMVert **queue = MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__);
- STACK_DECLARE(queue);
+ BLI_LINKSTACK_DECLARE(queue, BMVert *);
/* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
- BMVert **queue_next = MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__);
- STACK_DECLARE(queue_next);
+ BLI_LINKSTACK_DECLARE(queue_next, BMVert *);
- STACK_INIT(queue);
- STACK_INIT(queue_next);
+ BLI_LINKSTACK_INIT(queue);
+ BLI_LINKSTACK_INIT(queue_next);
{
BMIter viter;
@@ -1871,7 +1897,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
dists[i] = FLT_MAX;
}
else {
- STACK_PUSH(queue, v);
+ BLI_LINKSTACK_PUSH(queue, v);
dists[i] = 0.0f;
}
@@ -1880,11 +1906,11 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
do {
BMVert *v;
- unsigned int i;
+ LinkNode *lnk;
memcpy(dists_prev, dists, sizeof(float) * bm->totvert);
- while ((v = STACK_POP(queue))) {
+ while ((v = BLI_LINKSTACK_POP(queue))) {
BMIter iter;
BMEdge *e;
BMLoop *l;
@@ -1896,7 +1922,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
- STACK_PUSH(queue_next, v_other);
+ BLI_LINKSTACK_PUSH(queue_next, v_other);
}
}
}
@@ -1912,7 +1938,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
- STACK_PUSH(queue_next, v_other);
+ BLI_LINKSTACK_PUSH(queue_next, v_other);
}
}
} while ((l = l->next) != l_end);
@@ -1921,22 +1947,20 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
}
/* clear for the next loop */
- for (i = 0; i < STACK_SIZE(queue_next); i++) {
- BM_elem_flag_disable(queue_next[i], BM_ELEM_TAG);
+ for (lnk = queue_next; lnk; lnk = lnk->next) {
+ BM_elem_flag_disable((BMVert *)lnk->link, BM_ELEM_TAG);
}
- STACK_SWAP(queue, queue_next);
+ BLI_LINKSTACK_SWAP(queue, queue_next);
/* none should be tagged now since 'queue_next' is empty */
BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
- } while (STACK_SIZE(queue));
+ } while (BLI_LINKSTACK_SIZE(queue));
- STACK_FREE(queue);
- STACK_FREE(queue_next);
+ BLI_LINKSTACK_FREE(queue);
+ BLI_LINKSTACK_FREE(queue_next);
- MEM_freeN(queue);
- MEM_freeN(queue_next);
MEM_freeN(dists_prev);
}
@@ -2125,7 +2149,7 @@ static void createTransEditVerts(TransInfo *t)
BMVert *eve;
BMIter iter;
BMVert *eve_act = NULL;
- float *mappedcos = NULL, *quats = NULL;
+ float (*mappedcos)[3] = NULL, (*quats)[4] = NULL;
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
float *dists = NULL;
int a;
@@ -2214,30 +2238,34 @@ static void createTransEditVerts(TransInfo *t)
island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map);
}
- /* BMESH_TODO, crazy-space writing into the index values is BAD!, means we cant
- * use the values for vertex mirror - campbell */
-
/* detect CrazySpace [tm] */
if (modifiers_getCageIndex(t->scene, t->obedit, NULL, 1) >= 0) {
- if (modifiers_isCorrectableDeformed(t->obedit)) {
- int totleft;
+ int totleft = -1;
+ 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 = editbmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
+ }
- /* if we still have more modifiers, also do crazyspace
- * correction with quats, relative to the coordinates after
- * the modifiers that support deform matrices (defcos) */
- if (totleft > 0) {
- mappedcos = crazyspace_get_mapped_editverts(t->scene, t->obedit);
- quats = MEM_mallocN((t->total) * sizeof(float) * 4, "crazy quats");
- crazyspace_set_quats_editmesh(em, (float *)defcos, mappedcos, quats); /* BMESH_TODO, abuses vertex index, should use an int array */
- if (mappedcos)
- MEM_freeN(mappedcos);
- }
+ /* if we still have more modifiers, also do crazyspace
+ * correction with quats, relative to the coordinates after
+ * the modifiers that support deform matrices (defcos) */
+
+#if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
+ if ((totleft > 0) || (totleft == -1))
+#else
+ if (totleft > 0)
+#endif
+ {
+ mappedcos = crazyspace_get_mapped_editverts(t->scene, t->obedit);
+ quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
+ crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats);
+ if (mappedcos)
+ MEM_freeN(mappedcos);
+ }
- if (defcos)
- MEM_freeN(defcos);
+ if (defcos) {
+ MEM_freeN(defcos);
}
}
@@ -2283,12 +2311,12 @@ static void createTransEditVerts(TransInfo *t)
}
/* CrazySpace */
- if (defmats || (quats && BM_elem_index_get(eve) != -1)) {
+ if (defmats || (quats && BM_elem_flag_test(eve, BM_ELEM_TAG))) {
float mat[3][3], qmat[3][3], imat[3][3];
/* use both or either quat and defmat correction */
- if (quats && BM_elem_index_get(eve) != -1) {
- quat_to_mat3(qmat, quats + 4 * BM_elem_index_get(eve));
+ if (quats && BM_elem_flag_test(eve, BM_ELEM_TAG)) {
+ quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
if (defmats)
mul_serie_m3(mat, mtx, qmat, defmats[a],
@@ -3866,7 +3894,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
}
/* if handles were not selected, store their selection status */
- if (!(sel1) && !(sel3)) {
+ if (!(sel1) || !(sel3)) {
if (hdata == NULL)
hdata = initTransDataCurveHandles(td, bezt);
}
@@ -5248,6 +5276,48 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
}
}
+static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t)
+{
+ SpaceClip *sc = t->sa->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ bool do_update = false;
+
+ do_update |= (plane_track->flag & SELECT) != 0;
+ if (do_update == false) {
+ if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ MovieTrackingTrack *track = plane_track->point_tracks[i];
+
+ if (TRACK_VIEW_SELECTED(sc, track)) {
+ do_update = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (do_update) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+ }
+ }
+
+ if (t->scene->nodetree) {
+ /* tracks can be used for stabilization nodes,
+ * flush update for such nodes */
+ nodeUpdateID(t->scene->nodetree, &clip->id);
+ WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
+ }
+}
+
static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
{
Mask *mask = NULL;
@@ -5281,6 +5351,25 @@ static void special_aftertrans_update__mask(bContext *C, TransInfo *t)
}
}
+static void special_aftertrans_update__node(bContext *UNUSED(C), TransInfo *t)
+{
+ int canceled = (t->state == TRANS_CANCEL);
+
+ if (canceled && t->remove_on_cancel) {
+ /* remove selected nodes on cancel */
+ SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ bNodeTree *ntree = snode->edittree;
+ if (ntree) {
+ bNode *node, *node_next;
+ for (node = ntree->nodes.first; node; node = node_next) {
+ node_next = node->next;
+ if (node->flag & NODE_SELECT)
+ nodeFreeNode(ntree, node);
+ }
+ }
+ }
+}
+
static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
{
/* so automerge supports mirror */
@@ -5392,6 +5481,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first;
+ special_aftertrans_update__node(C, t);
if (canceled == 0) {
ED_node_post_apply_transform(C, snode->edittree);
@@ -5403,15 +5493,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_CLIP) {
if (t->options & CTX_MOVIECLIP) {
- SpaceClip *sc = t->sa->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
-
- if (t->scene->nodetree) {
- /* tracks can be used for stabilization nodes,
- * flush update for such nodes */
- nodeUpdateID(t->scene->nodetree, &clip->id);
- WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
- }
+ special_aftertrans_update__movieclip(C, t);
}
else if (t->options & CTX_MASK) {
special_aftertrans_update__mask(C, t);
@@ -5959,7 +6041,8 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
enum transDataTracking_Mode {
transDataTracking_ModeTracks = 0,
- transDataTracking_ModeCurves = 1
+ transDataTracking_ModeCurves = 1,
+ transDataTracking_ModePlaneTracks = 2,
};
typedef struct TransDataTracking {
@@ -5978,6 +6061,9 @@ typedef struct TransDataTracking {
/* marker transformation from curves editor */
float *prev_pos, scale;
short coord;
+
+ MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
} TransDataTracking;
static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
@@ -6008,6 +6094,7 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
tdt->markersnr = track->markersnr;
tdt->markers = track->markers;
+ tdt->track = track;
if (rel) {
if (!anchor) {
@@ -6026,6 +6113,7 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
copy_v3_v3(td->iloc, td->loc);
//copy_v3_v3(td->center, td->loc);
+ td->flag |= TD_INDIVIDUAL_SCALE;
td->center[0] = marker->pos[0] * aspx;
td->center[1] = marker->pos[1] * aspy;
@@ -6076,6 +6164,52 @@ static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d
}
}
+static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
+ MovieTrackingPlaneTrack *plane_track, float corner[2],
+ float aspx, float aspy)
+{
+ tdt->mode = transDataTracking_ModePlaneTracks;
+ tdt->plane_track = plane_track;
+
+ td2d->loc[0] = corner[0] * aspx; /* hold original location */
+ td2d->loc[1] = corner[1] * aspy;
+
+ td2d->loc2d = corner; /* current location */
+ td2d->loc[2] = 0.0f;
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->center, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+}
+
+static void planeTrackToTransData(const int framenr, TransData *td, TransData2D *td2d,
+ TransDataTracking *tdt, MovieTrackingPlaneTrack *plane_track,
+ float aspx, float aspy)
+{
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+ int i;
+
+ tdt->flag = plane_marker->flag;
+ plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+
+ for (i = 0; i < 4; i++) {
+ planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspx, aspy);
+ }
+}
+
static void transDataTrackingFree(TransInfo *t)
{
TransDataTracking *tdt = t->customData;
@@ -6096,7 +6230,9 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
MovieTrackingTrack *track;
+ MovieTrackingPlaneTrack *plane_track;
TransDataTracking *tdt;
int framenr = ED_space_clip_get_clip_frame_number(sc);
float aspx, aspy;
@@ -6122,6 +6258,15 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
track = track->next;
}
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (plane_track->flag & SELECT) {
+ t->total += 4;
+ }
+ }
+
if (t->total == 0)
return;
@@ -6165,11 +6310,23 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
track = track->next;
}
+
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (plane_track->flag & SELECT) {
+ planeTrackToTransData(framenr, td, td2d, tdt, plane_track, aspx, aspy);
+ td += 4;
+ td2d += 4;
+ tdt += 4;
+ }
+ }
}
static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
- MovieTrackingMarker *marker, MovieTrackingMarker *prev_marker,
- short coord, float size)
+ MovieTrackingTrack *track, MovieTrackingMarker *marker,
+ MovieTrackingMarker *prev_marker, short coord, float size)
{
float frames_delta = (marker->framenr - prev_marker->framenr);
@@ -6180,6 +6337,7 @@ static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDa
tdt->coord = coord;
tdt->scale = 1.0f / size * frames_delta;
tdt->prev_pos = prev_marker->pos;
+ tdt->track = track;
/* calculate values depending on marker's speed */
td2d->loc[0] = marker->framenr;
@@ -6265,14 +6423,14 @@ static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
continue;
if (marker->flag & MARKER_GRAPH_SEL_X) {
- markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i - 1], 0, width);
+ markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
td += 1;
td2d += 1;
tdt += 1;
}
if (marker->flag & MARKER_GRAPH_SEL_Y) {
- markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i - 1], 1, height);
+ markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
td += 1;
td2d += 1;
@@ -6313,57 +6471,54 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
static void cancelTransTracking(TransInfo *t)
{
- TransDataTracking *tdt = t->customData;
SpaceClip *sc = t->sa->spacedata.first;
- MovieClip *clip = ED_space_clip_get_clip(sc);
- ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
- MovieTrackingTrack *track;
- MovieTrackingMarker *marker;
- int a, framenr = ED_space_clip_get_clip_frame_number(sc);
+ int i, framenr = ED_space_clip_get_clip_frame_number(sc);
- if (tdt->mode == transDataTracking_ModeTracks) {
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- marker = BKE_tracking_marker_get(track, framenr);
- marker->flag = tdt->flag;
+ i = 0;
+ while (i < t->total) {
+ TransDataTracking *tdt = (TransDataTracking *) t->customData + i;
- tdt++;
+ if (tdt->mode == transDataTracking_ModeTracks) {
+ MovieTrackingTrack *track = tdt->track;
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- if (track->flag & SELECT)
- tdt++;
+ marker->flag = tdt->flag;
- if (track->pat_flag & SELECT)
- tdt += 2;
+ if (track->flag & SELECT)
+ i++;
- if (track->search_flag & SELECT)
- tdt += 2;
- }
+ if (track->pat_flag & SELECT)
+ i += 4;
- track = track->next;
+ if (track->search_flag & SELECT)
+ i += 2;
}
- }
- else if (tdt->mode == transDataTracking_ModeCurves) {
- MovieTrackingMarker *prev_marker;
+ else if (tdt->mode == transDataTracking_ModeCurves) {
+ MovieTrackingTrack *track = tdt->track;
+ MovieTrackingMarker *marker, *prev_marker;
+ int a;
- track = tracksbase->first;
- while (track) {
- if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
- for (a = 1; a < track->markersnr; a++) {
- marker = &track->markers[a];
- prev_marker = &track->markers[a - 1];
+ for (a = 1; a < track->markersnr; a++) {
+ marker = &track->markers[a];
+ prev_marker = &track->markers[a - 1];
- if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
- continue;
+ if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+ continue;
- if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
- marker->flag = tdt->flag;
- }
+ if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
+ marker->flag = tdt->flag;
}
}
+ }
+ else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+ MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
- track = track->next;
+ plane_marker->flag = tdt->flag;
+ i += 3;
}
+
+ i++;
}
}
@@ -6432,6 +6587,10 @@ void flushTransTracking(TransInfo *t)
else if (tdt->mode == transDataTracking_ModeCurves) {
td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
}
+ else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+ td2d->loc2d[0] = td2d->loc[0] / aspx;
+ td2d->loc2d[1] = td2d->loc[1] / aspy;
+ }
}
}
@@ -6443,29 +6602,40 @@ typedef struct TransDataMasking {
float handle[2], orig_handle[2];
float vec[3][3];
MaskSplinePoint *point;
+ float parent_matrix[3][3];
+ float parent_inverse_matrix[3][3];
} TransDataMasking;
-static void MaskPointToTransData(MaskSplinePoint *point,
+static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
TransData *td, TransData2D *td2d, TransDataMasking *tdm,
const int propmode, const float asp[2])
{
BezTriple *bezt = &point->bezt;
short is_sel_point = MASKPOINT_ISSEL_KNOT(point);
short is_sel_any = MASKPOINT_ISSEL_ANY(point);
+ float parent_matrix[3][3], parent_inverse_matrix[3][3];
tdm->point = point;
copy_m3_m3(tdm->vec, bezt->vec);
+ BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
+ invert_m3_m3(parent_inverse_matrix, parent_matrix);
+
if (propmode || is_sel_point) {
int i;
for (i = 0; i < 3; i++) {
+ copy_m3_m3(tdm->parent_matrix, parent_matrix);
+ copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
+
/* CV coords are scaled by aspects. this is needed for rotations and
* proportional editing to be consistent with the stretched CV coords
* that are displayed. this also means that for display and numinput,
* and when the the CV coords are flushed, these are converted each time */
- td2d->loc[0] = bezt->vec[i][0] * asp[0];
- td2d->loc[1] = bezt->vec[i][1] * asp[1];
+ mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]);
+ td2d->loc[0] *= asp[0];
+ td2d->loc[1] *= asp[1];
td2d->loc[2] = 0.0f;
+
td2d->loc2d = bezt->vec[i];
td->flag = 0;
@@ -6497,18 +6667,23 @@ static void MaskPointToTransData(MaskSplinePoint *point,
td++;
td2d++;
+ tdm++;
}
}
else {
tdm->is_handle = TRUE;
+ copy_m3_m3(tdm->parent_matrix, parent_matrix);
+ copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
BKE_mask_point_handle(point, tdm->handle);
copy_v2_v2(tdm->orig_handle, tdm->handle);
- td2d->loc[0] = tdm->handle[0] * asp[0];
- td2d->loc[1] = tdm->handle[1] * asp[1];
+ mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle);
+ td2d->loc[0] *= asp[0];
+ td2d->loc[1] *= asp[1];
td2d->loc[2] = 0.0f;
+
td2d->loc2d = tdm->handle;
td->flag = 0;
@@ -6538,6 +6713,7 @@ static void MaskPointToTransData(MaskSplinePoint *point,
static void createTransMaskingData(bContext *C, TransInfo *t)
{
+ Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
TransData *td = NULL;
@@ -6610,7 +6786,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
MaskSplinePoint *point = &spline->points[i];
if (propmode || MASKPOINT_ISSEL_ANY(point)) {
- MaskPointToTransData(point, td, td2d, tdm, propmode, asp);
+ MaskPointToTransData(scene, point, td, td2d, tdm, propmode, asp);
if (propmode || MASKPOINT_ISSEL_KNOT(point)) {
td += 3;
@@ -6643,6 +6819,7 @@ void flushTransMasking(TransInfo *t)
for (a = 0, td = t->data2d, tdm = t->customData; a < t->total; a++, td++, tdm++) {
td->loc2d[0] = td->loc[0] * inv[0];
td->loc2d[1] = td->loc[1] * inv[1];
+ mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d);
if (tdm->is_handle)
BKE_mask_point_set_handle(tdm->point, td->loc2d, t->flag & T_ALT_TRANSFORM, tdm->orig_handle, tdm->vec);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index cb0a0530036..233ef1d18a5 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1052,6 +1052,7 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
t->ar = ar;
t->obedit = obedit;
t->settings = ts;
+ t->reports = op ? op->reports : NULL;
if (obedit) {
copy_m3_m4(t->obedit_mat, obedit->obmat);
@@ -1104,6 +1105,13 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
t->options |= CTX_EDGE;
}
+ t->remove_on_cancel = false;
+
+ if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) && RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->remove_on_cancel = true;
+ }
+ }
/* Assign the space type, some exceptions for running in different mode */
if (sa == NULL) {
@@ -1511,7 +1519,6 @@ void calculateCenterCursor2D(TransInfo *t)
if (t->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- /* only space supported right now but may change */
if (t->options & CTX_MASK) {
ED_space_image_get_aspect(sima, &aspx, &aspy);
}
@@ -1520,17 +1527,37 @@ void calculateCenterCursor2D(TransInfo *t)
}
cursor = sima->cursor;
}
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
+ if (t->options & CTX_MOVIECLIP) {
+ ED_space_clip_get_aspect_dimension_aware(space_clip, &aspx, &aspy);
+ }
+ else {
+ ED_space_clip_get_aspect(space_clip, &aspx, &aspy);
+ }
+ cursor = space_clip->cursor;
+ }
if (cursor) {
if (t->options & CTX_MASK) {
float co[2];
float frame_size[2];
- SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
- ED_space_image_get_size_fl(sima, frame_size);
-
- BKE_mask_coord_from_frame(co, cursor, frame_size);
- ED_space_image_get_aspect(sima, &aspx, &aspy);
+ if (t->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
+ ED_space_image_get_size_fl(sima, frame_size);
+ BKE_mask_coord_from_frame(co, cursor, frame_size);
+ ED_space_image_get_aspect(sima, &aspx, &aspy);
+ }
+ else if (t->spacetype == SPACE_CLIP) {
+ SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
+ ED_space_clip_get_size_fl(space_clip, frame_size);
+ BKE_mask_coord_from_frame(co, cursor, frame_size);
+ ED_space_clip_get_aspect(space_clip, &aspx, &aspy);
+ }
+ else {
+ BLI_assert(!"Shall not happen");
+ }
t->center[0] = co[0] * aspx;
t->center[1] = co[1] * aspy;
@@ -1609,7 +1636,7 @@ void calculateCenter(TransInfo *t)
calculateCenterMedian(t);
break;
case V3D_CURSOR:
- if (t->spacetype == SPACE_IMAGE)
+ if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
calculateCenterCursor2D(t);
else if (t->spacetype == SPACE_IPO)
calculateCenterCursorGraph2D(t);
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 6fecf0d6642..f667a98812b 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -428,12 +428,12 @@ int calc_manipulator_stats(const bContext *C)
totsel++;
}
else {
- if (bezt->f1) {
- calc_tw_center(scene, bezt->vec[0]);
+ if (bezt->f1 & SELECT) {
+ calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 0]);
totsel++;
}
- if (bezt->f3) {
- calc_tw_center(scene, bezt->vec[2]);
+ if (bezt->f3 & SELECT) {
+ calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 2]);
totsel++;
}
}
@@ -1858,11 +1858,12 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
* See [#34621], it's a miracle it did not cause more problems!!! */
/* However, we need to copy the "release_confirm" property... */
PointerRNA props_ptr;
- WM_operator_properties_create(&props_ptr, "TRANSFORM_OT_trackball");
+ wmOperatorType *ot = WM_operatortype_find("TRANSFORM_OT_trackball", true);
+ WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_boolean_set(&props_ptr, "release_confirm", RNA_boolean_get(op->ptr, "release_confirm"));
-
- WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, &props_ptr);
- //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, NULL, NULL, FALSE);
+ WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ //wm_operator_invoke(C, WM_operatortype_find(ot->idname, 0), event, NULL, NULL, FALSE);
+ WM_operator_properties_free(&props_ptr);
}
else if (drawflags & MAN_ROT_C) {
switch (drawflags) {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index eb204be3220..e7c22fc0899 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -537,6 +537,8 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
if (flags & P_OPTIONS) {
RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
+ prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
if (flags & P_CORRECT_UV) {
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 55d80d63234..cd6a2e6712e 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -728,31 +728,46 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
}
else {
+ const bool use_handle = (cu->drawflag & CU_HIDE_HANDLES) == 0;
+
for (nu = nurbs->first; nu; nu = nu->next) {
/* only bezier has a normal */
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
+ short flag = 0;
+
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+
+ if (use_handle) {
+ if (bezt->f1 & SELECT) flag |= SEL_F1;
+ if (bezt->f2 & SELECT) flag |= SEL_F2;
+ if (bezt->f3 & SELECT) flag |= SEL_F3;
+ }
+ else {
+ flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0;
+ }
+
/* exception */
- if ((bezt->f1 | bezt->f2 | bezt->f3) & SELECT) {
+ if (flag) {
float tvec[3];
- if ((bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT) {
+ if ((v3d->around == V3D_LOCAL) ||
+ ELEM3(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
+ {
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
add_v3_v3(normal, tvec);
}
else {
- if (bezt->f1 & SELECT) {
+ /* ignore bezt->f2 in this case */
+ if (flag & SEL_F1) {
sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]);
normalize_v3(tvec);
add_v3_v3(normal, tvec);
}
- if (bezt->f2 & SELECT) {
- sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[2]);
- normalize_v3(tvec);
- add_v3_v3(normal, tvec);
- }
- if (bezt->f3 & SELECT) {
+ if (flag & SEL_F3) {
sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]);
normalize_v3(tvec);
add_v3_v3(normal, tvec);
@@ -762,6 +777,11 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
BKE_nurb_bezt_calc_plane(nu, bezt, tvec);
add_v3_v3(plane, tvec);
}
+
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
+
bezt++;
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 909ca68cc20..04bccac2a15 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -59,6 +59,7 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_mesh.h"
+#include "BKE_tracking.h"
#include "RNA_access.h"
@@ -133,7 +134,8 @@ bool validSnap(TransInfo *t)
bool activeSnap(TransInfo *t)
{
- return (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT;
+ return ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP) ||
+ ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT);
}
void drawSnapping(const struct bContext *C, TransInfo *t)
@@ -1147,7 +1149,7 @@ static void TargetSnapClosest(TransInfo *t)
}
}
-static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3],
+static bool snapEdge(ARegion *ar, const float v1co[3], const short v1no[3], const float v2co[3], const short v2no[3], float obmat[4][4], float timat[3][3],
const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
@@ -1234,7 +1236,7 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s
return retval;
}
-static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3],
+static bool snapVertex(ARegion *ar, const float vco[3], const short vno[3], float obmat[4][4], float timat[3][3],
const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2],
float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth)
{
@@ -1518,6 +1520,129 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
return retval;
}
+/* may extend later (for now just snaps to empty center) */
+static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3], const float mval[2],
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
+{
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ bool retval = false;
+
+ if (ob->transflag & OB_DUPLI) {
+ return retval;
+ }
+ /* for now only vertex supported */
+ if (snap_mode != SCE_SNAP_MODE_VERTEX) {
+ return retval;
+ }
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_normal);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ switch (snap_mode) {
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ const float zero_co[3] = {0.0f};
+ retval |= snapVertex(ar, zero_co, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return retval;
+}
+
+static bool snapCamera(short snap_mode, ARegion *ar, Scene *scene, Object *object, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3], const float mval[2],
+ float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth)
+{
+ float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
+ bool retval = false;
+ MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
+ MovieTracking *tracking;
+ float ray_start_local[3], ray_normal_local[3];
+
+ if (clip == NULL) {
+ return retval;
+ }
+ if (object->transflag & OB_DUPLI) {
+ return retval;
+ }
+
+ tracking = &clip->tracking;
+
+ BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
+
+ invert_m4_m4(orig_camera_imat, orig_camera_mat);
+ invert_m4_m4(imat, obmat);
+
+ switch (snap_mode) {
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ MovieTrackingObject *tracking_object;
+
+ for (tracking_object = tracking->objects.first;
+ tracking_object;
+ tracking_object = tracking_object->next)
+ {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+ MovieTrackingTrack *track;
+ float reconstructed_camera_mat[4][4],
+ reconstructed_camera_imat[4][4];
+ float (*vertex_obmat)[4];
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_normal);
+
+ if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+ BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
+ CFRA, reconstructed_camera_mat);
+
+ invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
+ }
+
+ for (track = tracksbase->first; track; track = track->next) {
+ float bundle_pos[3];
+
+ if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
+ continue;
+ }
+
+ copy_v3_v3(bundle_pos, track->bundle_pos);
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ mul_m4_v3(orig_camera_imat, ray_start_local);
+ mul_mat3_m4_v3(orig_camera_imat, ray_normal_local);
+ vertex_obmat = orig_camera_mat;
+ }
+ else {
+ mul_m4_v3(reconstructed_camera_imat, bundle_pos);
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+ vertex_obmat = obmat;
+ }
+
+ retval |= snapVertex(ar, bundle_pos, NULL, vertex_obmat, NULL,
+ ray_start, ray_start_local, ray_normal_local, mval,
+ r_loc, NULL, r_dist_px, r_depth);
+ }
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ return retval;
+}
+
static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, float obmat[4][4], bool use_obedit,
Object **r_ob, float r_obmat[4][4],
const float ray_start[3], const float ray_normal[3], const float mval[2],
@@ -1545,6 +1670,12 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f
else if (ob->type == OB_ARMATURE) {
retval = snapArmature(snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
}
+ else if (ob->type == OB_EMPTY) {
+ retval = snapEmpty(snap_mode, ar, ob, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
+ }
+ else if (ob->type == OB_CAMERA) {
+ retval = snapCamera(snap_mode, ar, scene, ob, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth);
+ }
if (retval) {
if (r_ob) {
diff --git a/source/blender/editors/util/crazyspace.c b/source/blender/editors/util/crazyspace.c
index bed8aaaddf2..ff65e11f53e 100644
--- a/source/blender/editors/util/crazyspace.c
+++ b/source/blender/editors/util/crazyspace.c
@@ -51,39 +51,46 @@
#include "ED_util.h"
typedef struct {
- float *vertexcos;
+ float (*vertexcos)[3];
BLI_bitmap *vertex_visit;
} MappedUserData;
-#define TAN_MAKE_VEC(a, b, c) a[0] = b[0] + 0.2f * (b[0] - c[0]); a[1] = b[1] + 0.2f * (b[1] - c[1]); a[2] = b[2] + 0.2f * (b[2] - c[2])
-static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
+BLI_INLINE void tan_calc_v3(float a[3], const float b[3], const float c[3])
{
- float vecu[3], vecv[3];
+ a[0] = b[0] + 0.2f * (b[0] - c[0]);
+ a[1] = b[1] + 0.2f * (b[1] - c[1]);
+ a[2] = b[2] + 0.2f * (b[2] - c[2]);
+}
+
+static void set_crazy_vertex_quat(
+ float r_quat[4],
+ const float co_1[3], const float co_2[3], const float co_3[3],
+ const float vd_1[3], const float vd_2[3], const float vd_3[3])
+{
+ float vec_u[3], vec_v[3];
float q1[4], q2[4];
- TAN_MAKE_VEC(vecu, v1, v2);
- TAN_MAKE_VEC(vecv, v1, v3);
- tri_to_quat(q1, v1, vecu, vecv);
+ tan_calc_v3(vec_u, co_1, co_2);
+ tan_calc_v3(vec_v, co_1, co_3);
+ tri_to_quat(q1, co_1, vec_u, vec_v);
- TAN_MAKE_VEC(vecu, def1, def2);
- TAN_MAKE_VEC(vecv, def1, def3);
- tri_to_quat(q2, def1, vecu, vecv);
+ tan_calc_v3(vec_u, vd_1, vd_2);
+ tan_calc_v3(vec_v, vd_1, vd_3);
+ tri_to_quat(q2, vd_1, vec_u, vec_v);
- sub_qt_qtqt(quat, q2, q1);
+ sub_qt_qtqt(r_quat, q2, q1);
}
-#undef TAN_MAKE_VEC
static void make_vertexcos__mapFunc(void *userData, int index, const float co[3],
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
MappedUserData *mappedData = (MappedUserData *)userData;
- float *vec = mappedData->vertexcos;
- vec += 3 * index;
if (BLI_BITMAP_GET(mappedData->vertex_visit, index) == 0) {
- /* we need coord from prototype vertex, not it clones or images,
- * suppose they stored in the beginning of vertex array stored in DM */
- copy_v3_v3(vec, co);
+ /* we need coord from prototype vertex, not from copies,
+ * assume they stored in the beginning of vertex array stored in DM
+ * (mirror modifier for eg does this) */
+ copy_v3_v3(mappedData->vertexcos[index], co);
BLI_BITMAP_SET(mappedData->vertex_visit, index);
}
}
@@ -104,11 +111,11 @@ static int modifiers_disable_subsurf_temporary(Object *ob)
}
/* disable subsurf temporal, get mapped cos, and enable it */
-float *crazyspace_get_mapped_editverts(Scene *scene, Object *obedit)
+float (*crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
{
Mesh *me = obedit->data;
DerivedMesh *dm;
- float *vertexcos;
+ float (*vertexcos)[3];
int nverts = me->edit_btmesh->bm->totvert;
BLI_bitmap *vertex_visit;
MappedUserData userData;
@@ -122,7 +129,7 @@ float *crazyspace_get_mapped_editverts(Scene *scene, Object *obedit)
/* now get the cage */
dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
- vertexcos = MEM_callocN(3 * sizeof(float) * nverts, "vertexcos map");
+ vertexcos = MEM_callocN(sizeof(*vertexcos) * nverts, "vertexcos map");
vertex_visit = BLI_BITMAP_NEW(nverts, "vertexcos flags");
userData.vertexcos = vertexcos;
@@ -139,65 +146,69 @@ float *crazyspace_get_mapped_editverts(Scene *scene, Object *obedit)
return vertexcos;
}
-void crazyspace_set_quats_editmesh(BMEditMesh *em, float *origcos, float *mappedcos, float *quats)
+void crazyspace_set_quats_editmesh(BMEditMesh *em, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4])
{
- BMVert *v;
- BMIter iter, liter;
- BMLoop *l;
- float *v1, *v2, *v3, *co1, *co2, *co3;
- int *vert_table = MEM_callocN(sizeof(int) * em->bm->totvert, "vert_table");
- int index = 0;
-
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
-
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_SELECT) || BM_elem_flag_test(v, BM_ELEM_HIDDEN))
- continue;
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- BMLoop *l2 = BM_loop_other_edge_loop(l, v);
-
- /* retrieve mapped coordinates */
- v1 = mappedcos + 3 * BM_elem_index_get(l->v);
- v2 = mappedcos + 3 * BM_elem_index_get(BM_edge_other_vert(l2->e, l->v));
- v3 = mappedcos + 3 * BM_elem_index_get(BM_edge_other_vert(l->e, l->v));
-
- co1 = (origcos) ? origcos + 3 * BM_elem_index_get(l->v) : l->v->co;
- co2 = (origcos) ? origcos + 3 * BM_elem_index_get(BM_edge_other_vert(l2->e, l->v)) : BM_edge_other_vert(l2->e, l->v)->co;
- co3 = (origcos) ? origcos + 3 * BM_elem_index_get(BM_edge_other_vert(l->e, l->v)) : BM_edge_other_vert(l->e, l->v)->co;
-
- set_crazy_vertex_quat(quats, v1, v2, v3, co1, co2, co3);
- quats += 4;
-
- vert_table[BM_elem_index_get(l->v)] = index + 1;
-
- index++;
- break; /*just do one corner*/
+ BMFace *f;
+ BMIter iter;
+ int index;
+
+ {
+ BMVert *v;
+ BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, index) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ BM_elem_index_set(v, index); /* set_inline */
}
+ em->bm->elem_index_dirty &= ~BM_VERT;
}
- index = 0;
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (vert_table[index] != 0)
- BM_elem_index_set(v, vert_table[index] - 1); /* set_dirty! */
- else
- BM_elem_index_set(v, -1); /* set_dirty! */
-
- index++;
+ BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT) || BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN))
+ continue;
+
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
+ const float *co_prev, *co_curr, *co_next; /* orig */
+ const float *vd_prev, *vd_curr, *vd_next; /* deform */
+
+ const int i_prev = BM_elem_index_get(l_iter->prev->v);
+ const int i_curr = BM_elem_index_get(l_iter->v);
+ const int i_next = BM_elem_index_get(l_iter->next->v);
+
+ /* retrieve mapped coordinates */
+ vd_prev = mappedcos[i_prev];
+ vd_curr = mappedcos[i_curr];
+ vd_next = mappedcos[i_next];
+
+ if (origcos) {
+ co_prev = origcos[i_prev];
+ co_curr = origcos[i_curr];
+ co_next = origcos[i_next];
+ }
+ else {
+ co_prev = l_iter->prev->v->co;
+ co_curr = l_iter->v->co;
+ co_next = l_iter->next->v->co;
+ }
+
+ set_crazy_vertex_quat(quats[i_curr],
+ co_curr, co_next, co_prev,
+ vd_curr, vd_next, vd_prev);
+
+ BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
}
- em->bm->elem_index_dirty |= BM_VERT;
-
- MEM_freeN(vert_table);
}
-/* BMESH_TODO - use MPolys over MFace's */
-
-void crazyspace_set_quats_mesh(Mesh *me, float *origcos, float *mappedcos, float *quats)
+void crazyspace_set_quats_mesh(Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4])
{
int i;
MVert *mvert;
- MFace *mface;
- float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
+ MLoop *mloop;
+ MPoly *mp;
mvert = me->mvert;
for (i = 0; i < me->totvert; i++, mvert++)
@@ -205,49 +216,48 @@ void crazyspace_set_quats_mesh(Mesh *me, float *origcos, float *mappedcos, float
/* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
mvert = me->mvert;
- mface = me->mface;
- for (i = 0; i < me->totface; i++, mface++) {
-
- /* retrieve mapped coordinates */
- v1 = mappedcos + 3 * mface->v1;
- v2 = mappedcos + 3 * mface->v2;
- v3 = mappedcos + 3 * mface->v3;
-
- co1 = (origcos) ? origcos + 3 * mface->v1 : mvert[mface->v1].co;
- co2 = (origcos) ? origcos + 3 * mface->v2 : mvert[mface->v2].co;
- co3 = (origcos) ? origcos + 3 * mface->v3 : mvert[mface->v3].co;
-
- if ((mvert[mface->v2].flag & ME_VERT_TMP_TAG) == 0) {
- set_crazy_vertex_quat(&quats[mface->v2 * 4], co2, co3, co1, v2, v3, v1);
- mvert[mface->v2].flag |= ME_VERT_TMP_TAG;
- }
-
- if (mface->v4) {
- v4 = mappedcos + 3 * mface->v4;
- co4 = (origcos) ? origcos + 3 * mface->v4 : mvert[mface->v4].co;
-
- if ((mvert[mface->v1].flag & ME_VERT_TMP_TAG) == 0) {
- set_crazy_vertex_quat(&quats[mface->v1 * 4], co1, co2, co4, v1, v2, v4);
- mvert[mface->v1].flag |= ME_VERT_TMP_TAG;
- }
- if ((mvert[mface->v3].flag & ME_VERT_TMP_TAG) == 0) {
- set_crazy_vertex_quat(&quats[mface->v3 * 4], co3, co4, co2, v3, v4, v2);
- mvert[mface->v3].flag |= ME_VERT_TMP_TAG;
- }
- if ((mvert[mface->v4].flag & ME_VERT_TMP_TAG) == 0) {
- set_crazy_vertex_quat(&quats[mface->v4 * 4], co4, co1, co3, v4, v1, v3);
- mvert[mface->v4].flag |= ME_VERT_TMP_TAG;
- }
- }
- else {
- if ((mvert[mface->v1].flag & ME_VERT_TMP_TAG) == 0) {
- set_crazy_vertex_quat(&quats[mface->v1 * 4], co1, co2, co3, v1, v2, v3);
- mvert[mface->v1].flag |= ME_VERT_TMP_TAG;
- }
- if ((mvert[mface->v3].flag & ME_VERT_TMP_TAG) == 0) {
- set_crazy_vertex_quat(&quats[mface->v3 * 4], co3, co1, co2, v3, v1, v2);
- mvert[mface->v3].flag |= ME_VERT_TMP_TAG;
+ mp = me->mpoly;
+ mloop = me->mloop;
+
+ for (i = 0; i < me->totpoly; i++, mp++) {
+ MLoop *ml_prev, *ml_curr, *ml_next;
+ int j;
+
+ ml_next = &mloop[mp->loopstart];
+ ml_curr = &ml_next[mp->totloop - 1];
+ ml_prev = &ml_next[mp->totloop - 2];
+
+ for (j = 0; j < mp->totloop; j++) {
+ if ((mvert[ml_curr->v].flag & ME_VERT_TMP_TAG) == 0) {
+ const float *co_prev, *co_curr, *co_next; /* orig */
+ const float *vd_prev, *vd_curr, *vd_next; /* deform */
+
+ /* retrieve mapped coordinates */
+ vd_prev = mappedcos[ml_prev->v];
+ vd_curr = mappedcos[ml_curr->v];
+ vd_next = mappedcos[ml_next->v];
+
+ if (origcos) {
+ co_prev = origcos[ml_prev->v];
+ co_curr = origcos[ml_curr->v];
+ co_next = origcos[ml_next->v];
+ }
+ else {
+ co_prev = mvert[ml_prev->v].co;
+ co_curr = mvert[ml_curr->v].co;
+ co_next = mvert[ml_next->v].co;
+ }
+
+ set_crazy_vertex_quat(quats[ml_curr->v],
+ co_curr, co_next, co_prev,
+ vd_curr, vd_next, vd_prev);
+
+ mvert[ml_curr->v].flag |= ME_VERT_TMP_TAG;
}
+
+ ml_prev = ml_curr;
+ ml_curr = ml_next;
+ ml_next++;
}
}
}
@@ -260,11 +270,12 @@ int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em
int i, a, numleft = 0, numVerts = 0;
int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
+ VirtualModifierData virtualModifierData;
modifiers_clearErrors(ob);
dm = NULL;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
/* compute the deformation matrices and coordinates for the first
* modifiers with on cage editing that are enabled and support computing
@@ -314,6 +325,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
int has_multires = mmd != NULL && mmd->sculptlvl > 0;
int numleft = 0;
+ VirtualModifierData virtualModifierData;
if (has_multires) {
*deformmats = NULL;
@@ -322,7 +334,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
}
dm = NULL;
- md = modifiers_getVirtualModifierList(ob);
+ md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
for (; md; md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -373,9 +385,10 @@ void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3
float (*deformedVerts)[3] = *deformcos;
float (*origVerts)[3] = MEM_dupallocN(deformedVerts);
- float *quats = NULL;
+ float (*quats)[4];
int i, deformed = 0;
- ModifierData *md = modifiers_getVirtualModifierList(ob);
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
Mesh *me = (Mesh *)ob->data;
for (; md; md = md->next) {
@@ -394,14 +407,14 @@ void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3
}
}
- quats = MEM_mallocN(me->totvert * sizeof(float) * 4, "crazy quats");
+ quats = MEM_mallocN(me->totvert * sizeof(*quats), "crazy quats");
- crazyspace_set_quats_mesh(me, (float *)origVerts, (float *)deformedVerts, quats);
+ crazyspace_set_quats_mesh(me, origVerts, deformedVerts, quats);
for (i = 0; i < me->totvert; i++) {
float qmat[3][3], tmat[3][3];
- quat_to_mat3(qmat, &quats[i * 4]);
+ quat_to_mat3(qmat, quats[i]);
mul_m3_m3m3(tmat, qmat, (*deformmats)[i]);
copy_m3_m3((*deformmats)[i], tmat);
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index a873702b5b8..d20ef0e70e0 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -69,7 +69,7 @@
#define USE_EDBM_LOOPTRIS
-void draw_image_cursor(SpaceImage *sima, ARegion *ar)
+void draw_image_cursor(ARegion *ar, const float cursor[2])
{
float zoom[2], x_fac, y_fac;
@@ -80,7 +80,7 @@ void draw_image_cursor(SpaceImage *sima, ARegion *ar)
y_fac = zoom[1];
cpack(0xFFFFFF);
- glTranslatef(sima->cursor[0], sima->cursor[1], 0.0);
+ glTranslatef(cursor[0], cursor[1], 0.0);
fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac);
fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
@@ -108,7 +108,7 @@ void draw_image_cursor(SpaceImage *sima, ARegion *ar)
fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
- glTranslatef(-sima->cursor[0], -sima->cursor[1], 0.0);
+ glTranslatef(-cursor[0], -cursor[1], 0.0);
setlinestyle(0);
}
@@ -158,7 +158,7 @@ static int draw_uvs_dm_shadow(DerivedMesh *dm)
/* draw shadow mesh - this is the mesh with the modifier applied */
if (dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
- glColor3ub(112, 112, 112);
+ UI_ThemeColor(TH_UV_SHADOW);
dm->drawUVEdges(dm);
return 1;
}
@@ -362,7 +362,7 @@ static void draw_uvs_other(Scene *scene, Object *obedit, Image *curimage)
{
Base *base;
- glColor3ub(96, 96, 96);
+ UI_ThemeColor(TH_UV_OTHERS);
for (base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
@@ -404,7 +404,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
if (sima->flag & SI_DRAW_OTHER)
draw_uvs_other(scene, ob, curimage);
- glColor3ub(112, 112, 112);
+ UI_ThemeColor(TH_UV_SHADOW);
if (me->mtpoly) {
MPoly *mpoly = me->mpoly;
@@ -884,7 +884,7 @@ void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedi
draw_uvs_texpaint(sima, scene, obact);
if (show_uvedit && !(toolsettings->use_uv_sculpt))
- draw_image_cursor(sima, ar);
+ draw_image_cursor(ar, sima->cursor);
}
}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 0b514e3f6fd..8c299cccbc2 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -3823,6 +3823,12 @@ static void UV_OT_reveal(wmOperatorType *ot)
/******************** set 3d cursor operator ********************/
+static int uv_set_2d_cursor_poll(bContext *C)
+{
+ return ED_operator_uvedit_space_image(C) ||
+ ED_space_image_maskedit_poll(C);
+}
+
static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -3858,7 +3864,7 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
/* api callbacks */
ot->exec = uv_set_2d_cursor_exec;
ot->invoke = uv_set_2d_cursor_invoke;
- ot->poll = ED_operator_uvedit_space_image;
+ ot->poll = uv_set_2d_cursor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 7851eebe269..b8a54c56c63 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -33,6 +33,7 @@
#include "BLI_rand.h"
#include "BLI_heap.h"
#include "BLI_boxpack2d.h"
+#include "BLI_convexhull2d.h"
#include "ONL_opennl.h"
@@ -485,6 +486,36 @@ static void p_chart_uv_translate(PChart *chart, float trans[2])
}
}
+static void p_chart_uv_transform(PChart *chart, float mat[2][2])
+{
+ PVert *v;
+
+ for (v = chart->verts; v; v = v->nextlink) {
+ mul_v2_m2v2(v->uv, mat, v->uv);
+ }
+}
+
+static void p_chart_uv_to_array(PChart *chart, float (*points)[2])
+{
+ PVert *v;
+ unsigned int i = 0;
+
+ for (v = chart->verts; v; v = v->nextlink) {
+ copy_v2_v2(points[i++], v->uv);
+ }
+}
+
+static void UNUSED_FUNCTION(p_chart_uv_from_array)(PChart *chart, float (*points)[2])
+{
+ PVert *v;
+ unsigned int i = 0;
+
+ for (v = chart->verts; v; v = v->nextlink) {
+ copy_v2_v2(v->uv, points[i++]);
+ }
+}
+
+
static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *dir2, float *isect)
{
float lmbda, div;
@@ -4441,8 +4472,42 @@ void param_smooth_area(ParamHandle *handle)
p_smooth(chart);
}
}
-
-void param_pack(ParamHandle *handle, float margin)
+
+/* don't pack, just rotate (used for better packing) */
+static void param_pack_rotate(ParamHandle *handle)
+{
+ PChart *chart;
+ int i;
+
+ PHandle *phandle = (PHandle *)handle;
+
+ for (i = 0; i < phandle->ncharts; i++) {
+ float (*points)[2];
+ float angle;
+
+ chart = phandle->charts[i];
+
+ if (chart->flag & PCHART_NOPACK) {
+ continue;
+ }
+
+ points = MEM_mallocN(sizeof(*points) * chart->nverts, __func__);
+
+ p_chart_uv_to_array(chart, points);
+
+ angle = BLI_convexhull_aabb_fit_points_2d((const float (*)[2])points, chart->nverts);
+
+ MEM_freeN(points);
+
+ if (angle != 0.0f) {
+ float mat[2][2];
+ angle_to_mat2(mat, angle);
+ p_chart_uv_transform(chart, mat);
+ }
+ }
+}
+
+void param_pack(ParamHandle *handle, float margin, bool do_rotate)
{
/* box packing variables */
BoxPack *boxarray, *box;
@@ -4461,6 +4526,11 @@ void param_pack(ParamHandle *handle, float margin)
if (phandle->aspx != phandle->aspy)
param_scale(handle, 1.0f / phandle->aspx, 1.0f / phandle->aspy);
+ /* this could be its own function */
+ if (do_rotate) {
+ param_pack_rotate(handle);
+ }
+
/* we may not use all these boxes */
boxarray = MEM_mallocN(phandle->ncharts * sizeof(BoxPack), "BoxPack box");
@@ -4513,7 +4583,7 @@ void param_pack(ParamHandle *handle, float margin)
}
}
- BLI_box_pack_2D(boxarray, phandle->ncharts - unpacked, &tot_width, &tot_height);
+ BLI_box_pack_2d(boxarray, phandle->ncharts - unpacked, &tot_width, &tot_height);
if (tot_height > tot_width)
scale = 1.0f / tot_height;
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
index 7127a436570..265577555a6 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -99,7 +99,7 @@ void param_smooth_area(ParamHandle *handle);
/* Packing */
-void param_pack(ParamHandle *handle, float margin);
+void param_pack(ParamHandle *handle, float margin, bool do_rotate);
/* Average area for all charts */
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 3318ae72624..f788c6a772c 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -1718,6 +1718,7 @@ static int stitch_init(bContext *C, wmOperator *op)
UvElement *element = ED_uv_element_get(state->element_map, efa, l);
int offset1, itmp1 = element - state->element_map->buf;
int offset2, itmp2 = ED_uv_element_get(state->element_map, efa, l->next) - state->element_map->buf;
+ UvEdge *edge;
offset1 = map[itmp1];
offset2 = map[itmp2];
@@ -1737,8 +1738,8 @@ static int stitch_init(bContext *C, wmOperator *op)
all_edges[counter].uv2 = offset1;
}
- if (BLI_ghash_haskey(edge_hash, &all_edges[counter])) {
- UvEdge *edge = BLI_ghash_lookup(edge_hash, &all_edges[counter]);
+ edge = BLI_ghash_lookup(edge_hash, &all_edges[counter]);
+ if (edge) {
edge->flag = 0;
}
else {
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 49505b03a19..87cc42001d6 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -718,6 +718,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
ParamHandle *handle;
bool implicit = true;
+ bool do_rotate = RNA_boolean_get(op->ptr, "rotate");
if (!uvedit_have_selection(scene, em, implicit)) {
return OPERATOR_CANCELLED;
@@ -729,7 +730,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1);
- param_pack(handle, scene->toolsettings->uvcalc_margin);
+ param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate);
param_flush(handle);
param_delete(handle);
@@ -753,6 +754,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
ot->poll = ED_operator_uvedit;
/* properties */
+ RNA_def_boolean(ot->srna, "rotate", true, "Rotate", "Rotate islands for best fit");
RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
@@ -1151,7 +1153,7 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
param_lscm_end(handle);
param_average(handle);
- param_pack(handle, scene->toolsettings->uvcalc_margin);
+ param_pack(handle, scene->toolsettings->uvcalc_margin, false);
param_flush(handle);
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
index dbf3fa8349e..c61f72295d2 100644
--- a/source/blender/freestyle/intern/application/Controller.cpp
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -290,6 +290,8 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
_ListOfModels.push_back("Blender_models");
+ _Scene3dBBox = _RootNode->bbox();
+
_bboxDiag = (_RootNode->bbox().getMax() - _RootNode->bbox().getMin()).norm();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Triangles nb : " << _SceneNumFaces << endl;
@@ -339,6 +341,7 @@ void Controller::DeleteWingedEdge()
// clears the grid
_Grid.clear();
+ _Scene3dBBox.clear();
_SceneNumFaces = 0;
_minEdgeSize = DBL_MAX;
}
@@ -540,8 +543,8 @@ void Controller::ComputeViewMap()
}
_Chrono.start();
// Build View Map
- _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _RootNode->bbox(), _SceneNumFaces);
- _ViewMap->setScene3dBBox(_RootNode->bbox());
+ _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _Scene3dBBox, _SceneNumFaces);
+ _ViewMap->setScene3dBBox(_Scene3dBBox);
if (G.debug & G_DEBUG_FREESTYLE) {
printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size());
diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h
index d4537f5f987..f5e50347d0f 100644
--- a/source/blender/freestyle/intern/application/Controller.h
+++ b/source/blender/freestyle/intern/application/Controller.h
@@ -211,6 +211,7 @@ private:
FastGrid _Grid;
//HashGrid _Grid;
+ BBox<Vec3r> _Scene3dBBox;
unsigned int _SceneNumFaces;
real _minEdgeSize;
real _EPSILON;
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index 8cb44d05b84..7dc218c74df 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -369,7 +369,7 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl)
if (lineset->flags & FREESTYLE_LINESET_ENABLED) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << " " << layer_count+1 << ": " << lineset->name << " - " <<
- lineset->linestyle->id.name + 2 << endl;
+ (lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl;
}
Text *text = create_lineset_handler(bmain, srl->name, lineset->name);
controller->InsertStyleModule(layer_count, lineset->name, text);
@@ -680,9 +680,11 @@ void FRS_paste_active_lineset(FreestyleConfig *config)
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
if (lineset) {
- lineset->linestyle->id.us--;
+ if (lineset->linestyle)
+ lineset->linestyle->id.us--;
lineset->linestyle = lineset_buffer.linestyle;
- lineset->linestyle->id.us++;
+ if (lineset->linestyle)
+ lineset->linestyle->id.us++;
lineset->flags = lineset_buffer.flags;
lineset->selection = lineset_buffer.selection;
lineset->qi = lineset_buffer.qi;
@@ -711,10 +713,10 @@ void FRS_delete_active_lineset(FreestyleConfig *config)
if (lineset) {
if (lineset->group) {
lineset->group->id.us--;
- lineset->group = NULL;
}
- lineset->linestyle->id.us--;
- lineset->linestyle = NULL;
+ if (lineset->linestyle) {
+ lineset->linestyle->id.us--;
+ }
BLI_remlink(&config->linesets, lineset);
MEM_freeN(lineset);
BKE_freestyle_lineset_set_active_index(config, 0);
diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h
index 794ceba48e7..c557c2a6368 100644
--- a/source/blender/freestyle/intern/geometry/BBox.h
+++ b/source/blender/freestyle/intern/geometry/BBox.h
@@ -28,6 +28,10 @@
* \date 22/05/2003
*/
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
#endif
@@ -95,6 +99,7 @@ public:
inline BBox<Point>& operator=(const BBox<Point>& b)
{
+ BLI_assert(!b.empty());
_min = b.getMin();
_max = b.getMax();
_empty = false;
@@ -103,6 +108,7 @@ public:
inline BBox<Point>& operator+=(const BBox<Point>& b)
{
+ BLI_assert(!b.empty());
if (_empty) {
_min = b.getMin();
_max = b.getMax();
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
index 9b915df03d1..869ada0d058 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
@@ -44,7 +44,7 @@ PyDoc_STRVAR(ViewEdge_doc,
"Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n"
"\n"
"Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n"
-"it connnects two :class:`ViewVertex` objects. It is made by connecting\n"
+"it connects two :class:`ViewVertex` objects. It is made by connecting\n"
"a set of FEdges.\n"
"\n"
".. method:: __init__()\n"
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
index 18815ab6f62..b54ed48edc3 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
@@ -48,7 +48,7 @@ static char MaterialF0D___doc__[] =
" evaluation can be ambiguous (in the case of a :class:`TVertex` for\n"
" example. This functor tries to remove this ambiguity using the\n"
" context offered by the 1D element to which the Interface0DIterator\n"
-" belongs to and by arbitrary chosing the material of the face that\n"
+" belongs to and by arbitrary choosing the material of the face that\n"
" lies on its left when following the 1D element if there are two\n"
" different materials on each side of the point. However, there\n"
" still can be problematic cases, and the user willing to deal with\n"
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
index 8f7fccb5293..b64f6c06e93 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
@@ -47,7 +47,7 @@ static char ZDiscontinuityF0D___doc__[] =
" :class:`Interface0D` pointed by the Interface0DIterator and the\n"
" shape that lies behind (occludee). This distance is evaluated in\n"
" the camera space and normalized between 0 and 1. Therefore, if no\n"
-" oject is occluded by the shape to which the Interface0D belongs to,\n"
+" object is occluded by the shape to which the Interface0D belongs to,\n"
" 1 is returned.\n"
"\n"
" :arg it: An Interface0DIterator object.\n"
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
index 5c3dc3eed9f..65fde596e23 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
@@ -52,7 +52,7 @@ static char ZDiscontinuityF1D___doc__[] =
" Returns a real value giving the distance between an Interface1D\n"
" and the shape that lies behind (occludee). This distance is\n"
" evaluated in the camera space and normalized between 0 and 1.\n"
-" Therefore, if no oject is occluded by the shape to which the\n"
+" Therefore, if no object is occluded by the shape to which the\n"
" Interface1D belongs to, 1 is returned.\n"
"\n"
" :arg inter: An Interface1D object.\n"
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
index 2615df0a124..fb6da853e02 100644
--- a/source/blender/freestyle/intern/stroke/StrokeRep.cpp
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
@@ -149,7 +149,8 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
if (dp < 0)
userDir = userDir * (-1.0f);
stripDir = userDir;
- } else {
+ }
+ else {
++orientationErrors;
}
}
@@ -207,7 +208,8 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
if (dp < 0)
userDir = userDir * (-1.0f);
stripDir = userDir;
- } else {
+ }
+ else {
++orientationErrors;
}
}
@@ -226,7 +228,8 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
if (dp < 0)
userDir = userDir * (-1.0f);
stripDirPrev = userDir;
- } else {
+ }
+ else {
++orientationErrors;
}
}
@@ -302,7 +305,8 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
if (dp < 0)
userDir = userDir * (-1.0f);
stripDirLast = userDir;
- } else {
+ }
+ else {
++orientationErrors;
}
}
diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h
index 7986a08e303..4657e98be61 100644
--- a/source/blender/freestyle/intern/stroke/StrokeShader.h
+++ b/source/blender/freestyle/intern/stroke/StrokeShader.h
@@ -63,7 +63,7 @@ class Stroke;
* \endcode
* Here is a C++ code example of such an iteration:
* \code
- * for(StrokeInternal::StrokeVertexIterator v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd();
+ * for (StrokeInternal::StrokeVertexIterator v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd();
* v != vend;
* ++v)
* {
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
index 9d7cb051fdf..ecfb4d4fa25 100644
--- a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
@@ -1,23 +1,22 @@
-
-//
-// Copyright (C) : Please refer to the COPYRIGHT file distributed
-// with this source distribution.
-//
-// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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 *****
+ */
# include "TextStrokeRenderer.h"
# include "Canvas.h"
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
index cd56f9d54e3..42402f318ef 100644
--- a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
@@ -1,3 +1,27 @@
+/*
+ * ***** 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/freestyle/intern/stroke/TextStrokeRenderer.h
+ * \ingroup freestyle
+ */
+
//
// Filename : TextStrokeRenderer.h
// Author(s) : Stephane Grabli
@@ -11,29 +35,8 @@
//
///////////////////////////////////////////////////////////////////////////////
-
-//
-// Copyright (C) : Please refer to the COPYRIGHT file distributed
-// with this source distribution.
-//
-// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef TEXTSTROKERENDERER_H
-# define TEXTSTROKERENDERER_H
+#ifndef TEXTSTROKERENDERER_H
+#define TEXTSTROKERENDERER_H
# include "StrokeRenderer.h"
# include "../system/FreestyleConfig.h"
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h
index 69f6f42e022..e9474191319 100644
--- a/source/blender/freestyle/intern/view_map/Functions0D.h
+++ b/source/blender/freestyle/intern/view_map/Functions0D.h
@@ -346,7 +346,7 @@ public:
// ZDiscontinuity
/*! Returns a real giving the distance between and Interface0D and the shape that lies behind (occludee).
- * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded
+ * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no object is occluded
* by the shape to which the Interface0D belongs to, 1 is returned.
*/
class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D<real>
@@ -383,7 +383,7 @@ public:
/*! Returns the material of the object evaluated at the Interface0D.
* This evaluation can be ambiguous (in the case of a TVertex for example.
* This functor tries to remove this ambiguity using the context offered by the 1D element to which the
- * Interface0DIterator& belongs to and by arbitrary chosing the material of the face that lies on its left when
+ * Interface0DIterator& belongs to and by arbitrary choosing the material of the face that lies on its left when
* following the 1D element if there are two different materials on each side of the point.
* However, there still can be problematic cases, and the user willing to deal with this cases in a specific way
* should implement its own getMaterial functor.
diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h
index 2d3da151d13..7b10d1b5185 100644
--- a/source/blender/freestyle/intern/view_map/Functions1D.h
+++ b/source/blender/freestyle/intern/view_map/Functions1D.h
@@ -377,7 +377,7 @@ public:
// ZDiscontinuityF1D
/*! Returns a real giving the distance between and Interface1D and the shape that lies behind (occludee).
- * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded
+ * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no object is occluded
* by the shape to which the Interface1D belongs to, 1 is returned.
*/
class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D<real>
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
index 23681b43c48..581155fa6e8 100644
--- a/source/blender/freestyle/intern/view_map/SteerableViewMap.h
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
@@ -89,7 +89,7 @@ public:
/*! Returns the number of the SVM to which a FEdge belongs most.
* \param id
- * The First element of the Id struct of the FEdge we're intersted in.
+ * The First element of the Id struct of the FEdge we're interested in.
*/
unsigned getSVMNumber(unsigned id);
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h
index 987a5bda9b3..0ab089b7d7a 100644
--- a/source/blender/freestyle/intern/view_map/ViewMap.h
+++ b/source/blender/freestyle/intern/view_map/ViewMap.h
@@ -888,7 +888,7 @@ template<class Traits> class vertex_iterator_base;
} // end of namespace ViewEdgeInternal
-/*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connnects two ViewVertex.
+/*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connects two ViewVertex.
* It is made by connecting a set of FEdges.
*/
class LIB_VIEW_MAP_EXPORT ViewEdge : public Interface1D
diff --git a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
index 01e93ba77c7..a8c046c4dc1 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
+++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
@@ -232,7 +232,7 @@ public:
// operator corresponding to i++, i.e. which returns the value *and then* increments it.
// That's why we store the value in a temp.
- virtual Self operator++(int) // opérateur correspondant à i++
+ virtual Self operator++(int)
{
Self tmp = *this;
increment();
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
index 81b0f5f8934..702ee9bfea2 100644
--- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -595,7 +595,7 @@ static void computeCumulativeVisibility(ViewMap *ioViewMap, G& grid, real epsilo
wFaces.clear();
}
- if (iRenderMonitor) {
+ if (iRenderMonitor && vedges.size()) {
stringstream ss;
ss << "Freestyle: Visibility computations " << (100 * cnt / vedges.size()) << "%";
iRenderMonitor->setInfo(ss.str());
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index fca8dcc3392..cc22063a83c 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -46,6 +46,7 @@ struct CustomData;
struct DMFlagMat;
struct DerivedMesh;
struct GHash;
+struct GSet;
struct GPUVertPointLink;
struct PBVH;
@@ -175,10 +176,10 @@ GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid,
GPU_Buffers *GPU_build_bmesh_buffers(int smooth_shading);
void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
- struct BMesh *bm,
- struct GHash *bm_faces,
- struct GHash *bm_unique_verts,
- struct GHash *bm_other_verts);
+ struct BMesh *bm,
+ struct GHash *bm_faces,
+ struct GSet *bm_unique_verts,
+ struct GSet *bm_other_verts);
void GPU_update_grid_buffers(GPU_Buffers *buffers, struct CCGElem **grids,
const struct DMFlagMat *grid_flag_mats,
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 8dd28601d34..1db424b514d 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -61,6 +61,7 @@ int GPU_print_error(const char *str);
int GPU_glsl_support(void);
int GPU_non_power_of_two_support(void);
+int GPU_display_list_support(void);
int GPU_color_depth(void);
void GPU_code_generate_glsl_lib(void);
int GPU_bicubic_bump_support(void);
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index c54f937f4a9..384b7cce2ff 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -77,6 +77,8 @@ static int useVBOs = -1;
static GPUBufferState GLStates = 0;
static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
+static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
+
/* stores recently-deleted buffers so that new buffers won't have to
* be recreated as often
*
@@ -203,8 +205,11 @@ void GPU_global_buffer_pool_free_unused(void)
}
/* get a GPUBuffer of at least `size' bytes; uses one from the buffer
- * pool if possible, otherwise creates a new one */
-GPUBuffer *GPU_buffer_alloc(int size)
+ * pool if possible, otherwise creates a new one
+ *
+ * Thread-unsafe version for internal usage only.
+ */
+static GPUBuffer *gpu_buffer_alloc_intern(int size)
{
GPUBufferPool *pool;
GPUBuffer *buf;
@@ -284,10 +289,30 @@ GPUBuffer *GPU_buffer_alloc(int size)
return buf;
}
+/* Same as above, but safe for threading. */
+GPUBuffer *GPU_buffer_alloc(int size)
+{
+ GPUBuffer *buffer;
+
+ if (size == 0) {
+ /* Early out, no lock needed in this case. */
+ return NULL;
+ }
+
+ BLI_mutex_lock(&buffer_mutex);
+ buffer = gpu_buffer_alloc_intern(size);
+ BLI_mutex_unlock(&buffer_mutex);
+
+ return buffer;
+}
+
/* release a GPUBuffer; does not free the actual buffer or its data,
* but rather moves it to the pool of recently-freed buffers for
- * possible re-use*/
-void GPU_buffer_free(GPUBuffer *buffer)
+ * possible re-use
+ *
+ * Thread-unsafe version for internal usage only.
+ */
+static void gpu_buffer_free_intern(GPUBuffer *buffer)
{
GPUBufferPool *pool;
int i;
@@ -326,6 +351,19 @@ void GPU_buffer_free(GPUBuffer *buffer)
pool->totbuf++;
}
+/* Same as above, but safe for threading. */
+void GPU_buffer_free(GPUBuffer *buffer)
+{
+ if (!buffer) {
+ /* Early output, no need to lock in this case, */
+ return;
+ }
+
+ BLI_mutex_lock(&buffer_mutex);
+ gpu_buffer_free_intern(buffer);
+ BLI_mutex_unlock(&buffer_mutex);
+}
+
typedef struct GPUVertPointLink {
struct GPUVertPointLink *next;
/* -1 means uninitialized */
@@ -510,13 +548,17 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
pool = gpu_get_global_buffer_pool();
+ BLI_mutex_lock(&buffer_mutex);
+
/* alloc a GPUBuffer; fall back to legacy mode on failure */
- if (!(buffer = GPU_buffer_alloc(size)))
+ if (!(buffer = gpu_buffer_alloc_intern(size)))
dm->drawObject->legacy = 1;
/* nothing to do for legacy mode */
- if (dm->drawObject->legacy)
+ if (dm->drawObject->legacy) {
+ BLI_mutex_unlock(&buffer_mutex);
return NULL;
+ }
cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial,
"GPU_buffer_setup.cur_index_per_mat");
@@ -541,7 +583,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
/* attempt to map the buffer */
if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
/* failed to map the buffer; delete it */
- GPU_buffer_free(buffer);
+ gpu_buffer_free_intern(buffer);
gpu_buffer_pool_delete_last(pool);
buffer = NULL;
@@ -549,7 +591,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
* and reallocating the buffer */
if (pool->totbuf > 0) {
gpu_buffer_pool_delete_last(pool);
- buffer = GPU_buffer_alloc(size);
+ buffer = gpu_buffer_alloc_intern(size);
}
/* allocation still failed; fall back
@@ -591,6 +633,8 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
MEM_freeN(cur_index_per_mat);
+ BLI_mutex_unlock(&buffer_mutex);
+
return buffer;
}
@@ -1911,6 +1955,7 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
/* Assign index for use in the triangle index buffer */
+ /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */
BM_elem_index_set(v, (*v_index)); /* set_dirty! */
(*v_index)++;
@@ -1918,19 +1963,19 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
}
/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
-static int gpu_bmesh_vert_visible_count(GHash *bm_unique_verts,
- GHash *bm_other_verts)
+static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts,
+ GSet *bm_other_verts)
{
- GHashIterator gh_iter;
+ GSetIterator gs_iter;
int totvert = 0;
- GHASH_ITER (gh_iter, bm_unique_verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, bm_unique_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
totvert++;
}
- GHASH_ITER (gh_iter, bm_other_verts) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ GSET_ITER (gs_iter, bm_other_verts) {
+ BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
totvert++;
}
@@ -1957,10 +2002,10 @@ static int gpu_bmesh_face_visible_count(GHash *bm_faces)
/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
* shading, an element index buffer. */
void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
- BMesh *bm,
- GHash *bm_faces,
- GHash *bm_unique_verts,
- GHash *bm_other_verts)
+ BMesh *bm,
+ GHash *bm_faces,
+ GSet *bm_unique_verts,
+ GSet *bm_other_verts)
{
VertexBufferFormat *vert_data;
void *tri_data;
@@ -1991,22 +2036,23 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
/* Fill vertex buffer */
vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
if (vert_data) {
- GHashIterator gh_iter;
int v_index = 0;
if (buffers->smooth) {
+ GSetIterator gs_iter;
+
/* Vertices get an index assigned for use in the triangle
* index buffer */
bm->elem_index_dirty |= BM_VERT;
- GHASH_ITER (gh_iter, bm_unique_verts) {
- gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter),
+ GSET_ITER (gs_iter, bm_unique_verts) {
+ gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
vert_data, &v_index, NULL, NULL,
cd_vert_mask_offset);
}
- GHASH_ITER (gh_iter, bm_other_verts) {
- gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter),
+ GSET_ITER (gs_iter, bm_other_verts) {
+ gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
vert_data, &v_index, NULL, NULL,
cd_vert_mask_offset);
}
@@ -2014,6 +2060,8 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
maxvert = v_index;
}
else {
+ GHashIterator gh_iter;
+
GHASH_ITER (gh_iter, bm_faces) {
BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
@@ -2045,6 +2093,9 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+
+ /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
+ bm->elem_index_dirty |= BM_VERT;
}
else {
/* Memory map failed */
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index e244c7cf57f..d7919125fee 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -1039,9 +1039,7 @@ static void GPU_nodes_free(ListBase *nodes)
{
GPUNode *node;
- while (nodes->first) {
- node = nodes->first;
- BLI_remlink(nodes, node);
+ while ((node = BLI_pophead(nodes))) {
GPU_node_free(node);
}
}
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index e9f9d4a3379..0d25d988df9 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -1216,7 +1216,7 @@ static LinkNode *image_free_queue = NULL;
static void gpu_queue_image_for_free(Image *ima)
{
BLI_lock_thread(LOCK_OPENGL);
- BLI_linklist_append(&image_free_queue, ima);
+ BLI_linklist_prepend(&image_free_queue, ima);
BLI_unlock_thread(LOCK_OPENGL);
}
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index ea7b169a882..1d08f1f6ea9 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -86,6 +86,7 @@ static struct GPUGlobal {
int extdisabled;
int colordepth;
int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
+ int dlistsdisabled; /* Legacy ATI driver does not support display lists well */
GPUDeviceType device;
GPUOSType os;
GPUDriverType driver;
@@ -190,6 +191,9 @@ void GPU_extensions_init(void)
* Incomplete list http://dri.freedesktop.org/wiki/ATIRadeon
* New IDs from MESA's src/gallium/drivers/r300/r300_screen.c
*/
+ /* This list is close enough to those using the legacy driver which
+ * has a bug with display lists and glVertexAttrib
+ */
if (strstr(renderer, "R3") || strstr(renderer, "RV3") ||
strstr(renderer, "R4") || strstr(renderer, "RV4") ||
strstr(renderer, "RS4") || strstr(renderer, "RC4") ||
@@ -200,6 +204,7 @@ void GPU_extensions_init(void)
strstr(renderer, "RADEON 9"))
{
GG.npotdisabled = 1;
+ GG.dlistsdisabled = 1;
}
}
@@ -238,6 +243,11 @@ int GPU_non_power_of_two_support(void)
return GLEW_ARB_texture_non_power_of_two;
}
+int GPU_display_list_support(void)
+{
+ return !GG.dlistsdisabled;
+}
+
int GPU_color_depth(void)
{
return GG.colordepth;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 0ca929da65d..ed7a2f4ede0 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -1127,7 +1127,16 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor);
}
}
+ else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
+ /* transform normal by object then view matrix */
+ GPU_link(mat, "mtex_nspace_object", GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), tnor, &newnor);
+ }
+ else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
+ /* transform normal by view matrix */
+ GPU_link(mat, "mtex_nspace_world", GPU_builtin(GPU_VIEW_MATRIX), tnor, &newnor);
+ }
else {
+ /* no transform, normal in camera space */
newnor = tnor;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 2aee5b4846a..633112095a7 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1415,6 +1415,16 @@ void mtex_nspace_tangent(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 out
outnormal = normalize(outnormal);
}
+void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
+{
+ outnormal = normalize((viewmat*vec4(texnormal, 0.0)).xyz);
+}
+
+void mtex_nspace_object(mat4 viewmat, mat4 obmat, vec3 texnormal, out vec3 outnormal)
+{
+ outnormal = normalize((viewmat*(obmat*vec4(texnormal, 0.0))).xyz);
+}
+
void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
{
outnormal = (1.0 - norfac)*normal + norfac*newnormal;
@@ -2087,11 +2097,16 @@ void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result)
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_subsurface_scattering(vec4 color, float roughness, vec3 N, out vec4 result)
+void node_subsurface_scattering(vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, out vec4 result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
+void node_bsdf_hair(vec4 color, float roughnessu, float roughnessv, out vec4 result)
+{
+ result = color;
+}
+
/* emission */
void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
@@ -2119,6 +2134,20 @@ void node_fresnel(float ior, vec3 N, vec3 I, out float result)
result = fresnel_dielectric(I, N, (gl_FrontFacing)? eta: 1.0/eta);
}
+/* gamma */
+
+void node_gamma(vec4 col, float gamma, out vec4 outcol)
+{
+ outcol = col;
+
+ if(col.r > 0.0)
+ outcol.r = compatible_pow(col.r, gamma);
+ if(col.g > 0.0)
+ outcol.g = compatible_pow(col.g, gamma);
+ if(col.b > 0.0)
+ outcol.b = compatible_pow(col.b, gamma);
+}
+
/* geometry */
void node_attribute(vec3 attr_uv, out vec4 outcol, out vec3 outvec, out float outf)
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 7399b8554aa..64a2bbb72d9 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -31,6 +31,12 @@
#ifndef __IMB_COLORMANAGEMENT_H__
#define __IMB_COLORMANAGEMENT_H__
+/** \file blender/imbuf/IMB_colormanagement.h
+ * \ingroup imbuf
+ */
+
+#include "BLI_sys_types.h"
+
#define BCM_CONFIG_FILE "config.ocio"
struct bContext;
@@ -62,19 +68,22 @@ void IMB_colormanagement_check_is_data(struct ImBuf *ibuf, const char *name);
void IMB_colormanagement_assign_float_colorspace(struct ImBuf *ibuf, const char *name);
void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name);
+const char *IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf);
+const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf);
+
/* ** Color space transformation functions ** */
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
- const char *from_colorspace, const char *to_colorspace, int predivide);
+ const char *from_colorspace, const char *to_colorspace, bool predivide);
void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
- const char *from_colorspace, const char *to_colorspace, int predivide);
+ const char *from_colorspace, const char *to_colorspace, bool predivide);
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace);
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace);
-void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predivide, struct ColorSpace *colorspace);
+void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], bool predivide, struct ColorSpace *colorspace);
void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], struct ColorSpace *colorspace);
-void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide);
+void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide);
void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], struct ColorManagedDisplay *display);
void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], struct ColorManagedDisplay *display);
@@ -88,7 +97,7 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float
void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings);
-struct ImBuf *IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf, int save_as_render, int allocate_result,
+struct ImBuf *IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf, bool save_as_render, bool allocate_result,
const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
struct ImageFormatData *image_format_data);
@@ -110,7 +119,7 @@ unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct I
void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height,
int channels, const struct ColorManagedViewSettings *view_settings,
- const struct ColorManagedDisplaySettings *display_settings, int predivide);
+ const struct ColorManagedDisplaySettings *display_settings, bool predivide);
void IMB_display_buffer_release(void *cache_handle);
@@ -125,6 +134,10 @@ const char *IMB_colormanagement_display_get_none_name(void);
int IMB_colormanagement_view_get_named_index(const char *name);
const char *IMB_colormanagement_view_get_indexed_name(int index);
+/* ** Look funcrions ** */
+int IMB_colormanagement_look_get_named_index(const char *name);
+const char *IMB_colormanagement_look_get_indexed_name(int index);
+
/* ** Color space functions ** */
int IMB_colormanagement_colorspace_get_named_index(const char *name);
const char *IMB_colormanagement_colorspace_get_indexed_name(int index);
@@ -135,6 +148,7 @@ void IMB_colormanagment_colorspace_from_ibuf_ftype(struct ColorManagedColorspace
/* ** RNA helper functions ** */
void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem);
void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name);
+void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem);
void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem);
/* ** Tile-based buffer management ** */
@@ -142,7 +156,7 @@ void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_b
int stride, int offset_x, int offset_y, const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings,
int xmin, int ymin, int xmax, int ymax,
- int update_orig_byte_buffer);
+ bool update_orig_byte_buffer);
void IMB_partial_display_buffer_update_delayed(struct ImBuf *ibuf, int xmin, int ymin, int xmax, int ymax);
@@ -154,29 +168,34 @@ void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_proc
void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor, float pixel[4]);
void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]);
void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height,
- int channels, int predivide);
+ int channels, bool predivide);
void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor);
/* ** OpenGL drawing routines using GLSL for color space transform ** */
+/* Test if GLSL drawing is supported for combination of graphics card and this configuration */
+bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings,
+ bool skip_curves);
/* Configures GLSL shader for conversion from scene linear to display space */
-int IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings,
- const struct ColorManagedDisplaySettings *display_settings,
- int predivide);
+bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings,
+ bool predivide,
+ bool skip_curves);
/* Same as above, but display space conversion happens from a specified space */
-int IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings,
- const struct ColorManagedDisplaySettings *display_settings,
- struct ColorSpace *colorspace,
- int predivide);
+bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings,
+ struct ColorSpace *colorspace,
+ bool predivide,
+ bool skip_curves);
/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
-int IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, int predivide);
+bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, bool predivide);
/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
-int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, int predivide);
+bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, bool predivide);
/* Finish GLSL-based display space conversion */
void IMB_colormanagement_finish_glsl_draw(void);
/* Configures GLSL shader for conversion from space defined by role to scene linear space */
-int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide);
+bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide);
/* Finish GLSL-based color space conversion */
void IMB_colormanagement_finish_glsl_transform(void);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 819026facc6..8c2e79ab7d8 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -51,9 +51,6 @@
* - Endianness issues are dealt with internally.
* - File I/O must be done externally. The module uses FILE*'s to
* direct input/output.
- * - Platform dependency is limited. Some minor patches for
- * amiga and Irix are present. A 'posix-compliance-patch'
- * provides the interface to windows.
*
* \section dependencies Dependencies
*
@@ -72,6 +69,9 @@
#define IM_MAX_SPACE 64
+/* for bool */
+#include "../blenlib/BLI_sys_types.h"
+
/**
*
* \attention defined in ???
@@ -146,8 +146,8 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1);
*
* \attention Defined in allocimbuf.c
*/
-short addzbufImBuf(struct ImBuf *ibuf);
-short addzbuffloatImBuf(struct ImBuf *ibuf);
+bool addzbufImBuf(struct ImBuf *ibuf);
+bool addzbuffloatImBuf(struct ImBuf *ibuf);
/**
*
@@ -500,17 +500,17 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
int x1, int y1, int x2, int y2);
/* defined in metadata.c */
-int IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field);
+bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field);
/* exported for image tools in blender, to quickly allocate 32 bits rect */
-short imb_addrectImBuf(struct ImBuf *ibuf);
+bool imb_addrectImBuf(struct ImBuf *ibuf);
void imb_freerectImBuf(struct ImBuf *ibuf);
-short imb_addrectfloatImBuf(struct ImBuf *ibuf);
+bool imb_addrectfloatImBuf(struct ImBuf *ibuf);
void imb_freerectfloatImBuf(struct ImBuf *ibuf);
void imb_freemipmapImBuf(struct ImBuf *ibuf);
-short imb_addtilesImBuf(struct ImBuf *ibuf);
+bool imb_addtilesImBuf(struct ImBuf *ibuf);
void imb_freetilesImBuf(struct ImBuf *ibuf);
/* threaded processors */
diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h
index 047228926ee..02b738cc2cd 100644
--- a/source/blender/imbuf/intern/IMB_allocimbuf.h
+++ b/source/blender/imbuf/intern/IMB_allocimbuf.h
@@ -35,8 +35,8 @@
struct ImBuf;
-short imb_addencodedbufferImBuf(struct ImBuf *ibuf);
-short imb_enlargeencodedbufferImBuf(struct ImBuf *ibuf);
+bool imb_addencodedbufferImBuf(struct ImBuf *ibuf);
+bool imb_enlargeencodedbufferImBuf(struct ImBuf *ibuf);
#endif
diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
index c372e125a66..17eb4bf6db4 100644
--- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h
+++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
@@ -28,10 +28,15 @@
*
*/
-#ifndef IMB_COLORMANAGEMENT_INTERN_H
-#define IMB_COLORMANAGEMENT_INTERN_H
+#ifndef __IMB_COLORMANAGEMENT_INTERN_H__
+#define __IMB_COLORMANAGEMENT_INTERN_H__
+
+/** \file IMB_colormanagement_intern.h
+ * \ingroup imbuf
+ */
#include "DNA_listBase.h"
+#include "BLI_sys_types.h"
struct OCIO_ConstProcessorRcPtr;
struct ImBuf;
@@ -48,8 +53,8 @@ typedef struct ColorSpace {
struct OCIO_ConstProcessorRcPtr *to_scene_linear;
struct OCIO_ConstProcessorRcPtr *from_scene_linear;
- int is_invertible;
- int is_data;
+ bool is_invertible;
+ bool is_data;
} ColorSpace;
typedef struct ColorManagedDisplay {
@@ -68,6 +73,14 @@ typedef struct ColorManagedView {
char name[MAX_COLORSPACE_NAME];
} ColorManagedView;
+typedef struct ColorManagedLook {
+ struct ColorManagedLook *next, *prev;
+ int index;
+ char name[MAX_COLORSPACE_NAME];
+ char process_space[MAX_COLORSPACE_NAME];
+ bool is_noop;
+} ColorManagedLook;
+
/* ** Initialization / De-initialization ** */
void colormanagement_init(void);
@@ -87,14 +100,18 @@ struct ColorManagedView *colormanage_view_add(const char *name);
struct ColorManagedView *colormanage_view_get_indexed(int index);
struct ColorManagedView *colormanage_view_get_named(const char *name);
-struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data);
+struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, bool is_invertible, bool is_data);
struct ColorSpace *colormanage_colorspace_get_named(const char *name);
struct ColorSpace *colormanage_colorspace_get_roled(int role);
struct ColorSpace *colormanage_colorspace_get_indexed(int index);
+struct ColorManagedLook *colormanage_look_add(const char *name, const char *process_space, bool is_noop);
+struct ColorManagedLook *colormanage_look_get_named(const char *name);
+struct ColorManagedLook *colormanage_look_get_indexed(int index);
+
void colorspace_set_default_role(char *colorspace, int size, int role);
void colormanage_imbuf_set_default_spaces(struct ImBuf *ibuf);
void colormanage_imbuf_make_linear(struct ImBuf *ibuf, const char *from_colorspace);
-#endif /* IMB_COLORMANAGEMENT_INTERN_H */
+#endif /* __IMB_COLORMANAGEMENT_INTERN_H__ */
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 154941c5c09..3c8b29cf68a 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -94,7 +94,6 @@ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags);
/* cocoa */
struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
-short imb_cocoaSaveImage(struct ImBuf *ibuf, const char *name, int flags);
/* cineon */
int imb_save_cineon(struct ImBuf *buf, const char *name, int flags);
diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h
index 96f7a68d669..6173ffa9b78 100644
--- a/source/blender/imbuf/intern/IMB_indexer.h
+++ b/source/blender/imbuf/intern/IMB_indexer.h
@@ -25,6 +25,10 @@
#ifndef __IMB_INDEXER_H__
#define __IMB_INDEXER_H__
+/** \file IMB_indexer.h
+ * \ingroup imbuf
+ */
+
#ifdef WIN32
# include <io.h>
#endif
diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h
index f731fd69620..a717764b44f 100644
--- a/source/blender/imbuf/intern/IMB_metadata.h
+++ b/source/blender/imbuf/intern/IMB_metadata.h
@@ -62,7 +62,7 @@ void IMB_metadata_free(struct ImBuf *img);
* \param len - length of value buffer allocated by user.
* \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise
*/
-int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len);
+bool IMB_metadata_get_field(struct ImBuf *img, 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.
@@ -71,13 +71,13 @@ int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, cons
* \param value - the data to be written to the field. zero terminated string
* \return - 1 (true) if ImageInfo present, 0 (false) otherwise
*/
-int IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value);
+bool IMB_metadata_add_field(struct ImBuf *img, 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
*/
-int IMB_metadata_del_field(struct ImBuf *img, const char *key);
+bool IMB_metadata_del_field(struct ImBuf *img, const char *key);
#endif /* __IMB_METADATA_H__ */
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index ca0b26fa4b7..fb7033e1362 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -48,6 +48,8 @@
#include "MEM_guardedalloc.h"
#include "MEM_CacheLimiterC-Api.h"
+#include "BLI_utildefines.h"
+
void imb_freemipmapImBuf(ImBuf *ibuf)
{
int a;
@@ -191,46 +193,48 @@ ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
return rval;
}
-short addzbufImBuf(ImBuf *ibuf)
+bool addzbufImBuf(ImBuf *ibuf)
{
- int size;
+ size_t size;
- if (ibuf == NULL) return FALSE;
+ if (ibuf == NULL) return false;
IMB_freezbufImBuf(ibuf);
- size = ibuf->x * ibuf->y * sizeof(unsigned int);
- if ((ibuf->zbuf = MEM_mapallocN(size, "addzbufImBuf"))) {
+ size = (size_t)(ibuf->x * ibuf->y) * sizeof(unsigned int);
+
+ if ((ibuf->zbuf = MEM_mapallocN(size, __func__))) {
ibuf->mall |= IB_zbuf;
ibuf->flags |= IB_zbuf;
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-short addzbuffloatImBuf(ImBuf *ibuf)
+bool addzbuffloatImBuf(ImBuf *ibuf)
{
- int size;
+ size_t size;
- if (ibuf == NULL) return FALSE;
+ if (ibuf == NULL) return false;
IMB_freezbuffloatImBuf(ibuf);
- size = ibuf->x * ibuf->y * sizeof(float);
- if ((ibuf->zbuf_float = MEM_mapallocN(size, "addzbuffloatImBuf"))) {
+ size = (size_t)(ibuf->x * ibuf->y) * sizeof(float);
+
+ if ((ibuf->zbuf_float = MEM_mapallocN(size, __func__))) {
ibuf->mall |= IB_zbuffloat;
ibuf->flags |= IB_zbuffloat;
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-short imb_addencodedbufferImBuf(ImBuf *ibuf)
+bool imb_addencodedbufferImBuf(ImBuf *ibuf)
{
- if (ibuf == NULL) return FALSE;
+ if (ibuf == NULL) return false;
freeencodedbufferImBuf(ibuf);
@@ -239,33 +243,33 @@ short imb_addencodedbufferImBuf(ImBuf *ibuf)
ibuf->encodedsize = 0;
- if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf"))) {
+ if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, __func__))) {
ibuf->mall |= IB_mem;
ibuf->flags |= IB_mem;
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-short imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
+bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
{
unsigned int newsize, encodedsize;
void *newbuffer;
- if (ibuf == NULL) return FALSE;
+ if (ibuf == NULL) return false;
if (ibuf->encodedbuffersize < ibuf->encodedsize) {
- printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
- return FALSE;
+ printf("%s: error in parameters\n", __func__);
+ return false;
}
newsize = 2 * ibuf->encodedbuffersize;
if (newsize < 10000) newsize = 10000;
- newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
- if (newbuffer == NULL) return FALSE;
+ newbuffer = MEM_mallocN(newsize, __func__);
+ if (newbuffer == NULL) return false;
if (ibuf->encodedbuffer) {
memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
@@ -284,59 +288,61 @@ short imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
ibuf->mall |= IB_mem;
ibuf->flags |= IB_mem;
- return TRUE;
+ return true;
}
-short imb_addrectfloatImBuf(ImBuf *ibuf)
+bool imb_addrectfloatImBuf(ImBuf *ibuf)
{
- int size;
+ size_t size;
- if (ibuf == NULL) return FALSE;
+ if (ibuf == NULL) return false;
if (ibuf->rect_float)
imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */
- size = ibuf->x * ibuf->y;
- size = size * 4 * sizeof(float);
+ size = (size_t)(ibuf->x * ibuf->y) * sizeof(float[4]);
+
ibuf->channels = 4;
-
- if ((ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf"))) {
+ if ((ibuf->rect_float = MEM_mapallocN(size, __func__))) {
ibuf->mall |= IB_rectfloat;
ibuf->flags |= IB_rectfloat;
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
/* question; why also add zbuf? */
-short imb_addrectImBuf(ImBuf *ibuf)
+bool imb_addrectImBuf(ImBuf *ibuf)
{
- int size;
+ size_t size;
- if (ibuf == NULL) return FALSE;
+ if (ibuf == NULL) return false;
/* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
if (ibuf->rect && (ibuf->mall & IB_rect))
MEM_freeN(ibuf->rect);
ibuf->rect = NULL;
- size = ibuf->x * ibuf->y;
- size = size * sizeof(unsigned int);
+ size = (size_t)(ibuf->x * ibuf->y) * sizeof(unsigned int);
- if ((ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf"))) {
+ if ((ibuf->rect = MEM_mapallocN(size, __func__))) {
ibuf->mall |= IB_rect;
ibuf->flags |= IB_rect;
- if (ibuf->planes > 32) return (addzbufImBuf(ibuf));
- else return TRUE;
+ if (ibuf->planes > 32) {
+ return (addzbufImBuf(ibuf));
+ }
+ else {
+ return true;
+ }
}
- return FALSE;
+ return false;
}
-short imb_addtilesImBuf(ImBuf *ibuf)
+bool imb_addtilesImBuf(ImBuf *ibuf)
{
- if (ibuf == NULL) return FALSE;
+ if (ibuf == NULL) return false;
if (!ibuf->tiles)
if ((ibuf->tiles = MEM_callocN(sizeof(unsigned int *) * ibuf->xtiles * ibuf->ytiles, "imb_tiles")))
@@ -360,28 +366,28 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int
ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */
if (flags & IB_rect) {
- if (imb_addrectImBuf(ibuf) == FALSE) {
+ if (imb_addrectImBuf(ibuf) == false) {
IMB_freeImBuf(ibuf);
return NULL;
}
}
if (flags & IB_rectfloat) {
- if (imb_addrectfloatImBuf(ibuf) == FALSE) {
+ if (imb_addrectfloatImBuf(ibuf) == false) {
IMB_freeImBuf(ibuf);
return NULL;
}
}
if (flags & IB_zbuf) {
- if (addzbufImBuf(ibuf) == FALSE) {
+ if (addzbufImBuf(ibuf) == false) {
IMB_freeImBuf(ibuf);
return NULL;
}
}
if (flags & IB_zbuffloat) {
- if (addzbuffloatImBuf(ibuf) == FALSE) {
+ if (addzbuffloatImBuf(ibuf) == false) {
IMB_freeImBuf(ibuf);
return NULL;
}
@@ -420,7 +426,7 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
if (ibuf1->encodedbuffer) {
ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
- if (imb_addencodedbufferImBuf(ibuf2) == FALSE) {
+ if (imb_addencodedbufferImBuf(ibuf2) == false) {
IMB_freeImBuf(ibuf2);
return NULL;
}
diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c
index eb3cfc3ade3..dabeec74a62 100644
--- a/source/blender/imbuf/intern/bmp.c
+++ b/source/blender/imbuf/intern/bmp.c
@@ -273,7 +273,7 @@ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags)
if (!ofile) return 0;
putShortLSB(19778, ofile); /* "BM" */
- putIntLSB(0, ofile); /* This can be 0 for BI_RGB bitmaps */
+ putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); /* Total file size */
putShortLSB(0, ofile); /* Res1 */
putShortLSB(0, ofile); /* Res2 */
putIntLSB(BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile);
@@ -284,7 +284,7 @@ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags)
putShortLSB(1, ofile);
putShortLSB(24, ofile);
putIntLSB(0, ofile);
- putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile);
+ putIntLSB(bytesize, ofile);
putIntLSB((int)(ibuf->ppm[0] + 0.5), ofile);
putIntLSB((int)(ibuf->ppm[1] + 0.5), ofile);
putIntLSB(0, ofile);
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 0167eaccef0..366c2922739 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -28,6 +28,10 @@
*
*/
+/** \file blender/imbuf/intern/colormanagement.c
+ * \ingroup imbuf
+ */
+
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
@@ -81,13 +85,15 @@ static char global_role_default_byte[MAX_COLORSPACE_NAME];
static char global_role_default_float[MAX_COLORSPACE_NAME];
static char global_role_default_sequencer[MAX_COLORSPACE_NAME];
-static ListBase global_colorspaces = {NULL};
-static ListBase global_displays = {NULL};
-static ListBase global_views = {NULL};
+static ListBase global_colorspaces = {NULL, NULL};
+static ListBase global_displays = {NULL, NULL};
+static ListBase global_views = {NULL, NULL};
+static ListBase global_looks = {NULL, NULL};
static int global_tot_colorspace = 0;
static int global_tot_display = 0;
static int global_tot_view = 0;
+static int global_tot_looks = 0;
/* lock used by pre-cached processors getters, so processor wouldn't
* be created several times
@@ -99,7 +105,7 @@ static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER;
typedef struct ColormanageProcessor {
OCIO_ConstProcessorRcPtr *processor;
CurveMapping *curve_mapping;
- int is_data_result;
+ bool is_data_result;
} ColormanageProcessor;
static struct global_glsl_state {
@@ -107,6 +113,7 @@ static struct global_glsl_state {
OCIO_ConstProcessorRcPtr *processor;
/* Settings of processor for comparison. */
+ char look[MAX_COLORSPACE_NAME];
char view[MAX_COLORSPACE_NAME];
char display[MAX_COLORSPACE_NAME];
char input[MAX_COLORSPACE_NAME];
@@ -185,9 +192,11 @@ static struct global_glsl_state {
*/
typedef struct ColormanageCacheViewSettings {
int flag;
+ int look;
int view;
float exposure;
float gamma;
+ float dither;
CurveMapping *curve_mapping;
} ColormanageCacheViewSettings;
@@ -202,8 +211,10 @@ typedef struct ColormanageCacheKey {
typedef struct ColormnaageCacheData {
int flag; /* view flags of cached buffer */
+ int look; /* Additional artistics transform */
float exposure; /* exposure value cached buffer is calculated with */
float gamma; /* gamma value cached buffer is calculated with */
+ float dither; /* dither value cached buffer is calculated with */
CurveMapping *curve_mapping; /* curve mapping used for cached buffer */
int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */
} ColormnaageCacheData;
@@ -282,14 +293,18 @@ static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data)
ibuf->colormanage_cache->data = data;
}
-static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cache_view_settings,
+static void colormanage_view_settings_to_cache(ImBuf *ibuf,
+ ColormanageCacheViewSettings *cache_view_settings,
const ColorManagedViewSettings *view_settings)
{
+ int look = IMB_colormanagement_look_get_named_index(view_settings->look);
int view = IMB_colormanagement_view_get_named_index(view_settings->view_transform);
+ cache_view_settings->look = look;
cache_view_settings->view = view;
cache_view_settings->exposure = view_settings->exposure;
cache_view_settings->gamma = view_settings->gamma;
+ cache_view_settings->dither = ibuf->dither;
cache_view_settings->flag = view_settings->flag;
cache_view_settings->curve_mapping = view_settings->curve_mapping;
}
@@ -364,8 +379,10 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
*/
cache_data = colormanage_cachedata_get(cache_ibuf);
- if (cache_data->exposure != view_settings->exposure ||
+ if (cache_data->look != view_settings->look ||
+ cache_data->exposure != view_settings->exposure ||
cache_data->gamma != view_settings->gamma ||
+ cache_data->dither != view_settings->dither ||
cache_data->flag != view_settings->flag ||
cache_data->curve_mapping != curve_mapping ||
cache_data->curve_mapping_timestamp != curve_mapping_timestamp)
@@ -409,8 +426,10 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
/* store data which is needed to check whether cached buffer could be used for color managed display settings */
cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data");
+ cache_data->look = view_settings->look;
cache_data->exposure = view_settings->exposure;
cache_data->gamma = view_settings->gamma;
+ cache_data->dither = view_settings->dither;
cache_data->flag = view_settings->flag;
cache_data->curve_mapping = curve_mapping;
cache_data->curve_mapping_timestamp = curve_mapping_timestamp;
@@ -454,7 +473,8 @@ static void colormanage_role_color_space_name_get(OCIO_ConstConfigRcPtr *config,
static void colormanage_load_config(OCIO_ConstConfigRcPtr *config)
{
- int tot_colorspace, tot_display, tot_display_view, index, viewindex, viewindex2;
+ int tot_colorspace, tot_display, tot_display_view, tot_looks;
+ int index, viewindex, viewindex2;
const char *name;
/* get roles */
@@ -470,7 +490,7 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config)
for (index = 0 ; index < tot_colorspace; index++) {
OCIO_ConstColorSpaceRcPtr *ocio_colorspace;
const char *description;
- int is_invertible, is_data;
+ bool is_invertible, is_data;
name = OCIO_configGetColorSpaceNameByIndex(config, index);
@@ -519,6 +539,21 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config)
}
global_tot_display = tot_display;
+
+ /* load looks */
+ tot_looks = OCIO_configGetNumLooks(config);
+ colormanage_look_add("None", "", true);
+ for (index = 0; index < tot_looks; index++) {
+ OCIO_ConstLookRcPtr *ocio_look;
+ const char *process_space;
+
+ name = OCIO_configGetLookNameByIndex(config, index);
+ ocio_look = OCIO_configGetLook(config, name);
+ process_space = OCIO_lookGetProcessSpace(ocio_look);
+ OCIO_lookRelease(ocio_look);
+
+ colormanage_look_add(name, process_space, false);
+ }
}
static void colormanage_free_config(void)
@@ -566,6 +601,9 @@ static void colormanage_free_config(void)
/* free views */
BLI_freelistN(&global_views);
+ /* free looks */
+ BLI_freelistN(&global_looks);
+
OCIO_exit();
}
@@ -705,7 +743,8 @@ static ColorSpace *display_transform_get_colorspace(const ColorManagedViewSettin
return NULL;
}
-static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform,
+static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *look,
+ const char *view_transform,
const char *display,
float exposure, float gamma,
const char *from_colorspace)
@@ -713,6 +752,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *vie
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_DisplayTransformRcPtr *dt;
OCIO_ConstProcessorRcPtr *processor;
+ ColorManagedLook *look_descr = colormanage_look_get_named(look);
dt = OCIO_createDisplayTransform();
@@ -720,6 +760,11 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *vie
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
+ if (look_descr->is_noop == false) {
+ OCIO_displayTransformSetLooksOverrideEnabled(dt, true);
+ OCIO_displayTransformSetLooksOverride(dt, look);
+ }
+
/* fstop exposure control */
if (exposure != 0.0f) {
OCIO_MatrixTransformRcPtr *mt;
@@ -871,6 +916,7 @@ static void init_default_view_settings(const ColorManagedDisplaySettings *displa
else
view_settings->view_transform[0] = '\0';
+ BLI_strncpy(view_settings->look, "None", sizeof(view_settings->look));
view_settings->flag = 0;
view_settings->gamma = 1.0f;
view_settings->exposure = 0.0f;
@@ -923,7 +969,7 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
imb_freerectImBuf(ibuf);
IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, TRUE);
+ from_colorspace, to_colorspace, true);
}
}
@@ -953,6 +999,7 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display
{
ColorManagedDisplay *display;
ColorManagedView *default_view = NULL;
+ ColorManagedLook *default_look = (ColorManagedLook *) global_looks.first;
if (view_settings->view_transform[0] == '\0') {
display = colormanage_display_get_named(display_settings->display_device);
@@ -981,6 +1028,19 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display
}
}
+ if (view_settings->look[0] == '\0') {
+ BLI_strncpy(view_settings->look, default_look->name, sizeof(view_settings->look));
+ }
+ else {
+ ColorManagedLook *look = colormanage_look_get_named(view_settings->look);
+ if (look == NULL) {
+ printf("Color management: %s look \"%s\" not found, setting default \"%s\".\n",
+ what, view_settings->look, default_look->name);
+
+ BLI_strncpy(view_settings->look, default_look->name, sizeof(view_settings->look));
+ }
+ }
+
/* OCIO_TODO: move to do_versions() */
if (view_settings->exposure == 0.0f && view_settings->gamma == 0.0f) {
view_settings->exposure = 0.0f;
@@ -1134,6 +1194,21 @@ void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name)
ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA;
}
+const char *IMB_colormanagement_get_float_colorspace(ImBuf *ibuf)
+{
+ if (ibuf->float_colorspace) {
+ return ibuf->float_colorspace->name;
+ }
+ else {
+ return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+ }
+}
+
+const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf)
+{
+ return ibuf->rect_colorspace->name;
+}
+
/*********************** Threaded display buffer transform routines *************************/
typedef struct DisplayBufferThread {
@@ -1151,7 +1226,7 @@ typedef struct DisplayBufferThread {
int channels;
float dither;
- int is_data;
+ bool is_data;
const char *byte_colorspace;
const char *float_colorspace;
@@ -1180,7 +1255,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
int channels = ibuf->channels;
float dither = ibuf->dither;
- int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
+ bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0;
int offset = channels * start_line * ibuf->x;
int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x;
@@ -1224,8 +1299,8 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle
int buffer_size = channels * width * height;
- int is_data = handle->is_data;
- int is_data_display = handle->cm_processor->is_data_result;
+ bool is_data = handle->is_data;
+ bool is_data_display = handle->cm_processor->is_data_result;
linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer");
@@ -1258,7 +1333,7 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle
if (!is_data && !is_data_display) {
/* convert float buffer to scene linear space */
IMB_colormanagement_transform(linear_buffer, width, height, channels,
- from_colorspace, to_colorspace, FALSE);
+ from_colorspace, to_colorspace, false);
}
*is_straight_alpha = true;
@@ -1277,7 +1352,7 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle
if (!is_data && !is_data_display) {
IMB_colormanagement_transform(linear_buffer, width, height, channels,
- from_colorspace, to_colorspace, TRUE);
+ from_colorspace, to_colorspace, true);
}
*is_straight_alpha = false;
@@ -1310,7 +1385,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
int width = handle->width;
int height = handle->tot_line;
float dither = handle->dither;
- int is_data = handle->is_data;
+ bool is_data = handle->is_data;
if (cm_processor == NULL) {
if (display_buffer_byte) {
@@ -1403,8 +1478,8 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c
display_buffer_init_handle, do_display_buffer_apply_thread);
}
-static int is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings)
+static bool is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
{
if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 &&
view_settings->exposure == 0.0f &&
@@ -1414,10 +1489,10 @@ static int is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSett
const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings);
if (to_colorspace && !strcmp(from_colorspace, to_colorspace))
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte,
@@ -1425,7 +1500,7 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu
const ColorManagedDisplaySettings *display_settings)
{
ColormanageProcessor *cm_processor = NULL;
- int skip_transform = FALSE;
+ bool skip_transform = false;
/* if we're going to transform byte buffer, check whether transformation would
* happen to the same color space as byte buffer itself is
@@ -1436,7 +1511,7 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu
skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings);
}
- if (skip_transform == FALSE)
+ if (skip_transform == false)
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect,
@@ -1462,7 +1537,7 @@ typedef struct ProcessorTransformThread {
int start_line;
int tot_line;
int channels;
- int predivide;
+ bool predivide;
} ProcessorTransformThread;
typedef struct ProcessorTransformInit {
@@ -1471,7 +1546,7 @@ typedef struct ProcessorTransformInit {
int width;
int height;
int channels;
- int predivide;
+ bool predivide;
} ProcessorTransformInitData;
static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@@ -1481,7 +1556,7 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int
int channels = init_data->channels;
int width = init_data->width;
- int predivide = init_data->predivide;
+ bool predivide = init_data->predivide;
int offset = channels * start_line * width;
@@ -1507,7 +1582,7 @@ static void *do_processor_transform_thread(void *handle_v)
int channels = handle->channels;
int width = handle->width;
int height = handle->tot_line;
- int predivide = handle->predivide;
+ bool predivide = handle->predivide;
IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide);
@@ -1515,7 +1590,7 @@ static void *do_processor_transform_thread(void *handle_v)
}
static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels,
- ColormanageProcessor *cm_processor, int predivide)
+ ColormanageProcessor *cm_processor, bool predivide)
{
ProcessorTransformInitData init_data;
@@ -1534,7 +1609,7 @@ static void processor_transform_apply_threaded(float *buffer, int width, int hei
/* convert the whole buffer from specified by name color space to another - internal implementation */
static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace,
- const char *to_colorspace, int predivide, int do_threaded)
+ const char *to_colorspace, bool predivide, bool do_threaded)
{
ColormanageProcessor *cm_processor;
@@ -1561,18 +1636,18 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i
/* convert the whole buffer from specified by name color space to another */
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
- const char *from_colorspace, const char *to_colorspace, int predivide)
+ const char *from_colorspace, const char *to_colorspace, bool predivide)
{
- colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, FALSE);
+ colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false);
}
/* convert the whole buffer from specified by name color space to another
* will do threaded conversion
*/
void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
- const char *from_colorspace, const char *to_colorspace, int predivide)
+ const char *from_colorspace, const char *to_colorspace, bool predivide)
{
- colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, TRUE);
+ colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true);
}
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace)
@@ -1633,7 +1708,7 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpac
OCIO_processorApplyRGB(processor, pixel);
}
-void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predivide, ColorSpace *colorspace)
+void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], bool predivide, ColorSpace *colorspace)
{
OCIO_ConstProcessorRcPtr *processor;
@@ -1653,7 +1728,7 @@ void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predi
}
}
-void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide)
+void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide)
{
OCIO_ConstProcessorRcPtr *processor;
@@ -1732,7 +1807,7 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float
}
static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings, int make_byte)
+ const ColorManagedDisplaySettings *display_settings, bool make_byte)
{
if (!ibuf->rect && make_byte)
imb_addrectImBuf(ibuf);
@@ -1750,7 +1825,7 @@ static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorMan
void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings)
{
- colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, FALSE);
+ colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, false);
}
/* prepare image buffer to be saved on disk, applying color management if needed
@@ -1764,14 +1839,14 @@ void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManage
* in image format write callback and if float_colorspace is not NULL, no color
* space transformation should be applied on this buffer.
*/
-ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int allocate_result, const ColorManagedViewSettings *view_settings,
+ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, bool allocate_result, const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings, ImageFormatData *image_format_data)
{
ImBuf *colormanaged_ibuf = ibuf;
- int do_colormanagement;
+ bool do_colormanagement;
bool is_movie = BKE_imtype_is_movie(image_format_data->imtype);
- int requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype);
- int do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA;
+ bool requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype);
+ bool do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA;
do_colormanagement = save_as_render && (is_movie || !requires_linear_float);
@@ -1827,7 +1902,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int
}
if (do_colormanagement) {
- int make_byte = FALSE;
+ bool make_byte = false;
ImFileType *type;
/* for proper check whether byte buffer is required by a format or not
@@ -1843,7 +1918,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int
for (type = IMB_FILE_TYPES; type->is_a; type++) {
if (type->save && type->ftype(type, colormanaged_ibuf)) {
if ((type->flag & IM_FTYPE_FLOAT) == 0)
- make_byte = TRUE;
+ make_byte = true;
break;
}
@@ -1878,7 +1953,7 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
processor_transform_apply_threaded(display_buffer_float, width, height, channels,
- cm_processor, TRUE);
+ cm_processor, true);
IMB_buffer_byte_from_float(display_buffer, display_buffer_float,
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
@@ -1955,7 +2030,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
return (unsigned char *) ibuf->rect;
}
- colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings);
+ colormanage_view_settings_to_cache(ibuf, &cache_view_settings, applied_view_settings);
colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
if (ibuf->invalid_rect.xmin != ibuf->invalid_rect.xmax) {
@@ -1964,7 +2039,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
ibuf->x, 0, 0, applied_view_settings, display_settings,
ibuf->invalid_rect.xmin, ibuf->invalid_rect.ymin,
ibuf->invalid_rect.xmax, ibuf->invalid_rect.ymax,
- FALSE);
+ false);
}
BLI_rcti_init(&ibuf->invalid_rect, 0, 0, 0, 0);
@@ -2019,7 +2094,7 @@ unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, vo
void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height,
int channels, const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings, int predivide)
+ const ColorManagedDisplaySettings *display_settings, bool predivide)
{
if (global_tot_display == 0 || global_tot_view == 0) {
IMB_buffer_byte_from_float(display_buffer, linear_buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE,
@@ -2281,7 +2356,7 @@ static void colormanage_description_strip(char *description)
}
}
-ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data)
+ColorSpace *colormanage_colorspace_add(const char *name, const char *description, bool is_invertible, bool is_data)
{
ColorSpace *colorspace, *prev_space;
int counter = 1;
@@ -2342,7 +2417,7 @@ ColorSpace *colormanage_colorspace_get_roled(int role)
ColorSpace *colormanage_colorspace_get_indexed(int index)
{
- /* display indices are 1-based */
+ /* color space indices are 1-based */
return BLI_findlink(&global_colorspaces, index - 1);
}
@@ -2387,6 +2462,71 @@ void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSetting
}
}
+/*********************** Looks functions *************************/
+
+ColorManagedLook *colormanage_look_add(const char *name, const char *process_space, bool is_noop)
+{
+ ColorManagedLook *look;
+ int index = global_tot_looks;
+
+ look = MEM_callocN(sizeof(ColorManagedLook), "ColorManagedLook");
+ look->index = index + 1;
+ BLI_strncpy(look->name, name, sizeof(look->name));
+ BLI_strncpy(look->process_space, process_space, sizeof(look->process_space));
+ look->is_noop = is_noop;
+
+ BLI_addtail(&global_looks, look);
+
+ global_tot_looks++;
+
+ return look;
+}
+
+ColorManagedLook *colormanage_look_get_named(const char *name)
+{
+ ColorManagedLook *look;
+
+ for (look = global_looks.first; look; look = look->next) {
+ if (!strcmp(look->name, name)) {
+ return look;
+ }
+ }
+
+ return NULL;
+}
+
+ColorManagedLook *colormanage_look_get_indexed(int index)
+{
+ /* look indices are 1-based */
+ return BLI_findlink(&global_looks, index - 1);
+}
+
+int IMB_colormanagement_look_get_named_index(const char *name)
+{
+ ColorManagedLook *look;
+
+ look = colormanage_look_get_named(name);
+
+ if (look) {
+ return look->index;
+ }
+
+ return 0;
+}
+
+const char *IMB_colormanagement_look_get_indexed_name(int index)
+{
+ ColorManagedLook *look;
+
+ look = colormanage_look_get_indexed(index);
+
+ if (look) {
+ return look->name;
+ }
+
+ return NULL;
+}
+
/*********************** RNA helper functions *************************/
void IMB_colormanagement_display_items_add(EnumPropertyItem **items, int *totitem)
@@ -2435,6 +2575,23 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem,
}
}
+void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem)
+{
+ ColorManagedLook *look;
+
+ for (look = global_looks.first; look; look = look->next) {
+ EnumPropertyItem item;
+
+ item.value = look->index;
+ item.name = look->name;
+ item.identifier = look->name;
+ item.icon = 0;
+ item.description = "";
+
+ RNA_enum_item_add(items, totitem, &item);
+ }
+}
+
void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *totitem)
{
ColorSpace *colorspace;
@@ -2480,7 +2637,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
float *display_buffer_float = NULL;
const int width = xmax - xmin;
const int height = ymax - ymin;
- int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
+ bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0;
if (dither != 0.0f) {
/* cm_processor is NULL in cases byte_buffer's space matches display
@@ -2561,7 +2718,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer,
int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
- int xmin, int ymin, int xmax, int ymax, int update_orig_byte_buffer)
+ int xmin, int ymin, int xmax, int ymax, bool update_orig_byte_buffer)
{
if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) {
/* update byte buffer created by legacy color management */
@@ -2584,7 +2741,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
unsigned char *display_buffer = NULL;
int view_flag, display_index, buffer_width;
- colormanage_view_settings_to_cache(&cache_view_settings, view_settings);
+ colormanage_view_settings_to_cache(ibuf, &cache_view_settings, view_settings);
colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
view_flag = 1 << (cache_view_settings.view - 1);
@@ -2608,7 +2765,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
if (display_buffer) {
ColormanageProcessor *cm_processor = NULL;
- int skip_transform = 0;
+ bool skip_transform = false;
/* byte buffer is assumed to be in imbuf's rect space, so if byte buffer
* is known we could skip display->linear->display conversion in case
@@ -2667,13 +2824,16 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag
if (display_space)
cm_processor->is_data_result = display_space->is_data;
- cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device,
- applied_view_settings->exposure, applied_view_settings->gamma,
+ cm_processor->processor = create_display_buffer_processor(applied_view_settings->look,
+ applied_view_settings->view_transform,
+ display_settings->display_device,
+ applied_view_settings->exposure,
+ applied_view_settings->gamma,
global_role_scene_linear);
if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping);
- curvemapping_premultiply(cm_processor->curve_mapping, FALSE);
+ curvemapping_premultiply(cm_processor->curve_mapping, false);
}
return cm_processor;
@@ -2722,7 +2882,7 @@ void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor,
}
void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height,
- int channels, int predivide)
+ int channels, bool predivide)
{
/* apply curve mapping */
if (cm_processor->curve_mapping) {
@@ -2771,6 +2931,7 @@ static bool check_glsl_display_processor_changed(const ColorManagedViewSettings
{
return !(global_glsl_state.exposure == view_settings->exposure &&
global_glsl_state.gamma == view_settings->gamma &&
+ STREQ(global_glsl_state.look, view_settings->look) &&
STREQ(global_glsl_state.view, view_settings->view_transform) &&
STREQ(global_glsl_state.display, display_settings->display_device) &&
STREQ(global_glsl_state.input, from_colorspace));
@@ -2787,6 +2948,7 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace))
{
/* Store settings of processor for further comparison. */
+ BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.display, display_settings->display_device, MAX_COLORSPACE_NAME);
BLI_strncpy(global_glsl_state.input, from_colorspace, MAX_COLORSPACE_NAME);
@@ -2799,7 +2961,8 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
/* We're using display OCIO processor, no RGB curves yet. */
global_glsl_state.processor =
- create_display_buffer_processor(global_glsl_state.view,
+ create_display_buffer_processor(global_glsl_state.look,
+ global_glsl_state.view,
global_glsl_state.display,
global_glsl_state.exposure,
global_glsl_state.gamma,
@@ -2807,6 +2970,17 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
}
}
+bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_settings,
+ bool skip_curves)
+{
+ /* curves not supported yet */
+ if (!skip_curves)
+ if (view_settings && (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES))
+ return 0;
+
+ return OCIO_supportGLSLDraw();
+}
+
/**
* Configures GLSL shader for conversion from specified to
* display color space
@@ -2820,9 +2994,10 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s
* This is low-level function, use glaDrawImBuf_glsl_ctx if you
* only need to display given image buffer
*/
-int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings,
- struct ColorSpace *from_colorspace, int predivide)
+bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings,
+ struct ColorSpace *from_colorspace, bool predivide,
+ bool skip_curves)
{
ColorManagedViewSettings default_view_settings;
const ColorManagedViewSettings *applied_view_settings;
@@ -2840,8 +3015,9 @@ int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSetting
}
/* RGB curves mapping is not supported on GPU yet. */
- if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
- return FALSE;
+ if (!skip_curves)
+ if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
+ return false;
/* Make sure OCIO processor is up-to-date. */
update_glsl_display_processor(applied_view_settings, display_settings,
@@ -2851,27 +3027,27 @@ int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSetting
}
/* Configures GLSL shader for conversion from scene linear to display space */
-int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings,
- const ColorManagedDisplaySettings *display_settings,
- int predivide)
+bool IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings,
+ bool predivide, bool skip_curves)
{
return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
- NULL, predivide);
+ NULL, predivide, skip_curves);
}
/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */
-int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, int predivide)
+bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, bool predivide)
{
ColorManagedViewSettings *view_settings;
ColorManagedDisplaySettings *display_settings;
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
- return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide);
+ return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide, false);
}
/* Same as setup_glsl_draw, but color management settings are guessing from a given context */
-int IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, int predivide)
+bool IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, bool predivide)
{
return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, predivide);
}
@@ -2897,7 +3073,7 @@ void IMB_colormanagement_finish_glsl_draw(void)
* When there's no need to apply transform on 2D textures, use
* IMB_colormanagement_finish_glsl_transform().
*/
-int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide)
+bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide)
{
OCIO_ConstProcessorRcPtr *processor;
ColorSpace *colorspace;
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 76a5e98da7e..af9f7109106 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -565,7 +565,7 @@ void IMB_rect_from_float(ImBuf *ibuf)
buffer = MEM_dupallocN(ibuf->rect_float);
/* first make float buffer in byte space */
- IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, TRUE);
+ IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, true);
/* convert from float's premul alpha to byte's straight alpha */
IMB_unpremultiply_rect_float(buffer, ibuf->planes, ibuf->x, ibuf->y);
@@ -657,7 +657,7 @@ void IMB_float_from_rect(ImBuf *ibuf)
/* then make float be in linear space */
IMB_colormanagement_colorspace_to_scene_linear(rect_float, ibuf->x, ibuf->y, ibuf->channels,
- ibuf->rect_colorspace, FALSE);
+ ibuf->rect_colorspace, false);
/* byte buffer is straight alpha, float should always be premul */
IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y);
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index 26dd0f2977a..bde17e17419 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -359,17 +359,21 @@ void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol
unsigned char *cp = rect;
while (a--) {
- if (cp[3] == 0) {
+ if (cp[3] == 255) {
+ /* pass */
+ }
+ else if (cp[3] == 0) {
cp[0] = backcol[0] * 255;
cp[1] = backcol[1] * 255;
cp[2] = backcol[2] * 255;
}
else {
- int mul = 255 - cp[3];
+ float alpha = cp[3] / 255.0;
+ float mul = 1.0f - alpha;
- cp[0] = (cp[0] * cp[3] >> 8) + mul * backcol[0] / 255;
- cp[1] = (cp[1] * cp[3] >> 8) + mul * backcol[1] / 255;
- cp[2] = (cp[2] * cp[3] >> 8) + mul * backcol[2] / 255;
+ cp[0] = (cp[0] * alpha) + mul * backcol[0];
+ cp[1] = (cp[1] * alpha) + mul * backcol[1];
+ cp[2] = (cp[2] * alpha) + mul * backcol[2];
}
cp[3] = 255;
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 7acfe8a9dd1..dd0970a71f2 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -22,6 +22,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/imbuf/intern/indexer.c
+ * \ingroup imbuf
+ */
+
#include <stdlib.h>
#include "MEM_guardedalloc.h"
diff --git a/source/blender/imbuf/intern/indexer_dv.c b/source/blender/imbuf/intern/indexer_dv.c
index 7a8f8fcc752..4e8c13d2e99 100644
--- a/source/blender/imbuf/intern/indexer_dv.c
+++ b/source/blender/imbuf/intern/indexer_dv.c
@@ -22,6 +22,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/imbuf/intern/indexer_dv.c
+ * \ingroup imbuf
+ */
+
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index 38caf224c42..a31ed5e7420 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -59,11 +59,7 @@
#define IS_maxjpg(x) ((x->ftype & JPG_MSK) == JPG_MAX)
/* the types are from the jpeg lib */
-static void jpeg_error(j_common_ptr cinfo)
-#ifdef __GNUC__
-__attribute__((noreturn))
-#endif
-;
+static void jpeg_error(j_common_ptr cinfo) ATTR_NORETURN;
static void init_source(j_decompress_ptr cinfo);
static boolean fill_input_buffer(j_decompress_ptr cinfo);
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c
index fed55c05eea..2b4367528dd 100644
--- a/source/blender/imbuf/intern/metadata.c
+++ b/source/blender/imbuf/intern/metadata.c
@@ -63,21 +63,21 @@ void IMB_metadata_free(struct ImBuf *img)
}
}
-int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, const size_t len)
+bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, const size_t len)
{
ImMetaData *info;
- int retval = 0;
+ bool retval = false;
if (!img)
- return 0;
+ return false;
if (!img->metadata) {
- return 0;
+ return false;
}
info = img->metadata;
while (info) {
if (strcmp(key, info->key) == 0) {
BLI_strncpy(field, info->value, len);
- retval = 1;
+ retval = true;
break;
}
info = info->next;
@@ -85,13 +85,13 @@ int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, cons
return retval;
}
-int IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value)
+bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value)
{
ImMetaData *info;
ImMetaData *last;
if (!img)
- return 0;
+ return false;
if (!img->metadata) {
img->metadata = MEM_callocN(sizeof(ImMetaData), "ImMetaData");
@@ -109,15 +109,15 @@ int IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value
}
info->key = BLI_strdup(key);
info->value = BLI_strdup(value);
- return 1;
+ return true;
}
-int IMB_metadata_del_field(struct ImBuf *img, const char *key)
+bool IMB_metadata_del_field(struct ImBuf *img, const char *key)
{
ImMetaData *p, *p1;
if ((!img) || (!img->metadata))
- return (0);
+ return false;
p = img->metadata;
p1 = NULL;
@@ -131,20 +131,20 @@ int IMB_metadata_del_field(struct ImBuf *img, const char *key)
MEM_freeN(p->key);
MEM_freeN(p->value);
MEM_freeN(p);
- return (1);
+ return true;
}
p1 = p;
p = p->next;
}
- return (0);
+ return false;
}
-int IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field)
+bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field)
{
ImMetaData *p;
if (!img)
- return (0);
+ return false;
if (!img->metadata)
return (IMB_metadata_add_field(img, key, field));
@@ -154,7 +154,7 @@ int IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *fi
if (!strcmp(key, p->key)) {
MEM_freeN(p->value);
p->value = BLI_strdup(field);
- return (1);
+ return true;
}
p = p->next;
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 875e01f8037..1e145347bb3 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -235,7 +235,7 @@ typedef struct PreviewImage {
# undef GS
#endif
// #define GS(a) (*((short *)(a)))
-#define GS(a) (CHECK_TYPE_INLINE(a, const char), (*((short *)(a))))
+#define GS(a) (CHECK_TYPE_INLINE(a, const char *), (*((short *)(a))))
#define ID_NEW(a) if ( (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid
#define ID_NEW_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index 1495ba1b1a5..f4e2ff43fc5 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -59,7 +59,7 @@ typedef struct bActionActuator {
short layer; /* Animation layer */
short end_reset; /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */
short strideaxis; /* Displacement axis */
- short pad;
+ short blend_mode; /* Layer blending mode */
float stridelength; /* Displacement incurred by cycle */ // not in use
float layer_weight; /* How much of the previous layer to use for blending. (<0 = disable, 0 = add mode) */
} bActionActuator;
@@ -341,6 +341,10 @@ typedef struct bActuator {
#define ACT_ACTION_FROM_PROP 6
#define ACT_ACTION_MOTION 7
+/* actionactuator->blend_mode */
+#define ACT_ACTION_BLEND 0
+#define ACT_ACTION_ADD 1
+
/* ipoactuator->type */
#define ACT_IPO_PLAY 0
#define ACT_IPO_PINGPONG 1
diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h
index 32a0629c338..50bbc04ccb1 100644
--- a/source/blender/makesdna/DNA_color_types.h
+++ b/source/blender/makesdna/DNA_color_types.h
@@ -162,6 +162,7 @@ typedef struct Scopes {
typedef struct ColorManagedViewSettings {
int flag, pad;
+ char look[64]; /* look which is being applied when displaying buffer on the screen (prior to view transform) */
char view_transform[64]; /* view transform which is being applied when displaying buffer on the screen */
float exposure; /* fstop exposure */
float gamma; /* post-display gamma transform */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index f1b7a7c3cc3..29e49a970d8 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -407,8 +407,10 @@ typedef struct bShrinkwrapConstraint {
struct Object *target;
float dist; /* distance to kept from target */
short shrinkType; /* shrink type (look on MOD shrinkwrap for values) */
- char projAxis; /* axis to project over UP_X, UP_Y, UP_Z */
- char pad[9];
+ char projAxis; /* axis to project/constrain */
+ char projAxisSpace; /* space to project axis in */
+ float projLimit; /* distance to search */
+ char pad[4];
} bShrinkwrapConstraint;
/* Follow Track constraints */
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 7ff8667f90e..2cfbbbd516b 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -184,12 +184,9 @@ typedef struct Curve {
struct Object *bevobj, *taperobj, *textoncurve;
struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
- Path *path;
struct Key *key;
struct Material **mat;
- ListBase bev;
-
/* texture space, copied as one block in editobject.c */
float loc[3];
float size[3];
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index e2863d6e465..f6516492b8f 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -73,50 +73,52 @@ typedef struct CustomData {
} CustomData;
/* CustomData.type */
-#define CD_MVERT 0
-#define CD_MSTICKY 1 /* DEPRECATED */
-#define CD_MDEFORMVERT 2
-#define CD_MEDGE 3
-#define CD_MFACE 4
-#define CD_MTFACE 5
-#define CD_MCOL 6
-#define CD_ORIGINDEX 7
-#define CD_NORMAL 8
-//#define CD_POLYINDEX 9
-#define CD_PROP_FLT 10
-#define CD_PROP_INT 11
-#define CD_PROP_STR 12
-#define CD_ORIGSPACE 13 /* for modifier stack face location mapping */
-#define CD_ORCO 14
-#define CD_MTEXPOLY 15
-#define CD_MLOOPUV 16
-#define CD_MLOOPCOL 17
-#define CD_TANGENT 18
-#define CD_MDISPS 19
-#define CD_PREVIEW_MCOL 20 /* for displaying weightpaint colors */
-#define CD_ID_MCOL 21
-#define CD_TEXTURE_MCOL 22
-#define CD_CLOTH_ORCO 23
-#define CD_RECAST 24
+enum {
+ CD_MVERT = 0,
+ CD_MSTICKY = 1, /* DEPRECATED */
+ CD_MDEFORMVERT = 2,
+ CD_MEDGE = 3,
+ CD_MFACE = 4,
+ CD_MTFACE = 5,
+ CD_MCOL = 6,
+ CD_ORIGINDEX = 7,
+ CD_NORMAL = 8,
+/* CD_POLYINDEX = 9, */
+ CD_PROP_FLT = 10,
+ CD_PROP_INT = 11,
+ CD_PROP_STR = 12,
+ CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
+ CD_ORCO = 14,
+ CD_MTEXPOLY = 15,
+ CD_MLOOPUV = 16,
+ CD_MLOOPCOL = 17,
+ CD_TANGENT = 18,
+ CD_MDISPS = 19,
+ CD_PREVIEW_MCOL = 20, /* for displaying weightpaint colors */
+ CD_ID_MCOL = 21,
+ CD_TEXTURE_MCOL = 22,
+ CD_CLOTH_ORCO = 23,
+ CD_RECAST = 24,
/* BMESH ONLY START */
-#define CD_MPOLY 25
-#define CD_MLOOP 26
-#define CD_SHAPE_KEYINDEX 27
-#define CD_SHAPEKEY 28
-#define CD_BWEIGHT 29
-#define CD_CREASE 30
-#define CD_ORIGSPACE_MLOOP 31
-#define CD_PREVIEW_MLOOPCOL 32
-#define CD_BM_ELEM_PYPTR 33
+ CD_MPOLY = 25,
+ CD_MLOOP = 26,
+ CD_SHAPE_KEYINDEX = 27,
+ CD_SHAPEKEY = 28,
+ CD_BWEIGHT = 29,
+ CD_CREASE = 30,
+ CD_ORIGSPACE_MLOOP = 31,
+ CD_PREVIEW_MLOOPCOL = 32,
+ CD_BM_ELEM_PYPTR = 33,
/* BMESH ONLY END */
-#define CD_PAINT_MASK 34
-#define CD_GRID_PAINT_MASK 35
-#define CD_MVERT_SKIN 36
-#define CD_FREESTYLE_EDGE 37
-#define CD_FREESTYLE_FACE 38
-#define CD_NUMTYPES 39
+ CD_PAINT_MASK = 34,
+ CD_GRID_PAINT_MASK = 35,
+ CD_MVERT_SKIN = 36,
+ CD_FREESTYLE_EDGE = 37,
+ CD_FREESTYLE_FACE = 38,
+ CD_NUMTYPES = 39,
+};
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
@@ -162,22 +164,22 @@ typedef struct CustomData {
#define CD_MASK_FREESTYLE_FACE (1LL << CD_FREESTYLE_FACE)
/* CustomData.flag */
-
-/* indicates layer should not be copied by CustomData_from_template or
- * CustomData_copy_data */
-#define CD_FLAG_NOCOPY (1<<0)
-/* indicates layer should not be freed (for layers backed by external data) */
-#define CD_FLAG_NOFREE (1<<1)
-/* indicates the layer is only temporary, also implies no copy */
-#define CD_FLAG_TEMPORARY ((1<<2)|CD_FLAG_NOCOPY)
-/* indicates the layer is stored in an external file */
-#define CD_FLAG_EXTERNAL (1<<3)
-/* indicates external data is read into memory */
-#define CD_FLAG_IN_MEMORY (1<<4)
+enum {
+ /* Indicates layer should not be copied by CustomData_from_template or CustomData_copy_data */
+ CD_FLAG_NOCOPY = (1 << 0),
+ /* Indicates layer should not be freed (for layers backed by external data) */
+ CD_FLAG_NOFREE = (1 << 1),
+ /* Indicates the layer is only temporary, also implies no copy */
+ CD_FLAG_TEMPORARY = ((1 << 2) | CD_FLAG_NOCOPY),
+ /* Indicates the layer is stored in an external file */
+ CD_FLAG_EXTERNAL = (1 << 3),
+ /* Indicates external data is read into memory */
+ CD_FLAG_IN_MEMORY = (1 << 4),
+};
/* Limits */
-#define MAX_MTFACE 8
-#define MAX_MCOL 8
+#define MAX_MTFACE 8
+#define MAX_MCOL 8
#ifdef __cplusplus
}
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
index 738377b137e..db16fa37b86 100644
--- a/source/blender/makesdna/DNA_freestyle_types.h
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -28,6 +28,10 @@
#ifndef __DNA_FREESTYLE_TYPES_H__
#define __DNA_FREESTYLE_TYPES_H__
+/** \file DNA_freestyle_types.h
+ * \ingroup DNA
+ */
+
#include "DNA_listBase.h"
#ifdef __cplusplus
diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h
index 3e641fba1ac..2699c6e576e 100644
--- a/source/blender/makesdna/DNA_ipo_types.h
+++ b/source/blender/makesdna/DNA_ipo_types.h
@@ -42,6 +42,8 @@
#include "DNA_ID.h"
+#include "BLI_compiler_attrs.h"
+
/* -------------------------- Type Defines --------------------------- */
/* sometimes used - mainly for GE/Ketsji */
diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h
index 0a09a82b2bb..f5ce3c8d8c1 100644
--- a/source/blender/makesdna/DNA_key_types.h
+++ b/source/blender/makesdna/DNA_key_types.h
@@ -60,7 +60,6 @@ typedef struct KeyBlock {
int uid; /* for meshes only, match the unique number with the customdata layer */
void *data; /* array of shape key values, size is (Key->elemsize * KeyBlock->totelem) */
- float *weights; /* store an aligned array of weights from 'vgroup' */
char name[64]; /* MAX_NAME (unique name, user assigned) */
char vgroup[64]; /* MAX_VGROUP_NAME (optional vertex group), array gets allocated into 'weights' when set */
diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h
index 837f0c354e6..242d6f0feeb 100644
--- a/source/blender/makesdna/DNA_lattice_types.h
+++ b/source/blender/makesdna/DNA_lattice_types.h
@@ -68,10 +68,6 @@ typedef struct Lattice {
struct MDeformVert *dvert;
char vgroup[64]; /* multiply the influence, MAX_VGROUP_NAME */
- /* used while deforming, always free and NULL after use */
- float *latticedata;
- float latmat[4][4];
-
struct EditLatt *editlatt;
} Lattice;
diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h
index f5473d3d84a..19c4e057a96 100644
--- a/source/blender/makesdna/DNA_linestyle_types.h
+++ b/source/blender/makesdna/DNA_linestyle_types.h
@@ -28,6 +28,10 @@
#ifndef __DNA_LINESTYLE_TYPES_H__
#define __DNA_LINESTYLE_TYPES_H__
+/** \file DNA_linestyle_types.h
+ * \ingroup DNA
+ */
+
#include "DNA_listBase.h"
#include "DNA_ID.h"
diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h
index 1b6b802f2de..4307ea57f15 100644
--- a/source/blender/makesdna/DNA_mask_types.h
+++ b/source/blender/makesdna/DNA_mask_types.h
@@ -58,15 +58,18 @@ typedef struct Mask {
typedef struct MaskParent {
// int flag; /* parenting flags */ /* not used */
- int pad;
int id_type; /* type of parenting */
+ int type; /* type of parenting */
ID *id; /* ID block of entity to which mask/spline is parented to
* in case of parenting to movie tracking data set to MovieClip datablock */
char parent[64]; /* entity of parent to which parenting happened
* in case of parenting to movie tracking data contains name of layer */
char sub_parent[64]; /* sub-entity of parent to which parenting happened
* in case of parenting to movie tracking data contains name of track */
- float parent_orig[2]; /* track location at the moment of parenting */
+ float parent_orig[2]; /* track location at the moment of parenting,
+ * stored in mask space*/
+
+ float parent_corners_orig[4][2]; /* Original corners of plane track at the moment of parenting */
} MaskParent;
typedef struct MaskSplinePointUW {
@@ -141,6 +144,12 @@ typedef struct MaskLayer {
/* MaskParent->flag */
/* #define MASK_PARENT_ACTIVE (1 << 0) */ /* UNUSED */
+/* MaskParent->type */
+enum {
+ MASK_PARENT_POINT_TRACK = 0, /* parenting happens to point track */
+ MASK_PARENT_PLANE_TRACK = 1, /* parenting happens to plane track */
+};
+
/* MaskSpline->flag */
/* reserve (1 << 0) for SELECT */
enum {
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index e37d1368892..7cdb79232a9 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -79,7 +79,7 @@ typedef struct Mesh {
* real faces are now stored in nface.*/
struct MFace *mface; /* array of mesh object mode faces for tessellation */
struct MTFace *mtface; /* store tessellation face UV's and texture here */
- struct TFace *tface; /* depecrated, use mtface */
+ struct TFace *tface DNA_DEPRECATED; /* deprecated, use mtface */
struct MVert *mvert; /* array of verts */
struct MEdge *medge; /* array of edges */
struct MDeformVert *dvert; /* deformgroup vertices */
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 9f9bc25a61c..1114549f2da 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -42,7 +42,7 @@ struct Image;
typedef struct MFace {
unsigned int v1, v2, v3, v4;
short mat_nr;
- char edcode, flag; /* we keep edcode, for conversion to edges draw flags in old files */
+ char edcode, flag; /* we keep edcode, for conversion to edges draw flags in old files */
} MFace;
typedef struct MEdge {
@@ -52,44 +52,42 @@ typedef struct MEdge {
} MEdge;
typedef struct MDeformWeight {
- int def_nr;
- float weight;
+ int def_nr;
+ float weight;
} MDeformWeight;
typedef struct MDeformVert {
struct MDeformWeight *dw;
int totweight;
- int flag; /* flag only in use for weightpaint now */
+ int flag; /* flag only in use for weightpaint now */
} MDeformVert;
typedef struct MVert {
- float co[3];
- short no[3];
+ float co[3];
+ short no[3];
char flag, bweight;
} MVert;
/* tessellation vertex color data.
- * at the moment alpha is abused for vertex painting
- * and not used for transparency, note that red and blue are swapped */
+ * at the moment alpha is abused for vertex painting and not used for transparency, note that red and blue are swapped
+ */
typedef struct MCol {
char a, r, g, b;
} MCol;
-/* new face structure, replaces MFace, which is now
- * only used for storing tessellations.*/
+/* new face structure, replaces MFace, which is now only used for storing tessellations.*/
typedef struct MPoly {
/* offset into loop array and number of loops in the face */
int loopstart;
- int totloop; /* keep signed since we need to subtract when getting the previous loop */
+ int totloop; /* keep signed since we need to subtract when getting the previous loop */
short mat_nr;
char flag, pad;
} MPoly;
-/* the e here is because we want to move away from
- * relying on edge hashes.*/
+/* the e here is because we want to move away from relying on edge hashes.*/
typedef struct MLoop {
- unsigned int v; /*vertex index*/
- unsigned int e; /*edge index*/
+ unsigned int v; /* vertex index */
+ unsigned int e; /* edge index */
} MLoop;
typedef struct MTexPoly {
@@ -114,9 +112,11 @@ typedef struct MLoopUV {
} MLoopUV;
/*mloopuv->flag*/
-#define MLOOPUV_EDGESEL 1
-#define MLOOPUV_VERTSEL 2
-#define MLOOPUV_PINNED 4
+enum {
+ MLOOPUV_EDGESEL = (1 << 0),
+ MLOOPUV_VERTSEL = (1 << 1),
+ MLOOPUV_PINNED = (1 << 2),
+};
/**
* at the moment alpha is abused for vertex painting,
@@ -166,13 +166,13 @@ typedef struct MTFace {
/*Custom Data Properties*/
typedef struct MFloatProperty {
- float f;
+ float f;
} MFloatProperty;
typedef struct MIntProperty {
- int i;
+ int i;
} MIntProperty;
typedef struct MStringProperty {
- char s[255], s_len;
+ char s[255], s_len;
} MStringProperty;
typedef struct OrigSpaceFace {
@@ -188,11 +188,10 @@ typedef struct MDisps {
int totdisp;
int level;
float (*disps)[3];
-
- /* Used for hiding parts of a multires mesh. Essentially the multires
- * equivalent of MVert.flag's ME_HIDE bit.
- *
- * This is a bitmap, keep in sync with type used in BLI_bitmap.h */
+
+ /* Used for hiding parts of a multires mesh. Essentially the multires equivalent of MVert.flag's ME_HIDE bit.
+ * NOTE: This is a bitmap, keep in sync with type used in BLI_bitmap.h
+ */
unsigned int *hidden;
} MDisps;
@@ -200,15 +199,18 @@ typedef struct MDisps {
typedef struct MultiresCol {
float a, r, g, b;
} MultiresCol;
+
typedef struct MultiresColFace {
/* vertex colors */
MultiresCol col[4];
} MultiresColFace;
+
typedef struct MultiresFace {
unsigned int v[4];
unsigned int mid;
char flag, mat_nr, pad[2];
} MultiresFace;
+
typedef struct MultiresEdge {
unsigned int v[2];
unsigned int mid;
@@ -245,7 +247,7 @@ typedef struct Multires {
/** End Multires **/
typedef struct MRecast {
- int i;
+ int i;
} MRecast;
typedef struct GridPaintMask {
@@ -259,20 +261,19 @@ typedef struct GridPaintMask {
} GridPaintMask;
typedef enum MVertSkinFlag {
- /* Marks a vertex as the edge-graph root, used for calculating
- * rotations for all connected edges (recursively.) Also used to
- * choose a root when generating an armature. */
+ /* Marks a vertex as the edge-graph root, used for calculating rotations for all connected edges (recursively).
+ * Also used to choose a root when generating an armature.
+ */
MVERT_SKIN_ROOT = 1,
- /* Marks a branch vertex (vertex with more than two connected
- * edges) so that it's neighbors are directly hulled together,
- * rather than the default of generating intermediate frames. */
- MVERT_SKIN_LOOSE = 2
+ /* Marks a branch vertex (vertex with more than two connected edges), so that it's neighbors are
+ * directly hulled together, rather than the default of generating intermediate frames.
+ */
+ MVERT_SKIN_LOOSE = 2,
} MVertSkinFlag;
typedef struct MVertSkin {
- /* Radii of the skin, define how big the generated frames
- * are. Currently only the first two elements are used. */
+ /* Radii of the skin, define how big the generated frames are. Currently only the first two elements are used. */
float radius[3];
/* MVertSkinFlag */
@@ -285,7 +286,9 @@ typedef struct FreestyleEdge {
} FreestyleEdge;
/* FreestyleEdge->flag */
-#define FREESTYLE_EDGE_MARK 1
+enum {
+ FREESTYLE_EDGE_MARK = 1,
+};
typedef struct FreestyleFace {
char flag;
@@ -293,96 +296,118 @@ typedef struct FreestyleFace {
} FreestyleFace;
/* FreestyleFace->flag */
-#define FREESTYLE_FACE_MARK 1
-
-/* mvert->flag (1=SELECT) */
-#define ME_SPHERETEST 2
-#define ME_VERT_TMP_TAG 4
-#define ME_HIDE 16
-#define ME_VERT_MERGED (1<<6)
-#define ME_VERT_PBVH_UPDATE (1<<7)
-
-/* medge->flag (1=SELECT)*/
-#define ME_EDGEDRAW (1<<1)
-#define ME_SEAM (1<<2)
-#define ME_FGON (1<<3) /* no longer used (now we have ngons), only defined so we can clear it */
- /* reserve 16 for ME_HIDE */
-#define ME_EDGERENDER (1<<5)
-#define ME_LOOSEEDGE (1<<7)
-#define ME_EDGE_TMP_TAG (1 << 8)
-#define ME_SHARP (1<<9) /* only reason this flag remains a 'short' */
+enum {
+ FREESTYLE_FACE_MARK = 1,
+};
+
+/* mvert->flag */
+enum {
+/* SELECT = (1 << 0), */
+ ME_SPHERETEST = (1 << 1),
+ ME_VERT_TMP_TAG = (1 << 2),
+ ME_HIDE = (1 << 4),
+ ME_VERT_MERGED = (1 << 6),
+ ME_VERT_PBVH_UPDATE = (1 << 7),
+};
+
+/* medge->flag */
+enum {
+/* SELECT = (1 << 0), */
+ ME_EDGEDRAW = (1 << 1),
+ ME_SEAM = (1 << 2),
+ ME_FGON = (1 << 3), /* no longer used (now we have ngons), only defined so we can clear it */
+/* ME_HIDE = (1 << 4), */
+ ME_EDGERENDER = (1 << 5),
+ ME_LOOSEEDGE = (1 << 7),
+ ME_EDGE_TMP_TAG = (1 << 8),
+ ME_SHARP = (1 << 9), /* only reason this flag remains a 'short' */
+};
/* puno = vertexnormal (mface) */
-#define ME_PROJXY 16
-#define ME_PROJXZ 32
-#define ME_PROJYZ 64
+enum {
+ ME_PROJXY = (1 << 4),
+ ME_PROJXZ = (1 << 5),
+ ME_PROJYZ = (1 << 6),
+};
/* edcode (mface) */
-#define ME_V1V2 1
-#define ME_V2V3 2
-#define ME_V3V1 4
-#define ME_V3V4 4
-#define ME_V4V1 8
+enum {
+ ME_V1V2 = (1 << 0),
+ ME_V2V3 = (1 << 1),
+ ME_V3V1 = (1 << 2),
+ ME_V3V4 = ME_V3V1,
+ ME_V4V1 = (1 << 3),
+};
/* flag (mface) */
-#define ME_SMOOTH 1
-#define ME_FACE_SEL 2
-/* flag ME_HIDE==16 is used here too */
+enum {
+ ME_SMOOTH = (1 << 0),
+ ME_FACE_SEL = (1 << 1),
+/* ME_HIDE = (1 << 4), */
+};
#define ME_POLY_LOOP_PREV(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + (mp)->totloop - 1) % (mp)->totloop)])
#define ME_POLY_LOOP_NEXT(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + 1) % (mp)->totloop)])
/* mselect->type */
-#define ME_VSEL 0
-#define ME_ESEL 1
-#define ME_FSEL 2
+enum {
+ ME_VSEL = 0,
+ ME_ESEL = 1,
+ ME_FSEL = 2,
+};
/* mtface->flag */
-#define TF_SELECT 1 /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */
-#define TF_ACTIVE 2 /* deprecated! */
-#define TF_SEL1 4
-#define TF_SEL2 8
-#define TF_SEL3 16
-#define TF_SEL4 32
+enum {
+ TF_SELECT = (1 << 0), /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */
+ TF_ACTIVE = (1 << 1), /* deprecated! */
+ TF_SEL1 = (1 << 2),
+ TF_SEL2 = (1 << 3),
+ TF_SEL3 = (1 << 4),
+ TF_SEL4 = (1 << 5),
+};
/* mtface->mode */
-#define TF_DYNAMIC 1
-#define TF_ALPHASORT 2
-#define TF_TEX 4
-#define TF_SHAREDVERT 8
-#define TF_LIGHT 16
-
-#define TF_CONVERTED 32 /* tface converted to material */
-
-#define TF_SHAREDCOL 64
-#define TF_TILES 128 /* deprecated */
-#define TF_BILLBOARD 256
-#define TF_TWOSIDE 512
-#define TF_INVISIBLE 1024
-
-#define TF_OBCOL 2048
-#define TF_BILLBOARD2 4096 /* with Z axis constraint */
-#define TF_SHADOW 8192
-#define TF_BMFONT 16384
+enum {
+ TF_DYNAMIC = (1 << 0),
+ TF_ALPHASORT = (1 << 1),
+ TF_TEX = (1 << 2),
+ TF_SHAREDVERT = (1 << 3),
+ TF_LIGHT = (1 << 4),
+
+ TF_CONVERTED = (1 << 5), /* tface converted to material */
+
+ TF_SHAREDCOL = (1 << 6),
+ TF_TILES = (1 << 7), /* deprecated */
+ TF_BILLBOARD = (1 << 8),
+ TF_TWOSIDE = (1 << 9),
+ TF_INVISIBLE = (1 << 10),
+
+ TF_OBCOL = (1 << 11),
+ TF_BILLBOARD2 = (1 << 12), /* with Z axis constraint */
+ TF_SHADOW = (1 << 13),
+ TF_BMFONT = (1 << 14),
+};
/* mtface->transp, values 1-4 are used as flags in the GL, WARNING, TF_SUB cant work with this */
-#define TF_SOLID 0
-#define TF_ADD 1
-#define TF_ALPHA 2
-#define TF_CLIP 4 /* clipmap alpha/binary alpha all or nothing! */
-
-/* sub is not available in the user interface anymore */
-#define TF_SUB 3
+enum {
+ TF_SOLID = 0,
+ TF_ADD = (1 << 0),
+ TF_ALPHA = (1 << 1),
+ TF_CLIP = (1 << 2), /* clipmap alpha/binary alpha all or nothing! */
+ TF_SUB = 3, /* sub is not available in the user interface anymore */
+};
/* mtface->unwrap */
-#define TF_DEPRECATED1 1
-#define TF_DEPRECATED2 2
-#define TF_DEPRECATED3 4
-#define TF_DEPRECATED4 8
-#define TF_PIN1 16
-#define TF_PIN2 32
-#define TF_PIN3 64
-#define TF_PIN4 128
-
-#endif
+enum {
+ TF_DEPRECATED1 = (1 << 0),
+ TF_DEPRECATED2 = (1 << 1),
+ TF_DEPRECATED3 = (1 << 2),
+ TF_DEPRECATED4 = (1 << 3),
+ TF_PIN1 = (1 << 4),
+ TF_PIN2 = (1 << 5),
+ TF_PIN3 = (1 << 6),
+ TF_PIN4 = (1 << 7),
+};
+
+#endif /* __DNA_MESHDATA_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h
index 56683bf4797..8bbe53b33a6 100644
--- a/source/blender/makesdna/DNA_meta_types.h
+++ b/source/blender/makesdna/DNA_meta_types.h
@@ -65,8 +65,6 @@ typedef struct MetaBall {
ID id;
struct AnimData *adt;
- struct BoundBox *bb;
-
ListBase elems;
ListBase disp;
ListBase *editelems; /* not saved in files, note we use pointer for editmode check */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 0b07605d22d..6b4c225aab5 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -29,7 +29,8 @@
#include "DNA_listBase.h"
/* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE!
- * (ONLY ADD NEW ITEMS AT THE END) */
+ * (ONLY ADD NEW ITEMS AT THE END)
+ */
typedef enum ModifierType {
eModifierType_None = 0,
@@ -84,14 +85,14 @@ typedef enum ModifierType {
} ModifierType;
typedef enum ModifierMode {
- eModifierMode_Realtime = (1<<0),
- eModifierMode_Render = (1<<1),
- eModifierMode_Editmode = (1<<2),
- eModifierMode_OnCage = (1<<3),
- eModifierMode_Expanded = (1<<4),
- eModifierMode_Virtual = (1<<5),
- eModifierMode_ApplyOnSpline = (1<<6),
- eModifierMode_DisableTemporary = (1 << 31)
+ eModifierMode_Realtime = (1 << 0),
+ eModifierMode_Render = (1 << 1),
+ eModifierMode_Editmode = (1 << 2),
+ eModifierMode_OnCage = (1 << 3),
+ eModifierMode_Expanded = (1 << 4),
+ eModifierMode_Virtual = (1 << 5),
+ eModifierMode_ApplyOnSpline = (1 << 6),
+ eModifierMode_DisableTemporary = (1 << 31)
} ModifierMode;
typedef struct ModifierData {
@@ -99,19 +100,19 @@ typedef struct ModifierData {
int type, mode;
int stackindex, pad;
- char name[64]; /* MAX_NAME */
-
+ char name[64]; /* MAX_NAME */
+
/* XXX for timing info set by caller... solve later? (ton) */
struct Scene *scene;
-
+
char *error;
} ModifierData;
typedef enum {
- eSubsurfModifierFlag_Incremental = (1<<0),
- eSubsurfModifierFlag_DebugIncr = (1<<1),
- eSubsurfModifierFlag_ControlEdges = (1<<2),
- eSubsurfModifierFlag_SubsurfUv = (1<<3)
+ eSubsurfModifierFlag_Incremental = (1 << 0),
+ eSubsurfModifierFlag_DebugIncr = (1 << 1),
+ eSubsurfModifierFlag_ControlEdges = (1 << 2),
+ eSubsurfModifierFlag_SubsurfUv = (1 << 3),
} SubsurfModifierFlag;
/* not a real modifier */
@@ -120,7 +121,7 @@ typedef struct MappingInfoModifierData {
struct Tex *texture;
struct Object *map_object;
- char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
int uvlayer_tmp;
int texmapping;
} MappingInfoModifierData;
@@ -137,7 +138,7 @@ typedef struct LatticeModifierData {
ModifierData modifier;
struct Object *object;
- char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
float strength;
char pad[4];
} LatticeModifierData;
@@ -146,18 +147,20 @@ typedef struct CurveModifierData {
ModifierData modifier;
struct Object *object;
- char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
- short defaxis; /* axis along which curve deforms */
+ char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ short defaxis; /* axis along which curve deforms */
char pad[6];
} CurveModifierData;
/* CurveModifierData->defaxis */
-#define MOD_CURVE_POSX 1
-#define MOD_CURVE_POSY 2
-#define MOD_CURVE_POSZ 3
-#define MOD_CURVE_NEGX 4
-#define MOD_CURVE_NEGY 5
-#define MOD_CURVE_NEGZ 6
+enum {
+ MOD_CURVE_POSX = 1,
+ MOD_CURVE_POSY = 2,
+ MOD_CURVE_POSZ = 3,
+ MOD_CURVE_NEGX = 4,
+ MOD_CURVE_NEGY = 5,
+ MOD_CURVE_NEGZ = 6,
+};
typedef struct BuildModifierData {
ModifierData modifier;
@@ -169,20 +172,24 @@ typedef struct BuildModifierData {
/* Mask Modifier */
typedef struct MaskModifierData {
ModifierData modifier;
-
- struct Object *ob_arm; /* armature to use to in place of hardcoded vgroup */
- char vgroup[64]; /* name of vertex group to use to mask, MAX_VGROUP_NAME */
-
- int mode; /* using armature or hardcoded vgroup */
- int flag; /* flags for various things */
+
+ struct Object *ob_arm; /* armature to use to in place of hardcoded vgroup */
+ char vgroup[64]; /* name of vertex group to use to mask, MAX_VGROUP_NAME */
+
+ int mode; /* using armature or hardcoded vgroup */
+ int flag; /* flags for various things */
} MaskModifierData;
/* Mask Modifier -> mode */
-#define MOD_MASK_MODE_VGROUP 0
-#define MOD_MASK_MODE_ARM 1
+enum {
+ MOD_MASK_MODE_VGROUP = 0,
+ MOD_MASK_MODE_ARM = 1,
+};
/* Mask Modifier -> flag */
-#define MOD_MASK_INV (1<<0)
+enum {
+ MOD_MASK_INV = (1 << 0),
+};
typedef struct ArrayModifierData {
ModifierData modifier;
@@ -229,18 +236,24 @@ typedef struct ArrayModifierData {
} ArrayModifierData;
/* ArrayModifierData->fit_type */
-#define MOD_ARR_FIXEDCOUNT 0
-#define MOD_ARR_FITLENGTH 1
-#define MOD_ARR_FITCURVE 2
+enum {
+ MOD_ARR_FIXEDCOUNT = 0,
+ MOD_ARR_FITLENGTH = 1,
+ MOD_ARR_FITCURVE = 2,
+};
/* ArrayModifierData->offset_type */
-#define MOD_ARR_OFF_CONST (1<<0)
-#define MOD_ARR_OFF_RELATIVE (1<<1)
-#define MOD_ARR_OFF_OBJ (1<<2)
+enum {
+ MOD_ARR_OFF_CONST = (1 << 0),
+ MOD_ARR_OFF_RELATIVE = (1 << 1),
+ MOD_ARR_OFF_OBJ = (1 << 2),
+};
/* ArrayModifierData->flags */
-#define MOD_ARR_MERGE (1<<0)
-#define MOD_ARR_MERGEFINAL (1<<1)
+enum {
+ MOD_ARR_MERGE = (1 << 0),
+ MOD_ARR_MERGEFINAL = (1 << 1),
+};
typedef struct MirrorModifierData {
ModifierData modifier;
@@ -252,14 +265,16 @@ typedef struct MirrorModifierData {
} MirrorModifierData;
/* MirrorModifierData->flag */
-#define MOD_MIR_CLIPPING (1<<0)
-#define MOD_MIR_MIRROR_U (1<<1)
-#define MOD_MIR_MIRROR_V (1<<2)
-#define MOD_MIR_AXIS_X (1<<3)
-#define MOD_MIR_AXIS_Y (1<<4)
-#define MOD_MIR_AXIS_Z (1<<5)
-#define MOD_MIR_VGROUP (1<<6)
-#define MOD_MIR_NO_MERGE (1<<7)
+enum {
+ MOD_MIR_CLIPPING = (1 << 0),
+ MOD_MIR_MIRROR_U = (1 << 1),
+ MOD_MIR_MIRROR_V = (1 << 2),
+ MOD_MIR_AXIS_X = (1 << 3),
+ MOD_MIR_AXIS_Y = (1 << 4),
+ MOD_MIR_AXIS_Z = (1 << 5),
+ MOD_MIR_VGROUP = (1 << 6),
+ MOD_MIR_NO_MERGE = (1 << 7),
+};
typedef struct EdgeSplitModifierData {
ModifierData modifier;
@@ -269,8 +284,10 @@ typedef struct EdgeSplitModifierData {
} EdgeSplitModifierData;
/* EdgeSplitModifierData->flags */
-#define MOD_EDGESPLIT_FROMANGLE (1<<1)
-#define MOD_EDGESPLIT_FROMFLAG (1<<2)
+enum {
+ MOD_EDGESPLIT_FROMANGLE = (1 << 1),
+ MOD_EDGESPLIT_FROMFLAG = (1 << 2),
+};
typedef struct BevelModifierData {
ModifierData modifier;
@@ -282,29 +299,29 @@ typedef struct BevelModifierData {
short val_flags; /* flags used to interpret the bevel value */
short lim_flags; /* flags to tell the tool how to limit the bevel */
short e_flags; /* flags to direct how edge weights are applied to verts */
- float bevel_angle; /* if the MOD_BEVEL_ANGLE is set, this will be how "sharp" an edge must be before it gets beveled */
- char defgrp_name[64]; /* if the MOD_BEVEL_VWEIGHT option is set, this will be the name of the vert group, MAX_VGROUP_NAME */
+ /* if the MOD_BEVEL_ANGLE is set, this will be how "sharp" an edge must be before it gets beveled */
+ float bevel_angle;
+ /* if the MOD_BEVEL_VWEIGHT option is set, this will be the name of the vert group, MAX_VGROUP_NAME */
+ char defgrp_name[64];
} BevelModifierData;
-#define MOD_BEVEL_VERT (1 << 1)
-// #define MOD_BEVEL_RADIUS (1 << 2)
-#define MOD_BEVEL_ANGLE (1 << 3)
-#define MOD_BEVEL_WEIGHT (1 << 4)
-#define MOD_BEVEL_VGROUP (1 << 5)
-#define MOD_BEVEL_EMIN (1 << 7)
-#define MOD_BEVEL_EMAX (1 << 8)
-// #define MOD_BEVEL_RUNNING (1 << 9)
-// #define MOD_BEVEL_RES (1 << 10)
-// #define MOD_BEVEL_EVEN (1 << 11) /* this is a new setting not related to old (trunk bmesh bevel code) but adding
-// * here because they are mixed - campbell */
-// #define MOD_BEVEL_DIST (1 << 12) /* same as above */
-#define MOD_BEVEL_OVERLAP_OK (1 << 13)
-
-
-/* Smoke modifier flags */
-#define MOD_SMOKE_TYPE_DOMAIN (1 << 0)
-#define MOD_SMOKE_TYPE_FLOW (1 << 1)
-#define MOD_SMOKE_TYPE_COLL (1 << 2)
+enum {
+ MOD_BEVEL_VERT = (1 << 1),
+/* MOD_BEVEL_RADIUS = (1 << 2), */
+ MOD_BEVEL_ANGLE = (1 << 3),
+ MOD_BEVEL_WEIGHT = (1 << 4),
+ MOD_BEVEL_VGROUP = (1 << 5),
+ MOD_BEVEL_EMIN = (1 << 7),
+ MOD_BEVEL_EMAX = (1 << 8),
+/* MOD_BEVEL_RUNNING = (1 << 9), */
+/* MOD_BEVEL_RES = (1 << 10), */
+ /* This is a new setting not related to old (trunk bmesh bevel code)
+ * but adding here because they are mixed - campbell
+ */
+/* MOD_BEVEL_EVEN = (1 << 11), */
+/* MOD_BEVEL_DIST = (1 << 12), */ /* same as above */
+ MOD_BEVEL_OVERLAP_OK = (1 << 13),
+};
typedef struct SmokeModifierData {
ModifierData modifier;
@@ -316,70 +333,79 @@ typedef struct SmokeModifierData {
int type; /* domain, inflow, outflow, ... */
} SmokeModifierData;
+/* Smoke modifier flags */
+enum {
+ MOD_SMOKE_TYPE_DOMAIN = (1 << 0),
+ MOD_SMOKE_TYPE_FLOW = (1 << 1),
+ MOD_SMOKE_TYPE_COLL = (1 << 2),
+};
+
typedef struct DisplaceModifierData {
ModifierData modifier;
/* keep in sync with MappingInfoModifierData */
struct Tex *texture;
struct Object *map_object;
- char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
int uvlayer_tmp;
int texmapping;
/* end MappingInfoModifierData */
float strength;
int direction;
- char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
float midlevel;
int pad;
} DisplaceModifierData;
/* DisplaceModifierData->direction */
enum {
- MOD_DISP_DIR_X = 0,
- MOD_DISP_DIR_Y = 1,
- MOD_DISP_DIR_Z = 2,
- MOD_DISP_DIR_NOR = 3,
+ MOD_DISP_DIR_X = 0,
+ MOD_DISP_DIR_Y = 1,
+ MOD_DISP_DIR_Z = 2,
+ MOD_DISP_DIR_NOR = 3,
MOD_DISP_DIR_RGB_XYZ = 4,
};
/* DisplaceModifierData->texmapping */
enum {
- MOD_DISP_MAP_LOCAL = 0,
+ MOD_DISP_MAP_LOCAL = 0,
MOD_DISP_MAP_GLOBAL = 1,
MOD_DISP_MAP_OBJECT = 2,
- MOD_DISP_MAP_UV = 3
+ MOD_DISP_MAP_UV = 3,
};
typedef struct UVProjectModifierData {
ModifierData modifier;
/* the objects which do the projecting */
- struct Object *projectors[10]; /* MOD_UVPROJECT_MAX */
- struct Image *image; /* the image to project */
+ struct Object *projectors[10]; /* MOD_UVPROJECT_MAXPROJECTORS */
+ struct Image *image; /* the image to project */
int flags;
int num_projectors;
float aspectx, aspecty;
float scalex, scaley;
- char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
int uvlayer_tmp, pad;
} UVProjectModifierData;
#define MOD_UVPROJECT_MAXPROJECTORS 10
/* UVProjectModifierData->flags */
-#define MOD_UVPROJECT_OVERRIDEIMAGE (1<<0)
+enum {
+ MOD_UVPROJECT_OVERRIDEIMAGE = (1 << 0),
+};
typedef struct DecimateModifierData {
ModifierData modifier;
float percent; /* (mode == MOD_DECIM_MODE_COLLAPSE) */
- short iter; /* (mode == MOD_DECIM_MODE_UNSUBDIV) */
+ short iter; /* (mode == MOD_DECIM_MODE_UNSUBDIV) */
char delimit; /* (mode == MOD_DECIM_MODE_DISSOLVE) */
char pad;
- float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */
+ float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */
- char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
short flag, mode;
/* runtime only */
@@ -389,20 +415,15 @@ typedef struct DecimateModifierData {
enum {
MOD_DECIM_FLAG_INVERT_VGROUP = (1 << 0),
MOD_DECIM_FLAG_TRIANGULATE = (1 << 1), /* for collapse only. dont convert tri pairs back to quads */
- MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS = (1 << 2) /* for dissolve only. collapse all verts between 2 faces */
+ MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS = (1 << 2), /* for dissolve only. collapse all verts between 2 faces */
};
enum {
MOD_DECIM_MODE_COLLAPSE,
MOD_DECIM_MODE_UNSUBDIV,
- MOD_DECIM_MODE_DISSOLVE /* called planar in the UI */
+ MOD_DECIM_MODE_DISSOLVE, /* called planar in the UI */
};
-/* Smooth modifier flags */
-#define MOD_SMOOTH_X (1<<1)
-#define MOD_SMOOTH_Y (1<<2)
-#define MOD_SMOOTH_Z (1<<3)
-
typedef struct SmoothModifierData {
ModifierData modifier;
float fac;
@@ -411,17 +432,12 @@ typedef struct SmoothModifierData {
} SmoothModifierData;
-/* Cast modifier flags */
-#define MOD_CAST_X (1<<1)
-#define MOD_CAST_Y (1<<2)
-#define MOD_CAST_Z (1<<3)
-#define MOD_CAST_USE_OB_TRANSFORM (1<<4)
-#define MOD_CAST_SIZE_FROM_RADIUS (1<<5)
-
-/* Cast modifier projection types */
-#define MOD_CAST_TYPE_SPHERE 0
-#define MOD_CAST_TYPE_CYLINDER 1
-#define MOD_CAST_TYPE_CUBOID 2
+/* Smooth modifier flags */
+enum {
+ MOD_SMOOTH_X = (1 << 1),
+ MOD_SMOOTH_Y = (1 << 2),
+ MOD_SMOOTH_Z = (1 << 3),
+};
typedef struct CastModifierData {
ModifierData modifier;
@@ -430,18 +446,26 @@ typedef struct CastModifierData {
float fac;
float radius;
float size;
- char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
short flag, type;
} CastModifierData;
-/* WaveModifierData.flag */
-#define MOD_WAVE_X (1<<1)
-#define MOD_WAVE_Y (1<<2)
-#define MOD_WAVE_CYCL (1<<3)
-#define MOD_WAVE_NORM (1<<4)
-#define MOD_WAVE_NORM_X (1<<5)
-#define MOD_WAVE_NORM_Y (1<<6)
-#define MOD_WAVE_NORM_Z (1<<7)
+/* Cast modifier flags */
+enum {
+ /* And what bout (1 << 0) flag? ;) */
+ MOD_CAST_X = (1 << 1),
+ MOD_CAST_Y = (1 << 2),
+ MOD_CAST_Z = (1 << 3),
+ MOD_CAST_USE_OB_TRANSFORM = (1 << 4),
+ MOD_CAST_SIZE_FROM_RADIUS = (1 << 5),
+};
+
+/* Cast modifier projection types */
+enum {
+ MOD_CAST_TYPE_SPHERE = 0,
+ MOD_CAST_TYPE_CYLINDER = 1,
+ MOD_CAST_TYPE_CUBOID = 2,
+};
typedef struct WaveModifierData {
ModifierData modifier;
@@ -449,13 +473,13 @@ typedef struct WaveModifierData {
/* keep in sync with MappingInfoModifierData */
struct Tex *texture;
struct Object *map_object;
- char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
int uvlayer_tmp;
int texmapping;
/* end MappingInfoModifierData */
struct Object *objectcenter;
- char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
short flag, pad;
@@ -466,30 +490,42 @@ typedef struct WaveModifierData {
float pad1;
} WaveModifierData;
+/* WaveModifierData.flag */
+enum {
+ /* And what bout (1 << 0) flag? ;) */
+ MOD_WAVE_X = (1 << 1),
+ MOD_WAVE_Y = (1 << 2),
+ MOD_WAVE_CYCL = (1 << 3),
+ MOD_WAVE_NORM = (1 << 4),
+ MOD_WAVE_NORM_X = (1 << 5),
+ MOD_WAVE_NORM_Y = (1 << 6),
+ MOD_WAVE_NORM_Z = (1 << 7),
+};
+
typedef struct ArmatureModifierData {
ModifierData modifier;
- short deformflag, multi; /* deformflag replaces armature->deformflag */
+ short deformflag, multi; /* deformflag replaces armature->deformflag */
int pad2;
struct Object *object;
- float *prevCos; /* stored input of previous modifier, for vertexgroup blending */
- char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ float *prevCos; /* stored input of previous modifier, for vertexgroup blending */
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
} ArmatureModifierData;
typedef struct HookModifierData {
ModifierData modifier;
struct Object *object;
- char subtarget[64]; /* optional name of bone target, MAX_ID_NAME-2 */
-
- float parentinv[4][4]; /* matrix making current transform unmodified */
- float cent[3]; /* visualization of hook */
- float falloff; /* if not zero, falloff is distance where influence zero */
-
- int *indexar; /* if NULL, it's using vertexgroup */
+ char subtarget[64]; /* optional name of bone target, MAX_ID_NAME-2 */
+
+ float parentinv[4][4]; /* matrix making current transform unmodified */
+ float cent[3]; /* visualization of hook */
+ float falloff; /* if not zero, falloff is distance where influence zero */
+
+ int *indexar; /* if NULL, it's using vertexgroup */
int totindex;
float force;
- char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
} HookModifierData;
typedef struct SoftbodyModifierData {
@@ -497,36 +533,36 @@ typedef struct SoftbodyModifierData {
} SoftbodyModifierData;
typedef struct ClothModifierData {
- ModifierData modifier;
+ ModifierData modifier;
- struct Scene *scene; /* the context, time etc is here */
- struct Cloth *clothObject; /* The internal data structure for cloth. */
- struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */
+ struct Scene *scene; /* the context, time etc is here */
+ 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.h */
struct ListBase ptcaches;
} ClothModifierData;
typedef struct CollisionModifierData {
- ModifierData modifier;
-
- struct MVert *x; /* position at the beginning of the frame */
- struct MVert *xnew; /* position at the end of the frame */
- struct MVert *xold; /* unsued atm, but was discussed during sprint */
+ ModifierData modifier;
+
+ struct MVert *x; /* position at the beginning of the frame */
+ struct MVert *xnew; /* position at the end of the frame */
+ struct MVert *xold; /* unused atm, but was discussed during sprint */
struct MVert *current_xnew; /* new position at the actual inter-frame step */
- struct MVert *current_x; /* position at the actual inter-frame step */
- struct MVert *current_v; /* (xnew - x) at the actual inter-frame step */
-
- struct MFace *mfaces; /* object face data */
-
+ struct MVert *current_x; /* position at the actual inter-frame step */
+ struct MVert *current_v; /* (xnew - x) at the actual inter-frame step */
+
+ struct MFace *mfaces; /* object face data */
+
unsigned int numverts;
unsigned int numfaces;
- float time_x, time_xnew; /* cfra time of modifier */
- struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
+ float time_x, time_xnew; /* cfra time of modifier */
+ struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */
} CollisionModifierData;
typedef struct SurfaceModifierData {
- ModifierData modifier;
+ ModifierData modifier;
struct MVert *x; /* old position */
struct MVert *v; /* velocity */
@@ -538,11 +574,6 @@ typedef struct SurfaceModifierData {
int cfra, numverts;
} SurfaceModifierData;
-typedef enum {
- eBooleanModifierOp_Intersect = 0,
- eBooleanModifierOp_Union = 1,
- eBooleanModifierOp_Difference = 2,
-} BooleanModifierOp;
typedef struct BooleanModifierData {
ModifierData modifier;
@@ -550,11 +581,11 @@ typedef struct BooleanModifierData {
int operation, pad;
} BooleanModifierData;
-#define MOD_MDEF_INVERT_VGROUP (1<<0)
-#define MOD_MDEF_DYNAMIC_BIND (1<<1)
-
-#define MOD_MDEF_VOLUME 0
-#define MOD_MDEF_SURFACE 1
+typedef enum {
+ eBooleanModifierOp_Intersect = 0,
+ eBooleanModifierOp_Union = 1,
+ eBooleanModifierOp_Difference = 2,
+} BooleanModifierOp;
typedef struct MDefInfluence {
int vertex;
@@ -569,45 +600,49 @@ typedef struct MDefCell {
typedef struct MeshDeformModifierData {
ModifierData modifier;
- struct Object *object; /* mesh object */
- char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ struct Object *object; /* mesh object */
+ char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
short gridsize, flag, mode, pad;
/* result of static binding */
- MDefInfluence *bindinfluences; /* influences */
- int *bindoffsets; /* offsets into influences array */
- float *bindcagecos; /* coordinates that cage was bound with */
- int totvert, totcagevert; /* total vertices in mesh and cage */
+ MDefInfluence *bindinfluences; /* influences */
+ int *bindoffsets; /* offsets into influences array */
+ float *bindcagecos; /* coordinates that cage was bound with */
+ int totvert, totcagevert; /* total vertices in mesh and cage */
/* result of dynamic binding */
- MDefCell *dyngrid; /* grid with dynamic binding cell points */
- MDefInfluence *dyninfluences; /* dynamic binding vertex influences */
- int *dynverts, *pad2; /* is this vertex bound or not? */
- int dyngridsize; /* size of the dynamic bind grid */
- int totinfluence; /* total number of vertex influences */
- float dyncellmin[3]; /* offset of the dynamic bind grid */
- float dyncellwidth; /* width of dynamic bind cell */
- float bindmat[4][4]; /* matrix of cage at binding time */
+ MDefCell *dyngrid; /* grid with dynamic binding cell points */
+ MDefInfluence *dyninfluences; /* dynamic binding vertex influences */
+ int *dynverts, *pad2; /* is this vertex bound or not? */
+ int dyngridsize; /* size of the dynamic bind grid */
+ int totinfluence; /* total number of vertex influences */
+ float dyncellmin[3]; /* offset of the dynamic bind grid */
+ float dyncellwidth; /* width of dynamic bind cell */
+ float bindmat[4][4]; /* matrix of cage at binding time */
/* deprecated storage */
- float *bindweights; /* deprecated inefficient storage */
- float *bindcos; /* deprecated storage of cage coords */
+ float *bindweights; /* deprecated inefficient storage */
+ float *bindcos; /* deprecated storage of cage coords */
/* runtime */
- void (*bindfunc)(struct Scene *scene,
- struct MeshDeformModifierData *mmd,
- float *vertexcos, int totvert, float cagemat[4][4]);
+ void (*bindfunc)(struct Scene *scene, struct MeshDeformModifierData *mmd,
+ float *vertexcos, int totvert, float cagemat[4][4]);
} MeshDeformModifierData;
-typedef enum {
- eParticleSystemFlag_Pars = (1<<0),
- eParticleSystemFlag_psys_updated = (1<<1),
- eParticleSystemFlag_file_loaded = (1<<2),
-} ParticleSystemModifierFlag;
+enum {
+ MOD_MDEF_INVERT_VGROUP = (1 << 0),
+ MOD_MDEF_DYNAMIC_BIND = (1 << 1),
+};
+
+enum {
+ MOD_MDEF_VOLUME = 0,
+ MOD_MDEF_SURFACE = 1,
+};
typedef struct ParticleSystemModifierData {
ModifierData modifier;
+
struct ParticleSystem *psys;
struct DerivedMesh *dm;
int totdmvert, totdmedge, totdmface;
@@ -615,38 +650,46 @@ typedef struct ParticleSystemModifierData {
} ParticleSystemModifierData;
typedef enum {
- eParticleInstanceFlag_Parents = (1<<0),
- eParticleInstanceFlag_Children = (1<<1),
- eParticleInstanceFlag_Path = (1<<2),
- eParticleInstanceFlag_Unborn = (1<<3),
- eParticleInstanceFlag_Alive = (1<<4),
- eParticleInstanceFlag_Dead = (1<<5),
- eParticleInstanceFlag_KeepShape = (1<<6),
- eParticleInstanceFlag_UseSize = (1<<7),
+ eParticleSystemFlag_Pars = (1 << 0),
+ eParticleSystemFlag_psys_updated = (1 << 1),
+ eParticleSystemFlag_file_loaded = (1 << 2),
+} ParticleSystemModifierFlag;
+
+typedef enum {
+ eParticleInstanceFlag_Parents = (1 << 0),
+ eParticleInstanceFlag_Children = (1 << 1),
+ eParticleInstanceFlag_Path = (1 << 2),
+ eParticleInstanceFlag_Unborn = (1 << 3),
+ eParticleInstanceFlag_Alive = (1 << 4),
+ eParticleInstanceFlag_Dead = (1 << 5),
+ eParticleInstanceFlag_KeepShape = (1 << 6),
+ eParticleInstanceFlag_UseSize = (1 << 7),
} ParticleInstanceModifierFlag;
typedef struct ParticleInstanceModifierData {
ModifierData modifier;
+
struct Object *ob;
short psys, flag, axis, rt;
float position, random_position;
} ParticleInstanceModifierData;
typedef enum {
- eExplodeFlag_CalcFaces = (1<<0),
- eExplodeFlag_PaSize = (1<<1),
- eExplodeFlag_EdgeCut = (1<<2),
- eExplodeFlag_Unborn = (1<<3),
- eExplodeFlag_Alive = (1<<4),
- eExplodeFlag_Dead = (1<<5),
+ eExplodeFlag_CalcFaces = (1 << 0),
+ eExplodeFlag_PaSize = (1 << 1),
+ eExplodeFlag_EdgeCut = (1 << 2),
+ eExplodeFlag_Unborn = (1 << 3),
+ eExplodeFlag_Alive = (1 << 4),
+ eExplodeFlag_Dead = (1 << 5),
} ExplodeModifierFlag;
typedef struct ExplodeModifierData {
ModifierData modifier;
+
int *facepa;
short flag, vgroup;
float protect;
- char uvname[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char uvname[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
} ExplodeModifierData;
typedef struct MultiresModifierData {
@@ -657,83 +700,93 @@ typedef struct MultiresModifierData {
} MultiresModifierData;
typedef enum {
- eMultiresModifierFlag_ControlEdges = (1<<0),
- eMultiresModifierFlag_PlainUv = (1<<1),
+ eMultiresModifierFlag_ControlEdges = (1 << 0),
+ eMultiresModifierFlag_PlainUv = (1 << 1),
} MultiresModifierFlag;
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.h */
+ struct PointCache *point_cache; /* definition is in DNA_object_force.h */
} FluidsimModifierData;
typedef struct ShrinkwrapModifierData {
ModifierData modifier;
- struct Object *target; /* shrink target */
+ struct Object *target; /* shrink target */
struct Object *auxTarget; /* additional shrink target */
- char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
- float keepDist; /* distance offset to keep from mesh/projection point */
- short shrinkType; /* shrink type projection */
- short shrinkOpts; /* shrink options */
- float projLimit; /* limit the projection ray cast */
- char projAxis; /* axis to project over */
-
- /*
- * if using projection over vertex normal this controls the
- * the level of subsurface that must be done before getting the
- * vertex coordinates and normal
+ char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ float keepDist; /* distance offset to keep from mesh/projection point */
+ short shrinkType; /* shrink type projection */
+ short shrinkOpts; /* shrink options */
+ float projLimit; /* limit the projection ray cast */
+ char projAxis; /* axis to project over */
+
+ /* If using projection over vertex normal this controls the level of subsurface that must be done
+ * before getting the vertex coordinates and normal
*/
char subsurfLevels;
char pad[2];
-
} ShrinkwrapModifierData;
/* Shrinkwrap->shrinkType */
-#define MOD_SHRINKWRAP_NEAREST_SURFACE 0
-#define MOD_SHRINKWRAP_PROJECT 1
-#define MOD_SHRINKWRAP_NEAREST_VERTEX 2
+enum {
+ MOD_SHRINKWRAP_NEAREST_SURFACE = 0,
+ MOD_SHRINKWRAP_PROJECT = 1,
+ MOD_SHRINKWRAP_NEAREST_VERTEX = 2,
+};
/* Shrinkwrap->shrinkOpts */
-#define MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR (1<<0) /* allow shrinkwrap to move the vertex in the positive direction of axis */
-#define MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR (1<<1) /* allow shrinkwrap to move the vertex in the negative direction of axis */
+enum {
+ /* allow shrinkwrap to move the vertex in the positive direction of axis */
+ MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR = (1 << 0),
+ /* allow shrinkwrap to move the vertex in the negative direction of axis */
+ MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR = (1 << 1),
-#define MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (1<<3) /* ignore vertex moves if a vertex ends projected on a front face of the target */
-#define MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (1<<4) /* ignore vertex moves if a vertex ends projected on a back face of the target */
+ /* ignore vertex moves if a vertex ends projected on a front face of the target */
+ MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE = (1 << 3),
+ /* ignore vertex moves if a vertex ends projected on a back face of the target */
+ MOD_SHRINKWRAP_CULL_TARGET_BACKFACE = (1 << 4),
-#define MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE (1<<5) /* distance is measure to the front face of the target */
+ MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE = (1 << 5), /* distance is measure to the front face of the target */
+};
-#define MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS (1<<0)
-#define MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS (1<<1)
-#define MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS (1<<2)
-#define MOD_SHRINKWRAP_PROJECT_OVER_NORMAL 0 /* projection over normal is used if no axis is selected */
+/* Shrinkwrap->projAxis */
+enum {
+ MOD_SHRINKWRAP_PROJECT_OVER_NORMAL = 0, /* projection over normal is used if no axis is selected */
+ MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS = (1 << 0),
+ MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS = (1 << 1),
+ MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS = (1 << 2),
+};
typedef struct SimpleDeformModifierData {
ModifierData modifier;
- struct Object *origin; /* object to control the origin of modifier space coordinates */
- char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
- float factor; /* factors to control simple deforms */
- float limit[2]; /* lower and upper limit */
+ struct Object *origin; /* object to control the origin of modifier space coordinates */
+ char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ float factor; /* factors to control simple deforms */
+ float limit[2]; /* lower and upper limit */
- char mode; /* deform function */
- char axis; /* lock axis (for taper and strech) */
+ char mode; /* deform function */
+ char axis; /* lock axis (for taper and strech) */
char pad[2];
} SimpleDeformModifierData;
-#define MOD_SIMPLEDEFORM_MODE_TWIST 1
-#define MOD_SIMPLEDEFORM_MODE_BEND 2
-#define MOD_SIMPLEDEFORM_MODE_TAPER 3
-#define MOD_SIMPLEDEFORM_MODE_STRETCH 4
-
-#define MOD_SIMPLEDEFORM_LOCK_AXIS_X (1<<0)
-#define MOD_SIMPLEDEFORM_LOCK_AXIS_Y (1<<1)
+enum {
+ MOD_SIMPLEDEFORM_MODE_TWIST = 1,
+ MOD_SIMPLEDEFORM_MODE_BEND = 2,
+ MOD_SIMPLEDEFORM_MODE_TAPER = 3,
+ MOD_SIMPLEDEFORM_MODE_STRETCH = 4,
+};
-#define MOD_UVPROJECT_MAX 10
+enum {
+ MOD_SIMPLEDEFORM_LOCK_AXIS_X = (1 << 0),
+ MOD_SIMPLEDEFORM_LOCK_AXIS_Y = (1 << 1),
+};
typedef struct ShapeKeyModifierData {
ModifierData modifier;
@@ -742,11 +795,12 @@ typedef struct ShapeKeyModifierData {
typedef struct SolidifyModifierData {
ModifierData modifier;
- char defgrp_name[64]; /* name of vertex group to use, MAX_VGROUP_NAME */
- float offset; /* new surface offset level*/
- float offset_fac; /* midpoint of the offset */
- float offset_fac_vg; /* factor for the minimum weight to use when vgroups are used, avoids 0.0 weights giving duplicate geometry */
- float offset_clamp; /* clamp offset based on surrounding geometry */
+ char defgrp_name[64]; /* name of vertex group to use, MAX_VGROUP_NAME */
+ float offset; /* new surface offset level*/
+ float offset_fac; /* midpoint of the offset */
+ /* factor for the minimum weight to use when vgroups are used, avoids 0.0 weights giving duplicate geometry */
+ float offset_fac_vg;
+ float offset_clamp; /* clamp offset based on surrounding geometry */
float pad;
float crease_inner;
float crease_outer;
@@ -756,98 +810,107 @@ typedef struct SolidifyModifierData {
short mat_ofs_rim;
} SolidifyModifierData;
-#define MOD_SOLIDIFY_RIM (1 << 0)
-#define MOD_SOLIDIFY_EVEN (1 << 1)
-#define MOD_SOLIDIFY_NORMAL_CALC (1 << 2)
-#define MOD_SOLIDIFY_VGROUP_INV (1 << 3)
-#define MOD_SOLIDIFY_RIM_MATERIAL (1 << 4) /* deprecated, used in do_versions */
-#define MOD_SOLIDIFY_FLIP (1 << 5)
+enum {
+ MOD_SOLIDIFY_RIM = (1 << 0),
+ MOD_SOLIDIFY_EVEN = (1 << 1),
+ MOD_SOLIDIFY_NORMAL_CALC = (1 << 2),
+ MOD_SOLIDIFY_VGROUP_INV = (1 << 3),
+ MOD_SOLIDIFY_RIM_MATERIAL = (1 << 4), /* deprecated, used in do_versions */
+ MOD_SOLIDIFY_FLIP = (1 << 5),
+};
typedef struct ScrewModifierData {
ModifierData modifier;
+
struct Object *ob_axis;
- int steps;
- int render_steps;
- int iter;
- float screw_ofs;
- float angle;
- short axis;
- short flag;
+ int steps;
+ int render_steps;
+ int iter;
+ float screw_ofs;
+ float angle;
+ short axis;
+ short flag;
} ScrewModifierData;
-#define MOD_SCREW_NORMAL_FLIP (1 << 0)
-#define MOD_SCREW_NORMAL_CALC (1 << 1)
-#define MOD_SCREW_OBJECT_OFFSET (1 << 2)
-// #define MOD_SCREW_OBJECT_ANGLE (1 << 4)
-#define MOD_SCREW_SMOOTH_SHADING (1 << 5)
+enum {
+ MOD_SCREW_NORMAL_FLIP = (1 << 0),
+ MOD_SCREW_NORMAL_CALC = (1 << 1),
+ MOD_SCREW_OBJECT_OFFSET = (1 << 2),
+/* MOD_SCREW_OBJECT_ANGLE = (1 << 4), */
+ MOD_SCREW_SMOOTH_SHADING = (1 << 5),
+};
typedef struct OceanModifierData {
ModifierData modifier;
-
+
struct Ocean *ocean;
struct OceanCache *oceancache;
- int resolution;
- int spatial_size;
-
- float wind_velocity;
-
- float damp;
- float smallest_wave;
- float depth;
-
- float wave_alignment;
- float wave_direction;
- float wave_scale;
-
- float chop_amount;
- float foam_coverage;
- float time;
-
- int bakestart;
- int bakeend;
-
- char cachepath[1024]; // FILE_MAX
- char foamlayername[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
- char cached;
- char geometry_mode;
+ int resolution;
+ int spatial_size;
- char flag;
- char refresh;
+ float wind_velocity;
- short repeat_x;
- short repeat_y;
+ float damp;
+ float smallest_wave;
+ float depth;
- int seed;
+ float wave_alignment;
+ float wave_direction;
+ float wave_scale;
- float size;
-
- float foam_fade;
+ float chop_amount;
+ float foam_coverage;
+ float time;
- int pad;
+ int bakestart;
+ int bakeend;
-} OceanModifierData;
+ char cachepath[1024]; /* FILE_MAX */
+ char foamlayername[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char cached;
+ char geometry_mode;
+
+ char flag;
+ char refresh;
+
+ short repeat_x;
+ short repeat_y;
+
+ int seed;
-#define MOD_OCEAN_GEOM_GENERATE 0
-#define MOD_OCEAN_GEOM_DISPLACE 1
-#define MOD_OCEAN_GEOM_SIM_ONLY 2
+ float size;
+
+ float foam_fade;
-#define MOD_OCEAN_REFRESH_RESET 1
-#define MOD_OCEAN_REFRESH_SIM 2
-#define MOD_OCEAN_REFRESH_ADD 4
-#define MOD_OCEAN_REFRESH_CLEAR_CACHE 8
-#define MOD_OCEAN_REFRESH_TOPOLOGY 16
+ int pad;
+} OceanModifierData;
-#define MOD_OCEAN_GENERATE_FOAM 1
-#define MOD_OCEAN_GENERATE_NORMALS 2
+enum {
+ MOD_OCEAN_GEOM_GENERATE = 0,
+ MOD_OCEAN_GEOM_DISPLACE = 1,
+ MOD_OCEAN_GEOM_SIM_ONLY = 2,
+};
+enum {
+ MOD_OCEAN_REFRESH_RESET = (1 << 0),
+ MOD_OCEAN_REFRESH_SIM = (1 << 1),
+ MOD_OCEAN_REFRESH_ADD = (1 << 2),
+ MOD_OCEAN_REFRESH_CLEAR_CACHE = (1 << 3),
+ MOD_OCEAN_REFRESH_TOPOLOGY = (1 << 4),
+};
+
+enum {
+ MOD_OCEAN_GENERATE_FOAM = (1 << 0),
+ MOD_OCEAN_GENERATE_NORMALS = (1 << 1),
+};
typedef struct WarpModifierData {
ModifierData modifier;
/* keep in sync with MappingInfoModifierData */
struct Tex *texture;
struct Object *map_object;
- char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
int uvlayer_tmp;
int texmapping;
/* end MappingInfoModifierData */
@@ -855,7 +918,7 @@ typedef struct WarpModifierData {
struct Object *object_from;
struct Object *object_to;
struct CurveMapping *curfalloff;
- char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
float strength;
float falloff_radius;
char flag; /* not used yet */
@@ -866,189 +929,175 @@ typedef struct WarpModifierData {
#define MOD_WARP_VOLUME_PRESERVE 1
typedef enum {
- eWarp_Falloff_None = 0,
- eWarp_Falloff_Curve = 1,
- eWarp_Falloff_Sharp = 2, /* PROP_SHARP */
- eWarp_Falloff_Smooth = 3, /* PROP_SMOOTH */
- eWarp_Falloff_Root = 4, /* PROP_ROOT */
- eWarp_Falloff_Linear = 5, /* PROP_LIN */
- eWarp_Falloff_Const = 6, /* PROP_CONST */
- eWarp_Falloff_Sphere = 7, /* PROP_SPHERE */
+ eWarp_Falloff_None = 0,
+ eWarp_Falloff_Curve = 1,
+ eWarp_Falloff_Sharp = 2, /* PROP_SHARP */
+ eWarp_Falloff_Smooth = 3, /* PROP_SMOOTH */
+ eWarp_Falloff_Root = 4, /* PROP_ROOT */
+ eWarp_Falloff_Linear = 5, /* PROP_LIN */
+ eWarp_Falloff_Const = 6, /* PROP_CONST */
+ eWarp_Falloff_Sphere = 7, /* PROP_SPHERE */
/* PROP_RANDOM not used */
} WarpModifierFalloff;
typedef struct WeightVGEditModifierData {
ModifierData modifier;
- /* Note: I tried to keep everything logically ordered - provided the
- * alignment constraints... */
+ char defgrp_name[64]; /* Name of vertex group to edit. MAX_VGROUP_NAME. */
- char defgrp_name[64]; /* Name of vertex group to edit. MAX_VGROUP_NAME. */
-
- short edit_flags; /* Using MOD_WVG_EDIT_* flags. */
- short falloff_type; /* Using MOD_WVG_MAPPING_* defines. */
- float default_weight; /* Weight for vertices not in vgroup. */
+ short edit_flags; /* Using MOD_WVG_EDIT_* flags. */
+ short falloff_type; /* Using MOD_WVG_MAPPING_* defines. */
+ float default_weight; /* Weight for vertices not in vgroup. */
/* Mapping stuff. */
struct CurveMapping *cmap_curve; /* The custom mapping curve! */
/* The add/remove vertices weight thresholds. */
- float add_threshold, rem_threshold;
+ float add_threshold, rem_threshold;
/* Masking options. */
- float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */
- /* Name of mask vertex group from which to get weight factors. */
- char mask_defgrp_name[64]; /* MAX_VGROUP_NAME */
+ float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */
+ char mask_defgrp_name[64]; /* Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME */
/* Texture masking. */
- int mask_tex_use_channel; /* Which channel to use as weightf. */
+ int mask_tex_use_channel; /* Which channel to use as weightf. */
struct Tex *mask_texture; /* The texture. */
struct Object *mask_tex_map_obj; /* Name of the map object. */
- /* How to map the texture (using MOD_DISP_MAP_* constants). */
- int mask_tex_mapping;
- char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME */
+ int mask_tex_mapping; /* How to map the texture (using MOD_DISP_MAP_* enums). */
+ char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME */
/* Padding... */
int pad_i1;
} WeightVGEditModifierData;
/* WeightVGEdit flags. */
-/* Use parametric mapping. */
-//#define MOD_WVG_EDIT_MAP (1 << 0)
-/* Use curve mapping. */
-//#define MOD_WVG_EDIT_CMAP (1 << 1)
-/* Reverse weights (in the [0.0, 1.0] standard range). */
-//#define MOD_WVG_EDIT_REVERSE_WEIGHTS (1 << 2)
-/* Add vertices with higher weight than threshold to vgroup. */
-#define MOD_WVG_EDIT_ADD2VG (1 << 3)
-/* Remove vertices with lower weight than threshold from vgroup. */
-#define MOD_WVG_EDIT_REMFVG (1 << 4)
-/* Clamp weights. */
-//#define MOD_WVG_EDIT_CLAMP (1 << 5)
+enum {
+ /* (1 << 0), (1 << 1) and (1 << 2) are free for future use! */
+ MOD_WVG_EDIT_ADD2VG = (1 << 3), /* Add vertices with higher weight than threshold to vgroup. */
+ MOD_WVG_EDIT_REMFVG = (1 << 4), /* Remove vertices with lower weight than threshold from vgroup. */
+};
typedef struct WeightVGMixModifierData {
ModifierData modifier;
- /* XXX Note: I tried to keep everything logically ordered - provided the
- * alignment constraints... */
+ char defgrp_name_a[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */
+ char defgrp_name_b[64]; /* Name of other vertex group to mix in. MAX_VGROUP_NAME. */
+ float default_weight_a; /* Default weight value for first vgroup. */
+ float default_weight_b; /* Default weight value to mix in. */
+ char mix_mode; /* How second vgroups weights affect first ones */
+ char mix_set; /* What vertices to affect. */
- char defgrp_name_a[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */
- char defgrp_name_b[64]; /* Name of other vertex group to mix in. MAX_VGROUP_NAME. */
- float default_weight_a; /* Default weight value for first vgroup. */
- float default_weight_b; /* Default weight value to mix in. */
- char mix_mode; /* How second vgroups weights affect first ones */
- char mix_set; /* What vertices to affect. */
-
- char pad_c1[6];
+ char pad_c1[6];
/* Masking options. */
- float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */
- /* Name of mask vertex group from which to get weight factors. */
- char mask_defgrp_name[64]; /* MAX_VGROUP_NAME */
+ float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */
+ char mask_defgrp_name[64]; /* Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME */
/* Texture masking. */
- int mask_tex_use_channel; /* Which channel to use as weightf. */
- struct Tex *mask_texture; /* The texture. */
- struct Object *mask_tex_map_obj; /* Name of the map object. */
- int mask_tex_mapping; /* How to map the texture! */
- char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME. */
+ int mask_tex_use_channel; /* Which channel to use as weightf. */
+ struct Tex *mask_texture; /* The texture. */
+ struct Object *mask_tex_map_obj; /* Name of the map object. */
+ int mask_tex_mapping; /* How to map the texture! */
+ char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME. */
/* Padding... */
int pad_i1;
} WeightVGMixModifierData;
/* How second vgroup's weights affect first ones. */
-#define MOD_WVG_MIX_SET 1 /* Second weights replace weights. */
-#define MOD_WVG_MIX_ADD 2 /* Second weights are added to weights. */
-#define MOD_WVG_MIX_SUB 3 /* Second weights are subtracted from weights. */
-#define MOD_WVG_MIX_MUL 4 /* Second weights are multiplied with weights. */
-#define MOD_WVG_MIX_DIV 5 /* Second weights divide weights. */
-#define MOD_WVG_MIX_DIF 6 /* Difference between second weights and weights. */
-#define MOD_WVG_MIX_AVG 7 /* Average of both weights. */
+enum {
+ MOD_WVG_MIX_SET = 1, /* Second weights replace weights. */
+ MOD_WVG_MIX_ADD = 2, /* Second weights are added to weights. */
+ MOD_WVG_MIX_SUB = 3, /* Second weights are subtracted from weights. */
+ MOD_WVG_MIX_MUL = 4, /* Second weights are multiplied with weights. */
+ MOD_WVG_MIX_DIV = 5, /* Second weights divide weights. */
+ MOD_WVG_MIX_DIF = 6, /* Difference between second weights and weights. */
+ MOD_WVG_MIX_AVG = 7, /* Average of both weights. */
+};
/* What vertices to affect. */
-#define MOD_WVG_SET_ALL 1 /* Affect all vertices. */
-#define MOD_WVG_SET_A 2 /* Affect only vertices in first vgroup. */
-#define MOD_WVG_SET_B 3 /* Affect only vertices in second vgroup. */
-#define MOD_WVG_SET_OR 4 /* Affect only vertices in one vgroup or the other. */
-#define MOD_WVG_SET_AND 5 /* Affect only vertices in both vgroups. */
+enum {
+ MOD_WVG_SET_ALL = 1, /* Affect all vertices. */
+ MOD_WVG_SET_A = 2, /* Affect only vertices in first vgroup. */
+ MOD_WVG_SET_B = 3, /* Affect only vertices in second vgroup. */
+ MOD_WVG_SET_OR = 4, /* Affect only vertices in one vgroup or the other. */
+ MOD_WVG_SET_AND = 5, /* Affect only vertices in both vgroups. */
+};
typedef struct WeightVGProximityModifierData {
ModifierData modifier;
- /* Note: I tried to keep everything logically ordered - provided the
- * alignment constraints... */
-
- char defgrp_name[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */
+ char defgrp_name[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */
/* Proximity modes. */
- int proximity_mode;
- int proximity_flags;
+ int proximity_mode;
+ int proximity_flags;
/* Target object from which to calculate vertices distances. */
struct Object *proximity_ob_target;
/* Masking options. */
- float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */
- /* Name of mask vertex group from which to get weight factors. */
- char mask_defgrp_name[64]; /* MAX_VGROUP_NAME */
+ float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */
+ char mask_defgrp_name[64]; /* Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME */
/* Texture masking. */
- int mask_tex_use_channel; /* Which channel to use as weightf. */
- struct Tex *mask_texture; /* The texture. */
- struct Object *mask_tex_map_obj; /* Name of the map object. */
- int mask_tex_mapping; /* How to map the texture! */
- char mask_tex_uvlayer_name[64]; /* Name of the UV Map. MAX_CUSTOMDATA_LAYER_NAME. */
+ int mask_tex_use_channel; /* Which channel to use as weightf. */
+ struct Tex *mask_texture; /* The texture. */
+ struct Object *mask_tex_map_obj; /* Name of the map object. */
+ int mask_tex_mapping; /* How to map the texture! */
+ char mask_tex_uvlayer_name[64]; /* Name of the UV Map. MAX_CUSTOMDATA_LAYER_NAME. */
- float min_dist, max_dist; /* Distances mapping to 0.0/1.0 weights. */
+ float min_dist, max_dist; /* Distances mapping to 0.0/1.0 weights. */
/* Put here to avoid breaking existing struct... */
- short falloff_type; /* Using MOD_WVG_MAPPING_* defines. */
+ short falloff_type; /* Using MOD_WVG_MAPPING_* enums. */
/* Padding... */
short pad_s1;
} WeightVGProximityModifierData;
/* Modes of proximity weighting. */
-/* Dist from target object to affected object. */
-#define MOD_WVG_PROXIMITY_OBJECT 1 /* source vertex to other location */
-/* Dist from target object to vertex. */
-#define MOD_WVG_PROXIMITY_GEOMETRY 2 /* source vertex to other geometry */
+enum {
+ MOD_WVG_PROXIMITY_OBJECT = 1, /* source vertex to other location */
+ MOD_WVG_PROXIMITY_GEOMETRY = 2, /* source vertex to other geometry */
+};
/* Flags options for proximity weighting. */
-/* Use nearest vertices of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */
-#define MOD_WVG_PROXIMITY_GEOM_VERTS (1 << 0)
-/* Use nearest edges of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */
-#define MOD_WVG_PROXIMITY_GEOM_EDGES (1 << 1)
-/* Use nearest faces of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */
-#define MOD_WVG_PROXIMITY_GEOM_FACES (1 << 2)
+enum {
+ /* Use nearest vertices of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */
+ MOD_WVG_PROXIMITY_GEOM_VERTS = (1 << 0),
+ /* Use nearest edges of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */
+ MOD_WVG_PROXIMITY_GEOM_EDGES = (1 << 1),
+ /* Use nearest faces of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */
+ MOD_WVG_PROXIMITY_GEOM_FACES = (1 << 2),
+};
/* Defines common to all WeightVG modifiers. */
/* Mapping modes. */
-#define MOD_WVG_MAPPING_NONE 0
-#define MOD_WVG_MAPPING_CURVE 1
-#define MOD_WVG_MAPPING_SHARP 2 /* PROP_SHARP */
-#define MOD_WVG_MAPPING_SMOOTH 3 /* PROP_SMOOTH */
-#define MOD_WVG_MAPPING_ROOT 4 /* PROP_ROOT */
-/* PROP_LIN not used (same as NONE, here...). */
-/* PROP_CONST not used. */
-#define MOD_WVG_MAPPING_SPHERE 7 /* PROP_SPHERE */
-#define MOD_WVG_MAPPING_RANDOM 8 /* PROP_RANDOM */
-#define MOD_WVG_MAPPING_STEP 9 /* Median Step. */
+enum {
+ MOD_WVG_MAPPING_NONE = 0,
+ MOD_WVG_MAPPING_CURVE = 1,
+ MOD_WVG_MAPPING_SHARP = 2, /* PROP_SHARP */
+ MOD_WVG_MAPPING_SMOOTH = 3, /* PROP_SMOOTH */
+ MOD_WVG_MAPPING_ROOT = 4, /* PROP_ROOT */
+ /* PROP_LIN not used (same as NONE, here...). */
+ /* PROP_CONST not used. */
+ MOD_WVG_MAPPING_SPHERE = 7, /* PROP_SPHERE */
+ MOD_WVG_MAPPING_RANDOM = 8, /* PROP_RANDOM */
+ MOD_WVG_MAPPING_STEP = 9, /* Median Step. */
+};
/* Tex channel to be used as mask. */
-#define MOD_WVG_MASK_TEX_USE_INT 1
-#define MOD_WVG_MASK_TEX_USE_RED 2
-#define MOD_WVG_MASK_TEX_USE_GREEN 3
-#define MOD_WVG_MASK_TEX_USE_BLUE 4
-#define MOD_WVG_MASK_TEX_USE_HUE 5
-#define MOD_WVG_MASK_TEX_USE_SAT 6
-#define MOD_WVG_MASK_TEX_USE_VAL 7
-#define MOD_WVG_MASK_TEX_USE_ALPHA 8
-
-/* Dynamic paint modifier flags */
-#define MOD_DYNAMICPAINT_TYPE_CANVAS (1 << 0)
-#define MOD_DYNAMICPAINT_TYPE_BRUSH (1 << 1)
+enum {
+ MOD_WVG_MASK_TEX_USE_INT = 1,
+ MOD_WVG_MASK_TEX_USE_RED = 2,
+ MOD_WVG_MASK_TEX_USE_GREEN = 3,
+ MOD_WVG_MASK_TEX_USE_BLUE = 4,
+ MOD_WVG_MASK_TEX_USE_HUE = 5,
+ MOD_WVG_MASK_TEX_USE_SAT = 6,
+ MOD_WVG_MASK_TEX_USE_VAL = 7,
+ MOD_WVG_MASK_TEX_USE_ALPHA = 8,
+};
typedef struct DynamicPaintModifierData {
ModifierData modifier;
@@ -1059,18 +1108,23 @@ typedef struct DynamicPaintModifierData {
int pad;
} DynamicPaintModifierData;
-/* Remesh modifier */
+/* Dynamic paint modifier flags */
+enum {
+ MOD_DYNAMICPAINT_TYPE_CANVAS = (1 << 0),
+ MOD_DYNAMICPAINT_TYPE_BRUSH = (1 << 1),
+};
+/* Remesh modifier */
typedef enum RemeshModifierFlags {
- MOD_REMESH_FLOOD_FILL = 1,
+ MOD_REMESH_FLOOD_FILL = 1,
MOD_REMESH_SMOOTH_SHADING = 2,
} RemeshModifierFlags;
typedef enum RemeshModifierMode {
/* blocky */
- MOD_REMESH_CENTROID = 0,
+ MOD_REMESH_CENTROID = 0,
/* smooth */
- MOD_REMESH_MASS_POINT = 1,
+ MOD_REMESH_MASS_POINT = 1,
/* keeps sharp edges */
MOD_REMESH_SHARP_FEATURES = 2,
} RemeshModifierMode;
@@ -1078,8 +1132,7 @@ typedef enum RemeshModifierMode {
typedef struct RemeshModifierData {
ModifierData modifier;
- /* floodfill option, controls how small components can be
- * before they are removed */
+ /* floodfill option, controls how small components can be before they are removed */
float threshold;
/* ratio between size of model and grid */
@@ -1096,14 +1149,13 @@ typedef struct RemeshModifierData {
} RemeshModifierData;
/* Skin modifier */
-
typedef struct SkinModifierData {
ModifierData modifier;
float branch_smoothing;
char flag;
-
+
char symmetry_axes;
char pad[2];
@@ -1111,20 +1163,20 @@ typedef struct SkinModifierData {
/* SkinModifierData.symmetry_axes */
enum {
- MOD_SKIN_SYMM_X = 1,
- MOD_SKIN_SYMM_Y = 2,
- MOD_SKIN_SYMM_Z = 4,
+ MOD_SKIN_SYMM_X = (1 << 0),
+ MOD_SKIN_SYMM_Y = (1 << 1),
+ MOD_SKIN_SYMM_Z = (1 << 2),
};
/* SkinModifierData.flag */
enum {
- MOD_SKIN_SMOOTH_SHADING = 1
+ MOD_SKIN_SMOOTH_SHADING = 1,
};
/* Triangulate modifier */
-
typedef struct TriangulateModifierData {
ModifierData modifier;
+
int flag;
int pad;
} TriangulateModifierData;
@@ -1133,39 +1185,43 @@ enum {
MOD_TRIANGULATE_BEAUTY = (1 << 0),
};
-/* Smooth modifier flags */
-#define MOD_LAPLACIANSMOOTH_X (1<<1)
-#define MOD_LAPLACIANSMOOTH_Y (1<<2)
-#define MOD_LAPLACIANSMOOTH_Z (1<<3)
-#define MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME (1 << 4)
-#define MOD_LAPLACIANSMOOTH_NORMALIZED (1 << 5)
-
typedef struct LaplacianSmoothModifierData {
ModifierData modifier;
+
float lambda, lambda_border, pad1;
- char defgrp_name[64]; /* MAX_VGROUP_NAME */
+ char defgrp_name[64]; /* MAX_VGROUP_NAME */
short flag, repeat;
} LaplacianSmoothModifierData;
+/* Smooth modifier flags */
+enum {
+ MOD_LAPLACIANSMOOTH_X = (1 << 1),
+ MOD_LAPLACIANSMOOTH_Y = (1 << 2),
+ MOD_LAPLACIANSMOOTH_Z = (1 << 3),
+ MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME = (1 << 4),
+ MOD_LAPLACIANSMOOTH_NORMALIZED = (1 << 5),
+};
+
typedef struct UVWarpModifierData {
ModifierData modifier;
char axis_u, axis_v;
char pad[6];
- float center[2]; /* used for rotate/scale */
+ float center[2]; /* used for rotate/scale */
struct Object *object_src; /* source */
- char bone_src[64]; /* optional name of bone target, MAX_ID_NAME-2 */
+ char bone_src[64]; /* optional name of bone target, MAX_ID_NAME-2 */
struct Object *object_dst; /* target */
- char bone_dst[64]; /* optional name of bone target, MAX_ID_NAME-2 */
+ char bone_dst[64]; /* optional name of bone target, MAX_ID_NAME-2 */
- char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
- char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
} UVWarpModifierData;
/* cache modifier */
typedef struct MeshCacheModifierData {
ModifierData modifier;
+
char flag;
char type; /* file format */
char time_mode;
@@ -1192,29 +1248,29 @@ typedef struct MeshCacheModifierData {
float eval_time;
float eval_factor;
- char filepath[1024]; // FILE_MAX
+ char filepath[1024]; /* FILE_MAX */
} MeshCacheModifierData;
enum {
MOD_MESHCACHE_TYPE_MDD = 1,
- MOD_MESHCACHE_TYPE_PC2 = 2
+ MOD_MESHCACHE_TYPE_PC2 = 2,
};
enum {
MOD_MESHCACHE_DEFORM_OVERWRITE = 0,
- MOD_MESHCACHE_DEFORM_INTEGRATE = 1
+ MOD_MESHCACHE_DEFORM_INTEGRATE = 1,
};
enum {
- MOD_MESHCACHE_INTERP_NONE = 0,
- MOD_MESHCACHE_INTERP_LINEAR = 1,
- // MOD_MESHCACHE_INTERP_CARDINAL = 2
+ MOD_MESHCACHE_INTERP_NONE = 0,
+ MOD_MESHCACHE_INTERP_LINEAR = 1,
+/* MOD_MESHCACHE_INTERP_CARDINAL = 2, */
};
enum {
- MOD_MESHCACHE_TIME_FRAME = 0,
+ MOD_MESHCACHE_TIME_FRAME = 0,
MOD_MESHCACHE_TIME_SECONDS = 1,
- MOD_MESHCACHE_TIME_FACTOR = 2,
+ MOD_MESHCACHE_TIME_FACTOR = 2,
};
enum {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 9ff4392242e..0ed620c4632 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -720,8 +720,10 @@ typedef struct NodeTexBase {
typedef struct NodeTexSky {
NodeTexBase base;
+ int sky_model;
float sun_direction[3];
float turbidity;
+ float ground_albedo;
} NodeTexSky;
typedef struct NodeTexImage {
@@ -827,6 +829,10 @@ typedef struct NodeTranslateData {
char pad[6];
} NodeTranslateData;
+typedef struct NodePlaneTrackDeformData {
+ char tracking_object[64];
+ char plane_track_name[64];
+} NodePlaneTrackDeformData;
typedef struct NodeShaderScript {
int mode;
@@ -888,6 +894,10 @@ typedef struct NodeShaderNormalMap {
#define SHD_TOON_DIFFUSE 0
#define SHD_TOON_GLOSSY 1
+/* hair components */
+#define SHD_HAIR_REFLECTION 0
+#define SHD_HAIR_TRANSMISSION 1
+
/* blend texture */
#define SHD_BLEND_LINEAR 0
#define SHD_BLEND_QUADRATIC 1
@@ -933,9 +943,9 @@ typedef struct NodeShaderNormalMap {
#define SHD_WAVE_BANDS 0
#define SHD_WAVE_RINGS 1
-#define SHD_WAVE_SINE 0
-#define SHD_WAVE_SAW 1
-#define SHD_WAVE_TRI 2
+/* sky texture */
+#define SHD_SKY_OLD 0
+#define SHD_SKY_NEW 1
/* image/environment texture */
#define SHD_COLORSPACE_NONE 0
@@ -965,6 +975,11 @@ typedef struct NodeShaderNormalMap {
#define SHD_NORMAL_MAP_BLENDER_OBJECT 3
#define SHD_NORMAL_MAP_BLENDER_WORLD 4
+/* subsurface */
+#define SHD_SUBSURFACE_COMPATIBLE 0 // Deprecated
+#define SHD_SUBSURFACE_CUBIC 1
+#define SHD_SUBSURFACE_GAUSSIAN 2
+
/* blur node */
#define CMP_NODE_BLUR_ASPECT_NONE 0
#define CMP_NODE_BLUR_ASPECT_Y 1
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index de34f101c31..2ff697f513f 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -41,7 +41,7 @@
#ifdef __cplusplus
extern "C" {
#endif
-
+
struct Object;
struct AnimData;
struct Ipo;
@@ -100,7 +100,10 @@ typedef struct BoundBox {
} BoundBox;
/* boundbox flag */
-#define OB_BB_DISABLED 1
+enum {
+ BOUNDBOX_DISABLED = (1 << 0),
+ BOUNDBOX_DIRTY = (1 << 1),
+};
typedef struct Object {
ID id;
@@ -130,7 +133,6 @@ typedef struct Object {
ListBase constraintChannels DNA_DEPRECATED; // XXX deprecated... old animation system
ListBase effect DNA_DEPRECATED; // XXX deprecated... keep for readfile
- ListBase disp; /* list of DispList, used by lattice, metaballs curve & surfaces */
ListBase defbase; /* list of bDeformGroup (vertex groups) names and flag only */
ListBase modifiers; /* list of ModifierData structures */
@@ -140,7 +142,7 @@ typedef struct Object {
/* materials */
struct Material **mat; /* material slots */
char *matbits; /* a boolean field, with each byte 1 if corresponding material is linked to object */
- int totcol; /* copy of mesh or curve or meta */
+ int totcol; /* copy of mesh, curve & meta struct member of same name (keep in sync) */
int actcol; /* currently selected material in the UI */
/* rot en drot have to be together! (transform('r' en 's')) */
@@ -276,6 +278,9 @@ typedef struct Object {
struct RigidBodyCon *rigidbody_constraint; /* settings for Bullet constraint */
float ima_ofs[2]; /* offset for image empties */
+
+ /* Runtime valuated curve-specific data, not stored in the file */
+ struct CurveCache *curve_cache;
} Object;
/* Warning, this is not used anymore because hooks are now modifiers */
@@ -318,26 +323,28 @@ typedef struct DupliObject {
/* **************** OBJECT ********************* */
/* used many places... should be specialized */
-#define SELECT 1
+#define SELECT 1
/* type */
-#define OB_EMPTY 0
-#define OB_MESH 1
-#define OB_CURVE 2
-#define OB_SURF 3
-#define OB_FONT 4
-#define OB_MBALL 5
+enum {
+ OB_EMPTY = 0,
+ OB_MESH = 1,
+ OB_CURVE = 2,
+ OB_SURF = 3,
+ OB_FONT = 4,
+ OB_MBALL = 5,
-#define OB_LAMP 10
-#define OB_CAMERA 11
+ OB_LAMP = 10,
+ OB_CAMERA = 11,
-#define OB_SPEAKER 12
+ OB_SPEAKER = 12,
-// #define OB_WAVE 21
-#define OB_LATTICE 22
+/* OB_WAVE = 21, */
+ OB_LATTICE = 22,
/* 23 and 24 are for life and sector (old file compat.) */
-#define OB_ARMATURE 25
+ OB_ARMATURE = 25,
+};
/* check if the object type supports materials */
#define OB_TYPE_SUPPORT_MATERIAL(_type) \
@@ -346,6 +353,8 @@ typedef struct DupliObject {
(ELEM(_type, OB_MESH, OB_LATTICE))
#define OB_TYPE_SUPPORT_EDITMODE(_type) \
(ELEM7(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
+#define OB_TYPE_SUPPORT_PARVERT(_type) \
+ (ELEM4(_type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE))
/* is this ID type used as object data */
#define OB_DATA_SUPPORT_ID(_id_type) \
@@ -355,263 +364,300 @@ typedef struct DupliObject {
ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_CA: case ID_LT: case ID_AR
/* partype: first 4 bits: type */
-#define PARTYPE 15
-#define PAROBJECT 0
-#define PARCURVE 1
-#define PARKEY 2
+enum {
+ PARTYPE = (1 << 4) - 1,
+ PAROBJECT = 0,
+ PARCURVE = 1,
+ PARKEY = 2,
-#define PARSKEL 4
-#define PARVERT1 5
-#define PARVERT3 6
-#define PARBONE 7
+ PARSKEL = 4,
+ PARVERT1 = 5,
+ PARVERT3 = 6,
+ PARBONE = 7,
/* slow parenting - is not threadsafe and/or may give errors after jumping */
-#define PARSLOW 16
+ PARSLOW = 16,
+};
/* (short) transflag */
/* flags 1 and 2 were unused or relics from past features */
-#define OB_NEG_SCALE 4
-#define OB_DUPLI (8+16+256+512+2048)
-#define OB_DUPLIFRAMES 8
-#define OB_DUPLIVERTS 16
-#define OB_DUPLIROT 32
-#define OB_DUPLINOSPEED 64
-/*#define OB_POWERTRACK 128*/ /*UNUSED*/
-#define OB_DUPLIGROUP 256
-#define OB_DUPLIFACES 512
-#define OB_DUPLIFACES_SCALE 1024
-#define OB_DUPLIPARTS 2048
-#define OB_RENDER_DUPLI 4096
-#define OB_NO_CONSTRAINTS 8192 /* runtime constraints disable */
-#define OB_NO_PSYS_UPDATE 16384 /* hack to work around particle issue */
+enum {
+ OB_NEG_SCALE = 1 << 2,
+ OB_DUPLIFRAMES = 1 << 3,
+ OB_DUPLIVERTS = 1 << 4,
+ OB_DUPLIROT = 1 << 5,
+ OB_DUPLINOSPEED = 1 << 6,
+/* OB_POWERTRACK = 1 << 7,*/ /*UNUSED*/
+ OB_DUPLIGROUP = 1 << 8,
+ OB_DUPLIFACES = 1 << 9,
+ OB_DUPLIFACES_SCALE = 1 << 10,
+ OB_DUPLIPARTS = 1 << 11,
+ OB_RENDER_DUPLI = 1 << 12,
+ OB_NO_CONSTRAINTS = 1 << 13, /* runtime constraints disable */
+ OB_NO_PSYS_UPDATE = 1 << 14, /* hack to work around particle issue */
+
+ OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLIGROUP | OB_DUPLIFACES | OB_DUPLIPARTS,
+};
/* (short) ipoflag */
/* XXX: many old flags for features removed due to incompatibility
* with new system and/or other design issues were here
*/
/* for stride/path editing (XXX: NEEDS REVIEW) */
-#define OB_DISABLE_PATH 1024
+#define OB_DISABLE_PATH (1 << 10)
/* (short) trackflag / upflag */
-#define OB_POSX 0
-#define OB_POSY 1
-#define OB_POSZ 2
-#define OB_NEGX 3
-#define OB_NEGY 4
-#define OB_NEGZ 5
+enum {
+ OB_POSX = 0,
+ OB_POSY = 1,
+ OB_POSZ = 2,
+ OB_NEGX = 3,
+ OB_NEGY = 4,
+ OB_NEGZ = 5,
+};
/* gameflag in game.h */
/* dt: no flags */
-#define OB_BOUNDBOX 1
-#define OB_WIRE 2
-#define OB_SOLID 3
-#define OB_MATERIAL 4
-#define OB_TEXTURE 5
-#define OB_RENDER 6
+enum {
+ OB_BOUNDBOX = 1,
+ OB_WIRE = 2,
+ OB_SOLID = 3,
+ OB_MATERIAL = 4,
+ OB_TEXTURE = 5,
+ OB_RENDER = 6,
-#define OB_PAINT 100 /* temporary used in draw code */
+ OB_PAINT = 100, /* temporary used in draw code */
+};
/* dtx: flags (short) */
-#define OB_DRAWBOUNDOX (1 << 0)
-#define OB_AXIS (1 << 1)
-#define OB_TEXSPACE (1 << 2)
-#define OB_DRAWNAME (1 << 3)
-#define OB_DRAWIMAGE (1 << 4)
+enum {
+ OB_DRAWBOUNDOX = 1 << 0,
+ OB_AXIS = 1 << 1,
+ OB_TEXSPACE = 1 << 2,
+ OB_DRAWNAME = 1 << 3,
+ OB_DRAWIMAGE = 1 << 4,
/* for solid+wire display */
-#define OB_DRAWWIRE (1 << 5)
+ OB_DRAWWIRE = 1 << 5,
/* for overdraw s*/
-#define OB_DRAWXRAY (1 << 6)
+ OB_DRAWXRAY = 1 << 6,
/* enable transparent draw */
-#define OB_DRAWTRANSP (1 << 7)
-#define OB_DRAW_ALL_EDGES (1 << 8) /* only for meshes currently */
+ OB_DRAWTRANSP = 1 << 7,
+ OB_DRAW_ALL_EDGES = 1 << 8, /* only for meshes currently */
+};
/* empty_drawtype: no flags */
-#define OB_ARROWS 1
-#define OB_PLAINAXES 2
-#define OB_CIRCLE 3
-#define OB_SINGLE_ARROW 4
-#define OB_CUBE 5
-#define OB_EMPTY_SPHERE 6
-#define OB_EMPTY_CONE 7
-#define OB_EMPTY_IMAGE 8
+enum {
+ OB_ARROWS = 1,
+ OB_PLAINAXES = 2,
+ OB_CIRCLE = 3,
+ OB_SINGLE_ARROW = 4,
+ OB_CUBE = 5,
+ OB_EMPTY_SPHERE = 6,
+ OB_EMPTY_CONE = 7,
+ OB_EMPTY_IMAGE = 8,
+};
/* boundtype */
-#define OB_BOUND_BOX 0
-#define OB_BOUND_SPHERE 1
-#define OB_BOUND_CYLINDER 2
-#define OB_BOUND_CONE 3
-#define OB_BOUND_TRIANGLE_MESH 4
-#define OB_BOUND_CONVEX_HULL 5
-/* #define OB_BOUND_DYN_MESH 6 */ /*UNUSED*/
-#define OB_BOUND_CAPSULE 7
+enum {
+ OB_BOUND_BOX = 0,
+ OB_BOUND_SPHERE = 1,
+ OB_BOUND_CYLINDER = 2,
+ OB_BOUND_CONE = 3,
+ OB_BOUND_TRIANGLE_MESH = 4,
+ OB_BOUND_CONVEX_HULL = 5,
+/* OB_BOUND_DYN_MESH = 6, */ /*UNUSED*/
+ OB_BOUND_CAPSULE = 7,
+};
/* **************** BASE ********************* */
-/* also needed for base!!!!! or rather, thy interfere....*/
+/* also needed for base!!!!! or rather, they interfere....*/
/* base->flag and ob->flag */
-#define BA_WAS_SEL 2
-#define BA_HAS_RECALC_OB 4
-#define BA_HAS_RECALC_DATA 8
+#define BA_WAS_SEL (1 << 1)
+#define BA_HAS_RECALC_OB (1 << 2)
+#define BA_HAS_RECALC_DATA (1 << 3)
/* NOTE: this was used as a proper setting in past, so nullify before using */
-#define BA_TEMP_TAG 32
+#define BA_TEMP_TAG (1 << 5)
-/* #define BA_FROMSET 128 */ /*UNUSED*/
+/* #define BA_FROMSET (1 << 7) */ /*UNUSED*/
-#define BA_TRANSFORM_CHILD 256 /* child of a transformed object */
-#define BA_TRANSFORM_PARENT 8192 /* parent of a transformed object */
+#define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */
+#define BA_TRANSFORM_PARENT (1 << 13) /* parent of a transformed object */
/* an initial attempt as making selection more specific! */
-#define BA_DESELECT 0
-#define BA_SELECT 1
+#define BA_DESELECT 0
+#define BA_SELECT 1
-#define OB_FROMDUPLI 512
-#define OB_DONE 1024
-// #define OB_RADIO 2048 /* deprecated */
-#define OB_FROMGROUP 4096
+#define OB_FROMDUPLI (1 << 9)
+#define OB_DONE (1 << 10)
+/* #define OB_RADIO (1 << 11) */ /* deprecated */
+#define OB_FROMGROUP (1 << 12)
/* WARNING - when adding flags check on PSYS_RECALC */
/* ob->recalc (flag bits!) */
-#define OB_RECALC_OB (1 << 0)
-#define OB_RECALC_DATA (1 << 1)
+enum {
+ OB_RECALC_OB = 1 << 0,
+ OB_RECALC_DATA = 1 << 1,
/* time flag is set when time changes need recalc, so baked systems can ignore it */
-#define OB_RECALC_TIME (1 << 2)
+ OB_RECALC_TIME = 1 << 2,
/* only use for matching any flag, NOT as an argument since more flags may be added. */
-#define OB_RECALC_ALL (OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME)
+ OB_RECALC_ALL = OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME,
+};
/* controller state */
-#define OB_MAX_STATES 30
+#define OB_MAX_STATES 30
/* collision masks */
-#define OB_MAX_COL_MASKS 8
+#define OB_MAX_COL_MASKS 8
/* ob->gameflag */
-#define OB_DYNAMIC 1
-#define OB_CHILD 2
-#define OB_ACTOR 4
-#define OB_INERTIA_LOCK_X 8
-#define OB_INERTIA_LOCK_Y 16
-#define OB_INERTIA_LOCK_Z 32
-#define OB_DO_FH 64
-#define OB_ROT_FH 128
-#define OB_ANISOTROPIC_FRICTION 256
-#define OB_GHOST 512
-#define OB_RIGID_BODY 1024
-#define OB_BOUNDS 2048
-
-#define OB_COLLISION_RESPONSE 4096
-#define OB_SECTOR 8192
-#define OB_PROP 16384
-#define OB_MAINACTOR 32768
-
-#define OB_COLLISION 65536
-#define OB_SOFT_BODY 0x20000
-#define OB_OCCLUDER 0x40000
-#define OB_SENSOR 0x80000
-#define OB_NAVMESH 0x100000
-#define OB_HASOBSTACLE 0x200000
-#define OB_CHARACTER 0x400000
+enum {
+ OB_DYNAMIC = 1 << 0,
+ OB_CHILD = 1 << 1,
+ OB_ACTOR = 1 << 2,
+ OB_INERTIA_LOCK_X = 1 << 3,
+ OB_INERTIA_LOCK_Y = 1 << 4,
+ OB_INERTIA_LOCK_Z = 1 << 5,
+ OB_DO_FH = 1 << 6,
+ OB_ROT_FH = 1 << 7,
+ OB_ANISOTROPIC_FRICTION = 1 << 8,
+ OB_GHOST = 1 << 9,
+ OB_RIGID_BODY = 1 << 10,
+ OB_BOUNDS = 1 << 11,
+
+ OB_COLLISION_RESPONSE = 1 << 12,
+ OB_SECTOR = 1 << 13,
+ OB_PROP = 1 << 14,
+ OB_MAINACTOR = 1 << 15,
+
+ OB_COLLISION = 1 << 16,
+ OB_SOFT_BODY = 1 << 17,
+ OB_OCCLUDER = 1 << 18,
+ OB_SENSOR = 1 << 19,
+ OB_NAVMESH = 1 << 20,
+ OB_HASOBSTACLE = 1 << 21,
+ OB_CHARACTER = 1 << 22,
+};
/* ob->gameflag2 */
-#define OB_NEVER_DO_ACTIVITY_CULLING 1
-#define OB_LOCK_RIGID_BODY_X_AXIS 4
-#define OB_LOCK_RIGID_BODY_Y_AXIS 8
-#define OB_LOCK_RIGID_BODY_Z_AXIS 16
-#define OB_LOCK_RIGID_BODY_X_ROT_AXIS 32
-#define OB_LOCK_RIGID_BODY_Y_ROT_AXIS 64
-#define OB_LOCK_RIGID_BODY_Z_ROT_AXIS 128
-
-/* #define OB_LIFE (OB_PROP|OB_DYNAMIC|OB_ACTOR|OB_MAINACTOR|OB_CHILD) */
+enum {
+ OB_NEVER_DO_ACTIVITY_CULLING = 1 << 0,
+ OB_LOCK_RIGID_BODY_X_AXIS = 1 << 2,
+ OB_LOCK_RIGID_BODY_Y_AXIS = 1 << 3,
+ OB_LOCK_RIGID_BODY_Z_AXIS = 1 << 4,
+ OB_LOCK_RIGID_BODY_X_ROT_AXIS = 1 << 5,
+ OB_LOCK_RIGID_BODY_Y_ROT_AXIS = 1 << 6,
+ OB_LOCK_RIGID_BODY_Z_ROT_AXIS = 1 << 7,
+
+/* OB_LIFE = OB_PROP | OB_DYNAMIC | OB_ACTOR | OB_MAINACTOR | OB_CHILD, */
+};
/* ob->body_type */
-#define OB_BODY_TYPE_NO_COLLISION 0
-#define OB_BODY_TYPE_STATIC 1
-#define OB_BODY_TYPE_DYNAMIC 2
-#define OB_BODY_TYPE_RIGID 3
-#define OB_BODY_TYPE_SOFT 4
-#define OB_BODY_TYPE_OCCLUDER 5
-#define OB_BODY_TYPE_SENSOR 6
-#define OB_BODY_TYPE_NAVMESH 7
-#define OB_BODY_TYPE_CHARACTER 8
+enum {
+ OB_BODY_TYPE_NO_COLLISION = 0,
+ OB_BODY_TYPE_STATIC = 1,
+ OB_BODY_TYPE_DYNAMIC = 2,
+ OB_BODY_TYPE_RIGID = 3,
+ OB_BODY_TYPE_SOFT = 4,
+ OB_BODY_TYPE_OCCLUDER = 5,
+ OB_BODY_TYPE_SENSOR = 6,
+ OB_BODY_TYPE_NAVMESH = 7,
+ OB_BODY_TYPE_CHARACTER = 8,
+};
/* ob->depsflag */
-#define OB_DEPS_EXTRA_OB_RECALC 1
-#define OB_DEPS_EXTRA_DATA_RECALC 2
+enum {
+ OB_DEPS_EXTRA_OB_RECALC = 1 << 0,
+ OB_DEPS_EXTRA_DATA_RECALC = 1 << 1,
+};
/* ob->scavisflag */
-#define OB_VIS_SENS 1
-#define OB_VIS_CONT 2
-#define OB_VIS_ACT 4
+enum {
+ OB_VIS_SENS = 1 << 0,
+ OB_VIS_CONT = 1 << 1,
+ OB_VIS_ACT = 1 << 2,
+};
/* ob->scaflag */
-#define OB_SHOWSENS 64
-#define OB_SHOWACT 128
-#define OB_ADDSENS 256
-#define OB_ADDCONT 512
-#define OB_ADDACT 1024
-#define OB_SHOWCONT 2048
-#define OB_ALLSTATE 4096
-#define OB_INITSTBIT 8192
-#define OB_DEBUGSTATE 16384
-#define OB_SHOWSTATE 32768
+enum {
+ OB_SHOWSENS = 1 << 6,
+ OB_SHOWACT = 1 << 7,
+ OB_ADDSENS = 1 << 8,
+ OB_ADDCONT = 1 << 9,
+ OB_ADDACT = 1 << 10,
+ OB_SHOWCONT = 1 << 11,
+ OB_ALLSTATE = 1 << 12,
+ OB_INITSTBIT = 1 << 13,
+ OB_DEBUGSTATE = 1 << 14,
+ OB_SHOWSTATE = 1 << 15,
+};
/* ob->restrictflag */
-#define OB_RESTRICT_VIEW 1
-#define OB_RESTRICT_SELECT 2
-#define OB_RESTRICT_RENDER 4
+enum {
+ OB_RESTRICT_VIEW = 1 << 0,
+ OB_RESTRICT_SELECT = 1 << 1,
+ OB_RESTRICT_RENDER = 1 << 2,
+};
/* ob->shapeflag */
-#define OB_SHAPE_LOCK 1
-#define OB_SHAPE_TEMPLOCK 2 // deprecated
-#define OB_SHAPE_EDIT_MODE 4
+enum {
+ OB_SHAPE_LOCK = 1 << 0,
+ OB_SHAPE_TEMPLOCK = 1 << 1, /* deprecated */
+ OB_SHAPE_EDIT_MODE = 1 << 2,
+};
/* ob->nlaflag */
- /* WARNING: flags (1<<0) and (1<<1) were from old animsys */
+enum {
+ /* WARNING: flags (1 << 0) and (1 << 1) were from old animsys */
/* object-channel expanded status */
-#define OB_ADS_COLLAPSED (1<<10)
+ OB_ADS_COLLAPSED = 1 << 10,
/* object's ipo-block */
-#define OB_ADS_SHOWIPO (1<<11)
+ OB_ADS_SHOWIPO = 1 << 11,
/* object's constraint channels */
-#define OB_ADS_SHOWCONS (1<<12)
+ OB_ADS_SHOWCONS = 1 << 12,
/* object's material channels */
-#define OB_ADS_SHOWMATS (1<<13)
+ OB_ADS_SHOWMATS = 1 << 13,
/* object's marticle channels */
-#define OB_ADS_SHOWPARTS (1<<14)
+ OB_ADS_SHOWPARTS = 1 << 14,
+};
/* ob->protectflag */
-#define OB_LOCK_LOCX 1
-#define OB_LOCK_LOCY 2
-#define OB_LOCK_LOCZ 4
-#define OB_LOCK_LOC 7
-#define OB_LOCK_ROTX 8
-#define OB_LOCK_ROTY 16
-#define OB_LOCK_ROTZ 32
-#define OB_LOCK_ROT 56
-#define OB_LOCK_SCALEX 64
-#define OB_LOCK_SCALEY 128
-#define OB_LOCK_SCALEZ 256
-#define OB_LOCK_SCALE 448
-#define OB_LOCK_ROTW 512
-#define OB_LOCK_ROT4D 1024
+enum {
+ OB_LOCK_LOCX = 1 << 0,
+ OB_LOCK_LOCY = 1 << 1,
+ OB_LOCK_LOCZ = 1 << 2,
+ OB_LOCK_LOC = OB_LOCK_LOCX | OB_LOCK_LOCY | OB_LOCK_LOCZ,
+ OB_LOCK_ROTX = 1 << 3,
+ OB_LOCK_ROTY = 1 << 4,
+ OB_LOCK_ROTZ = 1 << 5,
+ OB_LOCK_ROT = OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ,
+ OB_LOCK_SCALEX = 1 << 6,
+ OB_LOCK_SCALEY = 1 << 7,
+ OB_LOCK_SCALEZ = 1 << 8,
+ OB_LOCK_SCALE = OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ,
+ OB_LOCK_ROTW = 1 << 9,
+ OB_LOCK_ROT4D = 1 << 10,
+};
/* ob->mode */
typedef enum ObjectMode {
- OB_MODE_OBJECT = 0,
- OB_MODE_EDIT = 1,
- OB_MODE_SCULPT = 2,
- OB_MODE_VERTEX_PAINT = 4,
- OB_MODE_WEIGHT_PAINT = 8,
- OB_MODE_TEXTURE_PAINT = 16,
- OB_MODE_PARTICLE_EDIT = 32,
- OB_MODE_POSE = 64
+ 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,
} ObjectMode;
/* 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)
+#define OB_MODE_ALL_PAINT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)
#define MAX_DUPLI_RECUR 8
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 29fcaf3bf73..b7ca3066b4f 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -272,7 +272,9 @@ typedef struct ParticleSystem {
struct DerivedMesh *hair_in_dm, *hair_out_dm; /* input/output for cloth simulation */
struct Object *target_ob;
- struct Object *lattice;
+
+ struct LatticeDeformData *lattice_deform_data; /* run-time only lattice deformation data */
+
struct Object *parent; /* particles from global space -> parent space */
struct ListBase targets; /* used for keyed and boid physics */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index ceb745cf90a..e8f55ac047c 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -693,8 +693,8 @@ typedef struct GameData {
#define RAS_STORE_VBO 3
/* vsync */
-#define VSYNC_OFF 0
-#define VSYNC_ON 1
+#define VSYNC_ON 0
+#define VSYNC_OFF 1
#define VSYNC_ADAPTIVE 2
/* GameData.flag */
@@ -981,17 +981,6 @@ typedef struct ToolSettings {
* paint */
float vgroup_weight;
- /* Subdivide Settings */
- short cornertype;
- short pad1;
- /*Triangle to Quad conversion threshold*/
- float jointrilimit;
- /* Editmode Tools */
- float degr;
- short step;
- short turn;
-
- float extr_offs; /* extrude offset */
float doublimit; /* remove doubles limit */
float normalsize; /* size of normals */
short automerge;
@@ -999,30 +988,21 @@ typedef struct ToolSettings {
/* Selection Mode for Mesh */
short selectmode;
- /* Primitive Settings */
- /* UV Sphere */
- short segments;
- short rings;
-
- /* Cylinder - Tube - Circle */
- short vertices;
-
/* UV Calculation */
- short unwrapper;
- float uvcalc_radius;
- float uvcalc_cubesize;
+ char unwrapper;
+ char uvcalc_flag;
+ char uv_flag;
+ char uv_selectmode;
+
float uvcalc_margin;
- short uvcalc_mapdir;
- short uvcalc_mapalign;
- short uvcalc_flag;
- short uv_flag, uv_selectmode;
- short pad2;
-
- /* Grease Pencil */
- short gpencil_flags;
-
+
/* Auto-IK */
- short autoik_chainlen;
+ short autoik_chainlen; /* runtime only */
+
+ /* Grease Pencil */
+ char gpencil_flags;
+
+ char pad[5];
/* Image Paint (8 byttse aligned please!) */
struct ImagePaintSettings imapaint;
@@ -1035,16 +1015,13 @@ typedef struct ToolSettings {
/* Select Group Threshold */
float select_thresh;
-
- /* Graph Editor */
- float clean_thresh;
/* Auto-Keying Mode */
short autokey_mode, autokey_flag; /* defines in DNA_userdef_types.h */
/* Multires */
char multires_subdiv_type;
- char pad3[5];
+ char pad3[1];
/* Skeleton generation */
short skgen_resolution;
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 9d840ad13e8..ec86a4739c5 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -112,22 +112,48 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */
void *activedata; /* runtime for panel manipulation */
} Panel;
-typedef struct uiList { /* some list UI data need to be saved in file */
+/* uiList dynamic data... */
+/* These two Lines with # tell makesdna this struct can be excluded. */
+#
+#
+typedef struct uiListDyn {
+ int height; /* Number of rows needed to draw all elements. */
+ int visual_height; /* Actual visual height of the list (in rows). */
+ int visual_height_min; /* Minimal visual height of the list (in rows). */
+
+ int items_len; /* Number of items in collection. */
+ int items_shown; /* Number of items actually visible after filtering. */
+
+ /* Filtering data. */
+ int *items_filter_flags; /* items_len length. */
+ int *items_filter_neworder; /* org_idx -> new_idx, items_len length. */
+} uiListDyn;
+
+typedef struct uiList { /* some list UI data need to be saved in file */
struct uiList *next, *prev;
- struct uiListType *type; /* runtime */
- void *padp;
+ struct uiListType *type; /* runtime */
- char list_id[64]; /* defined as UI_MAX_NAME_STR */
+ char list_id[64]; /* defined as UI_MAX_NAME_STR */
- int layout_type; /* How items are layedout in the list */
- int padi;
+ int layout_type; /* How items are layedout in the list */
+ int flag;
int list_scroll;
- int list_size;
+ int list_grip;
int list_last_len;
- int list_grip_size;
-/* char list_search[64]; */
+ int padi1;
+
+ /* Filtering data. */
+ char filter_byname[64]; /* defined as UI_MAX_NAME_STR */
+ int filter_flag;
+ int filter_sort_flag;
+
+ /* Custom sub-classes properties. */
+ IDProperty *properties;
+
+ /* Dynamic data (runtime). */
+ uiListDyn *dyn_data;
} uiList;
typedef struct ScrArea {
@@ -232,13 +258,38 @@ typedef struct ARegion {
#define PNL_DEFAULT_CLOSED 1
#define PNL_NO_HEADER 2
-/* uilist layout_type */
+/* uiList layout_type */
enum {
UILST_LAYOUT_DEFAULT = 0,
UILST_LAYOUT_COMPACT = 1,
UILST_LAYOUT_GRID = 2,
};
+/* uiList flag */
+enum {
+ UILST_SCROLL_TO_ACTIVE_ITEM = 1 << 0, /* Scroll list to make active item visible. */
+ UILST_RESIZING = 1 << 1, /* We are currently resizing, deactivate autosize! */
+};
+
+/* uiList filter flags (dyn_data) */
+enum {
+ UILST_FLT_ITEM = 1 << 31, /* This item has passed the filter process successfully. */
+};
+
+/* uiList filter options */
+enum {
+ UILST_FLT_SHOW = 1 << 0, /* Show filtering UI. */
+ UILST_FLT_EXCLUDE = UILST_FLT_ITEM, /* Exclude filtered items, *must* use this same value. */
+};
+
+/* uiList filter orderby type */
+enum {
+ UILST_FLT_SORT_ALPHA = 1 << 0,
+ UILST_FLT_SORT_REVERSE = 1 << 31 /* Special value, bitflag used to reverse order! */
+};
+
+#define UILST_FLT_SORT_MASK (((unsigned int)UILST_FLT_SORT_REVERSE) - 1)
+
/* regiontype, first two are the default set */
/* Do NOT change order, append on end. Types are hardcoded needed */
enum {
diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h
index d8cf80d047b..1b946c829fd 100644
--- a/source/blender/makesdna/DNA_sensor_types.h
+++ b/source/blender/makesdna/DNA_sensor_types.h
@@ -60,6 +60,7 @@ typedef struct bMouseSensor {
short pad2;
} bMouseSensor;
+/* DEPRECATED */
typedef struct bTouchSensor {
char name[64]; /* MAX_NAME */
struct Material *ma;
@@ -235,7 +236,7 @@ typedef struct bJoystickSensor {
/* sensor->type */
#define SENS_ALWAYS 0
-#define SENS_TOUCH 1
+#define SENS_TOUCH 1 /* DEPRECATED */
#define SENS_NEAR 2
#define SENS_KEYBOARD 3
#define SENS_PROPERTY 4
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index c562a1fefae..0478ff567a0 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -132,8 +132,9 @@ typedef struct SpaceButs {
short mainb, mainbo, mainbuser; /* context tabs */
short re_align, align; /* align for panels */
short preview; /* preview is signal to refresh */
- short texture_context; /* texture context selector (material, world, brush)*/
- char flag, pad;
+ /* texture context selector (material, lamp, particles, world, other)*/
+ short texture_context, texture_context_prev;
+ char flag, pad[7];
void *path; /* runtime */
int pathflag, dataicon; /* runtime */
@@ -246,6 +247,13 @@ typedef struct SpaceOops {
View2D v2d DNA_DEPRECATED; /* deprecated, copied to region */
ListBase tree;
+
+ /* treestore is an ordered list of TreeStoreElem's from outliner tree;
+ * Note that treestore may contain duplicate elements if element
+ * is used multiple times in outliner tree (e. g. linked objects)
+ * Also note that BLI_mempool can not be read/written in DNA directly,
+ * therefore readfile.c/writefile.c linearize treestore into TreeStore structure
+ */
struct BLI_mempool *treestore;
/* search stuff */
@@ -253,7 +261,9 @@ typedef struct SpaceOops {
struct TreeStoreElem search_tse;
short flag, outlinevis, storeflag, search_flags;
- struct GHash *treehash;
+
+ /* pointers to treestore elements, grouped by (id, type, nr) in hashtable for faster searching */
+ void *treehash;
} SpaceOops;
@@ -1083,6 +1093,8 @@ typedef struct SpaceClip {
int around, pad4; /* pivot point for transforms */
+ float cursor[2]; /* Mask editor 2d cursor */
+
MaskSpaceInfo mask_info;
} SpaceClip;
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index 0b6e5f9c7bb..fcd0575f1c5 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -263,7 +263,7 @@ typedef struct TexMapping {
float loc[3], rot[3], size[3];
int flag;
char projx, projy, projz, mapping;
- int pad;
+ int type;
float mat[4][4];
float min[3], max[3];
@@ -287,6 +287,12 @@ typedef struct ColorMapping {
#define TEXMAP_CLIP_MAX 2
#define TEXMAP_UNIT_MATRIX 4
+/* texmap->type */
+#define TEXMAP_TYPE_POINT 0
+#define TEXMAP_TYPE_TEXTURE 1
+#define TEXMAP_TYPE_VECTOR 2
+#define TEXMAP_TYPE_NORMAL 3
+
/* colormap->flag */
#define COLORMAP_USE_RAMP 1
diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h
index 04cd69bc5ae..49c1e3ed35d 100644
--- a/source/blender/makesdna/DNA_tracking_types.h
+++ b/source/blender/makesdna/DNA_tracking_types.h
@@ -144,6 +144,44 @@ typedef struct MovieTrackingTrack {
struct bGPdata *gpd; /* grease-pencil data */
} MovieTrackingTrack;
+typedef struct MovieTrackingPlaneMarker {
+ /* Corners of the plane in the following order:
+ *
+ * Y
+ * ^
+ * | (3) --- (2)
+ * | | |
+ * | | |
+ * | | |
+ * | (0) --- (1)
+ * +-------------> X
+ *
+ * The coordinates are stored in frame normalized coordinates.
+ */
+ float corners[4][2];
+
+ int framenr; /* Number of frame plane marker is associated with */
+ int flag; /* Marker's flag (alive, ...) */
+} MovieTrackingPlaneMarker;
+
+typedef struct MovieTrackingPlaneTrack {
+ struct MovieTrackingPlaneTrack *next, *prev;
+
+ char name[64]; /* MAX_NAME */
+
+ MovieTrackingTrack **point_tracks; /* Array of point tracks used to define this plane.
+ * Each element is a pointer to MovieTrackingTrack. */
+ int point_tracksnr, pad; /* Number of tracks in point_tracks array. */
+
+ MovieTrackingPlaneMarker *markers; /* Markers in the plane track */
+ int markersnr; /* Count of markers in track (size of markers array) */
+
+ int flag; /* flags (selection, ...) */
+
+ /* Runtime data */
+ int last_marker, pad2; /* Most recently used marker */
+} MovieTrackingPlaneTrack;
+
typedef struct MovieTrackingSettings {
int flag;
@@ -225,6 +263,7 @@ typedef struct MovieTrackingObject {
float scale; /* scale of object solution in amera space */
ListBase tracks; /* list of tracks use to tracking this object */
+ ListBase plane_tracks; /* list of plane tracks used by this object */
MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */
/* reconstruction options */
@@ -280,9 +319,11 @@ typedef struct MovieTracking {
MovieTrackingSettings settings; /* different tracking-related settings */
MovieTrackingCamera camera; /* camera intrinsics */
ListBase tracks; /* list of tracks used for camera object */
+ ListBase plane_tracks; /* list of plane tracks used by camera object */
MovieTrackingReconstruction reconstruction; /* reconstruction data for camera object */
MovieTrackingStabilization stabilization; /* stabilization data */
- MovieTrackingTrack *act_track; /* active track */
+ MovieTrackingTrack *act_track; /* active track */
+ MovieTrackingPlaneTrack *act_plane_track; /* active plane track */
ListBase objects;
int objectnr, tot_object; /* index of active object and total number of objects */
@@ -432,4 +473,17 @@ enum {
TRACKING_COVERAGE_OK = 2
};
+/* MovieTrackingPlaneMarker->flag */
+enum {
+ PLANE_MARKER_DISABLED = (1 << 0),
+ PLANE_MARKER_TRACKED = (1 << 1),
+};
+
+/* MovieTrackingPlaneTrack->flag */
+enum {
+ PLANE_TRACK_HIDDEN = (1 << 1),
+ PLANE_TRACK_LOCKED = (1 << 2),
+ PLANE_TRACK_AUTOKEY = (1 << 3),
+};
+
#endif /* __DNA_TRACKING_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index e0c5cd5608e..1621f7c6cb6 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -286,6 +286,9 @@ typedef struct ThemeSpace {
char preview_stitch_unstitchable[4];
char preview_stitch_active[4];
+ char uv_shadow[4];
+ char uv_others[4];
+
char match[4]; /* outliner - filter match */
char selected_highlight[4]; /* outliner - selected item */
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 27aef3b8ec6..07a679be571 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -339,6 +339,12 @@ typedef struct wmOperator {
#define OPERATOR_RETVAL_CHECK(ret) (void)ret, BLI_assert(ret != 0 && (ret & OPERATOR_FLAGS_ALL) == ret)
/* wmOperator flag */
-#define OP_GRAB_POINTER 1
+enum {
+ OP_GRAB_POINTER = (1 << 0),
+
+ /* low level flag so exec() operators can tell if they were invoked, use with care.
+ * typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */
+ OP_IS_INVOKE = (1 << 1),
+};
#endif /* __DNA_WINDOWMANAGER_TYPES_H__ */
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 70c79fa393c..cae607949a9 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -29,6 +29,7 @@ add_definitions(-DWITH_DNA_GHASH)
blender_include_dirs(
../../../../intern/guardedalloc
+ ../../../../intern/atomic
../../blenlib
..
)
@@ -80,6 +81,8 @@ set(SRC
${SRC_DNA_INC}
)
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/dna.c PROPERTIES GENERATED TRUE)
+
blender_add_lib(bf_dna "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript
index c0db40dcfd2..7c3af30ee83 100644
--- a/source/blender/makesdna/intern/SConscript
+++ b/source/blender/makesdna/intern/SConscript
@@ -46,7 +46,9 @@ dna = env.Clone()
makesdna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesdna/\\"" ')
makesdna_tool.Append (CPPPATH = ['#/intern/guardedalloc',
- '../../makesdna', '../../bmesh'])
+ '#/intern/atomic',
+ '../../makesdna', '../../bmesh',
+ '../../blenlib'])
if env['OURPLATFORM'] == 'linuxcross':
USE_WINE = True # when cross compiling on linux 64bit this is useful
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 1225821102a..ed7f6f5d765 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -530,7 +530,7 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
#ifdef WITH_DNA_GHASH
/* create a ghash lookup to speed up */
- sdna->structs_map = BLI_ghash_str_new("init_structDNA gh");
+ sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs);
for (nr = 0; nr < sdna->nr_structs; nr++) {
sp = sdna->structs[nr];
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 3a4eb66bc19..c3a8148431a 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -31,6 +31,8 @@
#include "RNA_types.h"
+#include "BLI_compiler_attrs.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -621,7 +623,6 @@ extern StructRNA RNA_ThemeWidgetStateColors;
extern StructRNA RNA_TimelineMarker;
extern StructRNA RNA_Timer;
extern StructRNA RNA_ToolSettings;
-extern StructRNA RNA_TouchSensor;
extern StructRNA RNA_TrackToConstraint;
extern StructRNA RNA_TransformConstraint;
extern StructRNA RNA_TransformSequence;
@@ -1035,15 +1036,15 @@ void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier);
/* python compatible string representation of this property, (must be freed!) */
char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length);
char *RNA_pointer_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop_ptr, PointerRNA *ptr_prop);
-char *RNA_pointer_as_string_keywords_ex(struct bContext *C, PointerRNA *ptr, PointerRNA *ptr_default,
- const short skip_optional_value, const short all_args,
+char *RNA_pointer_as_string_keywords_ex(struct bContext *C, PointerRNA *ptr,
+ const bool skip_optional_value, const bool all_args,
const int max_prop_length,
PropertyRNA *iterprop);
-char *RNA_pointer_as_string_keywords(struct bContext *C, PointerRNA *ptr, PointerRNA *ptr_default,
- const short skip_optional_value, const short all_args,
+char *RNA_pointer_as_string_keywords(struct bContext *C, PointerRNA *ptr,
+ const bool skip_optional_value, const bool all_args,
const int max_prop_length);
-char *RNA_function_as_string_keywords(struct bContext *C, FunctionRNA *func, PointerRNA *ptr_default,
- const short as_function, const short all_args,
+char *RNA_function_as_string_keywords(struct bContext *C, FunctionRNA *func,
+ const bool as_function, const bool all_args,
const int max_prop_length);
/* Function */
@@ -1074,10 +1075,11 @@ void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **value);
void RNA_parameter_get_lookup(ParameterList *parms, const char *identifier, void **value);
void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, const void *value);
void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, const void *value);
-int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm);
-int RNA_parameter_length_get_data(ParameterList *parms, PropertyRNA *parm, void *data);
-void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int length);
-void RNA_parameter_length_set_data(ParameterList *parms, PropertyRNA *parm, void *data, int length);
+/* Only for PROP_DYNAMIC properties! */
+int RNA_parameter_dynamic_length_get(ParameterList *parms, PropertyRNA *parm);
+int RNA_parameter_dynamic_length_get_data(ParameterList *parms, PropertyRNA *parm, void *data);
+void RNA_parameter_dynamic_length_set(ParameterList *parms, PropertyRNA *parm, int length);
+void RNA_parameter_dynamic_length_set_data(ParameterList *parms, PropertyRNA *parm, void *data, int length);
int RNA_function_call(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
FunctionRNA *func, ParameterList *parms);
@@ -1085,17 +1087,9 @@ int RNA_function_call_lookup(struct bContext *C, struct ReportList *reports, Poi
const char *identifier, ParameterList *parms);
int RNA_function_call_direct(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
- FunctionRNA *func, const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 5, 6)))
-#endif
-;
+ FunctionRNA *func, const char *format, ...) ATTR_PRINTF_FORMAT(5, 6);
int RNA_function_call_direct_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
- const char *identifier, const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 5, 6)))
-#endif
-;
+ const char *identifier, const char *format, ...) ATTR_PRINTF_FORMAT(5, 6);
int RNA_function_call_direct_va(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
FunctionRNA *func, const char *format, va_list args);
int RNA_function_call_direct_va_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
@@ -1121,17 +1115,19 @@ StructRNA *ID_code_to_RNA_type(short idcode);
# define RNA_warning(format, ...) _RNA_warning("%s: " format "\n", __FUNCTION__, __VA_ARGS__)
#endif
-void _RNA_warning(const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 1, 2)))
-#endif
-;
+void _RNA_warning(const char *format, ...) ATTR_PRINTF_FORMAT(1, 2);
/* Equals test (skips pointers and collections)
* is_strict false assumes uninitialized properties are equal */
-bool RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop, bool is_strict);
-bool RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b, bool is_strict);
+typedef enum eRNAEqualsMode {
+ RNA_EQ_STRICT, /* set/unset ignored */
+ RNA_EQ_UNSET_MATCH_ANY, /* unset property matches anything */
+ RNA_EQ_UNSET_MATCH_NONE /* unset property never matches set property */
+} eRNAEqualsMode;
+
+bool RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop, eRNAEqualsMode mode);
+bool RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b, eRNAEqualsMode mode);
#ifdef __cplusplus
}
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 924fc505fda..d686a5951eb 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -42,8 +42,8 @@ extern "C" {
BlenderRNA *RNA_create(void);
void RNA_define_free(BlenderRNA *brna);
void RNA_free(BlenderRNA *brna);
-void RNA_define_verify_sdna(int verify);
-void RNA_define_animate_sdna(int animate);
+void RNA_define_verify_sdna(bool verify);
+void RNA_define_animate_sdna(bool animate);
void RNA_init(void);
void RNA_exit(void);
@@ -164,7 +164,7 @@ void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *update
void RNA_def_property_editable_func(PropertyRNA *prop, const char *editable);
void RNA_def_property_editable_array_func(PropertyRNA *prop, const char *editable);
-void RNA_def_property_update_runtime(PropertyRNA *prop, void *func);
+void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func);
void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength);
void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const char *set);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 86d043b839a..d33d3df8a5e 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -169,6 +169,8 @@ extern EnumPropertyItem linestyle_alpha_modifier_type_items[];
extern EnumPropertyItem linestyle_thickness_modifier_type_items[];
extern EnumPropertyItem linestyle_geometry_modifier_type_items[];
+extern EnumPropertyItem window_cursor_items[];
+
struct bContext;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 69cb2caf058..43bf1973c33 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -69,27 +69,27 @@ typedef struct PropertyPointerRNA {
/* Property */
typedef enum PropertyType {
- PROP_BOOLEAN = 0,
- PROP_INT = 1,
- PROP_FLOAT = 2,
- PROP_STRING = 3,
- PROP_ENUM = 4,
- PROP_POINTER = 5,
- PROP_COLLECTION = 6
+ PROP_BOOLEAN = 0,
+ PROP_INT = 1,
+ PROP_FLOAT = 2,
+ PROP_STRING = 3,
+ PROP_ENUM = 4,
+ PROP_POINTER = 5,
+ PROP_COLLECTION = 6,
} PropertyType;
/* also update rna_property_subtype_unit when you change this */
typedef enum PropertyUnit {
- PROP_UNIT_NONE = (0 << 16),
- PROP_UNIT_LENGTH = (1 << 16), /* m */
- PROP_UNIT_AREA = (2 << 16), /* m^2 */
- PROP_UNIT_VOLUME = (3 << 16), /* m^3 */
- PROP_UNIT_MASS = (4 << 16), /* kg */
- PROP_UNIT_ROTATION = (5 << 16), /* radians */
- PROP_UNIT_TIME = (6 << 16), /* frame */
- PROP_UNIT_VELOCITY = (7 << 16), /* m/s */
+ PROP_UNIT_NONE = (0 << 16),
+ PROP_UNIT_LENGTH = (1 << 16), /* m */
+ PROP_UNIT_AREA = (2 << 16), /* m^2 */
+ PROP_UNIT_VOLUME = (3 << 16), /* m^3 */
+ PROP_UNIT_MASS = (4 << 16), /* kg */
+ PROP_UNIT_ROTATION = (5 << 16), /* radians */
+ PROP_UNIT_TIME = (6 << 16), /* frame */
+ PROP_UNIT_VELOCITY = (7 << 16), /* m/s */
PROP_UNIT_ACCELERATION = (8 << 16), /* m/(s^2) */
- PROP_UNIT_CAMERA = (9 << 16) /* mm */
+ PROP_UNIT_CAMERA = (9 << 16), /* mm */
} PropertyUnit;
#define RNA_SUBTYPE_UNIT(subtype) ((subtype) & 0x00FF0000)
@@ -105,95 +105,101 @@ typedef enum PropertyUnit {
* node socket button subtypes!
*/
typedef enum PropertySubType {
- PROP_NONE = 0,
+ PROP_NONE = 0,
/* strings */
- PROP_FILEPATH = 1,
- PROP_DIRPATH = 2,
- PROP_FILENAME = 3,
- PROP_BYTESTRING = 4, /* a string which should be represented as bytes in python, still NULL terminated though. */
+ PROP_FILEPATH = 1,
+ PROP_DIRPATH = 2,
+ PROP_FILENAME = 3,
+ PROP_BYTESTRING = 4, /* a string which should be represented as bytes in python, NULL terminated though. */
/* 5 was used by "PROP_TRANSLATE" sub-type, which is now a flag. */
- PROP_PASSWORD = 6, /* a string which should not be displayed in UI */
+ PROP_PASSWORD = 6, /* a string which should not be displayed in UI */
/* numbers */
- PROP_UNSIGNED = 13,
- PROP_PERCENTAGE = 14,
- PROP_FACTOR = 15,
- PROP_ANGLE = 16 | PROP_UNIT_ROTATION,
- PROP_TIME = 17 | PROP_UNIT_TIME,
+ PROP_UNSIGNED = 13,
+ PROP_PERCENTAGE = 14,
+ PROP_FACTOR = 15,
+ PROP_ANGLE = 16 | PROP_UNIT_ROTATION,
+ PROP_TIME = 17 | PROP_UNIT_TIME,
/* distance in 3d space, don't use for pixel distance for eg. */
- PROP_DISTANCE = 18 | PROP_UNIT_LENGTH,
- PROP_DISTANCE_CAMERA = 19 | PROP_UNIT_CAMERA,
+ PROP_DISTANCE = 18 | PROP_UNIT_LENGTH,
+ PROP_DISTANCE_CAMERA = 19 | PROP_UNIT_CAMERA,
/* number arrays */
- PROP_COLOR = 20,
- PROP_TRANSLATION = 21 | PROP_UNIT_LENGTH,
- PROP_DIRECTION = 22,
- PROP_VELOCITY = 23 | PROP_UNIT_VELOCITY,
- PROP_ACCELERATION = 24 | PROP_UNIT_ACCELERATION,
- PROP_MATRIX = 25,
- PROP_EULER = 26 | PROP_UNIT_ROTATION,
- PROP_QUATERNION = 27,
- PROP_AXISANGLE = 28,
- PROP_XYZ = 29,
- PROP_XYZ_LENGTH = 29 | PROP_UNIT_LENGTH,
- PROP_COLOR_GAMMA = 30, /* used for colors which would be color managed before display */
- PROP_COORDS = 31, /* generic array, no units applied, only that x/y/z/w are used (python vec) */
+ PROP_COLOR = 20,
+ PROP_TRANSLATION = 21 | PROP_UNIT_LENGTH,
+ PROP_DIRECTION = 22,
+ PROP_VELOCITY = 23 | PROP_UNIT_VELOCITY,
+ PROP_ACCELERATION = 24 | PROP_UNIT_ACCELERATION,
+ PROP_MATRIX = 25,
+ PROP_EULER = 26 | PROP_UNIT_ROTATION,
+ PROP_QUATERNION = 27,
+ PROP_AXISANGLE = 28,
+ PROP_XYZ = 29,
+ PROP_XYZ_LENGTH = 29 | PROP_UNIT_LENGTH,
+ PROP_COLOR_GAMMA = 30, /* used for colors which would be color managed before display */
+ PROP_COORDS = 31, /* generic array, no units applied, only that x/y/z/w are used (python vec) */
/* booleans */
- PROP_LAYER = 40,
- PROP_LAYER_MEMBER = 41
+ PROP_LAYER = 40,
+ PROP_LAYER_MEMBER = 41,
} PropertySubType;
-/* Make sure enums are updated with thses */
-/* HIGHEST FLAG IN USE: 1 << 29 */
+/* Make sure enums are updated with these */
+/* HIGHEST FLAG IN USE: 1 << 30 */
typedef enum PropertyFlag {
/* editable means the property is editable in the user
* interface, properties are editable by default except
* for pointers and collections. */
- PROP_EDITABLE = (1 << 0),
+ PROP_EDITABLE = (1 << 0),
/* this property is editable even if it is lib linked,
* meaning it will get lost on reload, but it's useful
* for editing. */
- PROP_LIB_EXCEPTION = (1 << 16),
+ PROP_LIB_EXCEPTION = (1 << 16),
/* animatable means the property can be driven by some
* other input, be it animation curves, expressions, ..
* properties are animatable by default except for pointers
* and collections */
- PROP_ANIMATABLE = (1 << 1),
+ PROP_ANIMATABLE = (1 << 1),
/* icon */
- PROP_ICONS_CONSECUTIVE = (1 << 12),
+ PROP_ICONS_CONSECUTIVE = (1 << 12),
/* hidden in the user interface */
- PROP_HIDDEN = (1 << 19),
+ PROP_HIDDEN = (1 << 19),
/* do not write in presets */
- PROP_SKIP_SAVE = (1 << 28),
-
- /* function paramater flags */
- PROP_REQUIRED = (1 << 2),
- PROP_OUTPUT = (1 << 3),
- PROP_RNAPTR = (1 << 11),
+ PROP_SKIP_SAVE = (1 << 28),
+
+ /* function parameter flags */
+ PROP_REQUIRED = (1 << 2),
+ PROP_OUTPUT = (1 << 3),
+ PROP_RNAPTR = (1 << 11),
+ /* This allows for non-breaking API updates, when adding non-critical new parameter to a callback function.
+ * This way, old py code defining funcs without that parameter would still work.
+ * WARNING: any parameter after the first PYFUNC_OPTIONAL one will be considered as optional!
+ * NOTE: only for input parameters!
+ */
+ PROP_PYFUNC_OPTIONAL = (1 << 30),
/* registering */
- PROP_REGISTER = (1 << 4),
- PROP_REGISTER_OPTIONAL = (1 << 4) | (1 << 5),
+ PROP_REGISTER = (1 << 4),
+ PROP_REGISTER_OPTIONAL = PROP_REGISTER | (1 << 5),
/* pointers */
- PROP_ID_REFCOUNT = (1 << 6),
+ PROP_ID_REFCOUNT = (1 << 6),
/* disallow assigning a variable to its self, eg an object tracking its self
* only apply this to types that are derived from an ID ()*/
- PROP_ID_SELF_CHECK = (1 << 20),
+ PROP_ID_SELF_CHECK = (1 << 20),
/* use for...
* - pointers: in the UI and python so unsetting or setting to None won't work
* - strings: so our internal generated get/length/set functions know to do NULL checks before access [#30865] */
- PROP_NEVER_NULL = (1 << 18),
+ PROP_NEVER_NULL = (1 << 18),
/* currently only used for UI, this is similar to PROP_NEVER_NULL
* except that the value may be NULL at times, used for ObData, where an Empty's will be NULL
* but setting NULL on a mesh object is not possible. So, if its not NULL, setting NULL cant be done! */
- PROP_NEVER_UNLINK = (1 << 25),
+ PROP_NEVER_UNLINK = (1 << 25),
/* flag contains multiple enums.
* note: not to be confused with prop->enumbitflags
@@ -201,33 +207,33 @@ typedef enum PropertyFlag {
*
* note: these can't be animated so use with care.
*/
- PROP_ENUM_FLAG = (1 << 21),
+ PROP_ENUM_FLAG = (1 << 21),
/* need context for update function */
- PROP_CONTEXT_UPDATE = (1 << 22),
+ PROP_CONTEXT_UPDATE = (1 << 22),
PROP_CONTEXT_PROPERTY_UPDATE = (1 << 22) | (1 << 27),
/* Use for arrays or for any data that should not have a reference kept
* most common case is functions that return arrays where the array */
- PROP_THICK_WRAP = (1 << 23),
+ PROP_THICK_WRAP = (1 << 23),
/* Reject values outside limits, use for python api only so far
* this is for use when silently clamping string length will give
* bad behavior later. Could also enforce this for INT's and other types.
* note: currently no support for function arguments or non utf8 paths (filepaths) */
- PROP_NEVER_CLAMP = (1 << 26),
+ PROP_NEVER_CLAMP = (1 << 26),
/* internal flags */
- PROP_BUILTIN = (1 << 7),
- PROP_EXPORT = (1 << 8),
- PROP_RUNTIME = (1 << 9),
- PROP_IDPROPERTY = (1 << 10),
- PROP_RAW_ACCESS = (1 << 13),
- PROP_RAW_ARRAY = (1 << 14),
- PROP_FREE_POINTERS = (1 << 15),
- PROP_DYNAMIC = (1 << 17), /* for dynamic arrays, and retvals of type string */
- PROP_ENUM_NO_CONTEXT = (1 << 24), /* for enum that shouldn't be contextual */
- PROP_ENUM_NO_TRANSLATE = (1 << 29), /* for enums that shouldn't be translated (e.g. renderlayers' names in nodes) */
+ PROP_BUILTIN = (1 << 7),
+ PROP_EXPORT = (1 << 8),
+ PROP_RUNTIME = (1 << 9),
+ PROP_IDPROPERTY = (1 << 10),
+ PROP_RAW_ACCESS = (1 << 13),
+ PROP_RAW_ARRAY = (1 << 14),
+ PROP_FREE_POINTERS = (1 << 15),
+ PROP_DYNAMIC = (1 << 17), /* for dynamic arrays, and retvals of type string */
+ PROP_ENUM_NO_CONTEXT = (1 << 24), /* for enum that shouldn't be contextual */
+ PROP_ENUM_NO_TRANSLATE = (1 << 29), /* for enums not to be translated (e.g. renderlayers' names in nodes) */
} PropertyFlag;
typedef struct CollectionPropertyIterator {
@@ -332,23 +338,23 @@ typedef struct ParameterDynAlloc {
/* Function */
typedef enum FunctionFlag {
- FUNC_NO_SELF = 1, /* for static functions */
- FUNC_USE_SELF_TYPE = 2, /* for class methods, only used when FUNC_NO_SELF is set */
- FUNC_USE_MAIN = 4,
- FUNC_USE_CONTEXT = 8,
- FUNC_USE_REPORTS = 16,
- FUNC_USE_SELF_ID = 2048,
- FUNC_ALLOW_WRITE = 4096,
+ 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 */
+ 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 */
- FUNC_REGISTER = 32,
- FUNC_REGISTER_OPTIONAL = 32 | 64,
+ FUNC_REGISTER = (1 << 5),
+ FUNC_REGISTER_OPTIONAL = FUNC_REGISTER | (1 << 6),
/* internal flags */
- FUNC_BUILTIN = 128,
- FUNC_EXPORT = 256,
- FUNC_RUNTIME = 512,
- FUNC_FREE_POINTERS = 1024
+ FUNC_BUILTIN = (1 << 7),
+ FUNC_EXPORT = (1 << 8),
+ FUNC_RUNTIME = (1 << 9),
+ FUNC_FREE_POINTERS = (1 << 10),
} FunctionFlag;
typedef void (*CallFunc)(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, ParameterList *parms);
@@ -359,15 +365,15 @@ typedef struct FunctionRNA FunctionRNA;
typedef enum StructFlag {
/* indicates that this struct is an ID struct, and to use refcounting */
- STRUCT_ID = 1,
- STRUCT_ID_REFCOUNT = 2,
- STRUCT_UNDO = 4, /* defaults on, clear for user preferences and similar */
+ STRUCT_ID = (1 << 0),
+ STRUCT_ID_REFCOUNT = (1 << 1),
+ STRUCT_UNDO = (1 << 2), /* defaults on, clear for user preferences and similar */
/* internal flags */
- STRUCT_RUNTIME = 8,
- STRUCT_GENERATED = 16,
- STRUCT_FREE_POINTERS = 32,
- STRUCT_NO_IDPROPERTIES = 64 /* Menu's and Panels don't need properties */
+ STRUCT_RUNTIME = (1 << 3),
+ STRUCT_GENERATED = (1 << 4),
+ STRUCT_FREE_POINTERS = (1 << 5),
+ STRUCT_NO_IDPROPERTIES = (1 << 6), /* Menu's and Panels don't need properties */
} StructFlag;
typedef int (*StructValidateFunc)(struct PointerRNA *ptr, void *data, int *have_function);
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 2d0c4260c97..dfe1ebb3385 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -36,6 +36,7 @@ incs = [
'.',
'./intern',
'#/intern/guardedalloc',
+ '#/intern/atomic',
'#/intern/memutil',
'#/extern/glew/include',
'#/intern/audaspace/intern',
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 592c518e9c0..d901897cbc4 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -23,9 +23,6 @@
#
# ***** END GPL LICENSE BLOCK *****
-# Generated code has some unused vars we can ignore.
-remove_strict_flags()
-
if(CMAKE_COMPILER_IS_GNUCC)
# add here so we fail early.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration")
@@ -124,7 +121,7 @@ set(APISRC
)
string(REGEX REPLACE "rna_([a-zA-Z0-9_-]*).c" "${CMAKE_CURRENT_BINARY_DIR}/rna_\\1_gen.c" GENSRC "${DEFSRC}")
-set_source_files_properties(GENSRC PROPERTIES GENERATED true)
+set_source_files_properties(${GENSRC} PROPERTIES GENERATED TRUE)
set(SRC_RNA_INC
../RNA_access.h
@@ -276,6 +273,7 @@ blender_include_dirs(
../../../../intern/audaspace/intern
../../../../intern/cycles/blender
../../../../intern/guardedalloc
+ ../../../../intern/atomic
../../../../intern/memutil
../../../../intern/smoke/extern
)
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index c158facca7c..a908b403c03 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -2273,11 +2273,12 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
valstr = "*";
}
- /* this must be kept in sync with RNA_parameter_length_get_data,
+ /* this must be kept in sync with RNA_parameter_dynamic_length_get_data and RNA_parameter_get,
* we could just call the function directly, but this is faster */
if (flag & PROP_DYNAMIC) {
- fprintf(f, "\t%s_len = %s((int *)_data);\n", dparm->prop->identifier, pout ? "" : "*");
- data_str = "(&(((char *)_data)[sizeof(void *)]))";
+ fprintf(f, "\t%s_len = %s((ParameterDynAlloc *)_data)->array_tot;\n", dparm->prop->identifier,
+ pout ? "(int *)&" : "(int)");
+ data_str = "(&(((ParameterDynAlloc *)_data)->array))";
}
else {
data_str = "_data";
@@ -2691,7 +2692,11 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F
}
+ /* ensure func(void) if there are no args */
+ if (first) fprintf(f, "void");
+
fprintf(f, ")");
+
if (close_prototype)
fprintf(f, ";\n");
}
@@ -2763,7 +2768,7 @@ static void rna_generate_struct_prototypes(FILE *f)
static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, PropertyRNA *prop)
{
- char *strnest = "", *errnest = "";
+ char *strnest = (char *)"", *errnest = (char *)"";
int len, freenest = 0;
if (nest != NULL) {
@@ -3329,6 +3334,12 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
fprintf(f, "#include \"%s\"\n", api_filename);
fprintf(f, "\n");
+ /* we want the included C files to have warnings enabled but for the generated code
+ * ignore unused-parameter warnings which are hard to prevent */
+#ifdef __GNUC__
+ fprintf(f, "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n\n");
+#endif
+
fprintf(f, "/* Autogenerated Functions */\n\n");
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) {
@@ -3544,8 +3555,12 @@ static const char *cpp_classes = ""
" } \n"
"#define COLLECTION_PROPERTY_LOOKUP_INT_TRUE(sname, identifier) \\\n"
" inline static int sname##_##identifier##_lookup_int_wrap(PointerRNA *ptr, int key, PointerRNA *r_ptr) \\\n"
-" { return sname##_##identifier##_lookup_int(ptr, key, r_ptr); } \n"
-"\n"
+" { \\\n"
+" int found = sname##_##identifier##_lookup_int(ptr, key, r_ptr); \\\n"
+" if (!found) \\\n"
+" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n"
+" return found; \\\n"
+" } \n"
"#define COLLECTION_PROPERTY_LOOKUP_STRING_FALSE(sname, identifier) \\\n"
" inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n"
" { \\\n"
@@ -3573,8 +3588,12 @@ static const char *cpp_classes = ""
" } \n"
"#define COLLECTION_PROPERTY_LOOKUP_STRING_TRUE(sname, identifier) \\\n"
" inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n"
-" { return sname##_##identifier##_lookup_string(ptr, key, r_ptr); } \n"
-"\n"
+" { \\\n"
+" int found = sname##_##identifier##_lookup_string(ptr, key, r_ptr); \\\n"
+" if (!found) \\\n"
+" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n"
+" return found; \\\n"
+" } \n"
"#define COLLECTION_PROPERTY(collection_funcs, type, sname, identifier, has_length, has_lookup_int, has_lookup_string) \\\n"
" typedef CollectionIterator<type, sname##_##identifier##_begin, \\\n"
" sname##_##identifier##_next, sname##_##identifier##_end> identifier##_iterator; \\\n"
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 26febf217a6..075f852a032 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -36,6 +36,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_types.h"
@@ -57,7 +58,7 @@ EnumPropertyItem id_type_items[] = {
{ID_KE, "KEY", ICON_SHAPEKEY_DATA, "Key", ""},
{ID_LA, "LAMP", ICON_LAMP_DATA, "Lamp", ""},
{ID_LI, "LIBRARY", ICON_LIBRARY_DATA_DIRECT, "Library", ""},
- {ID_LS, "LINESTYLE", ICON_PARTICLE_DATA, "FreestyleLineStyle", ""}, /* FIXME proper icon */
+ {ID_LS, "LINESTYLE", ICON_BRUSH_DATA, "Line Style", ""}, /* FIXME proper icon */
{ID_LT, "LATTICE", ICON_LATTICE_DATA, "Lattice", ""},
{ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""},
{ID_MB, "META", ICON_META_DATA, "MetaBall", ""},
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index f3e561cde0a..341ba02fd47 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -49,6 +49,7 @@
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
+#include "BKE_fcurve.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -650,7 +651,7 @@ static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
{
PropertyRNA *prop = NULL;
- RNA_STRUCT_BEGIN(ptr, iprop)
+ RNA_STRUCT_BEGIN (ptr, iprop)
{
/* This assumes that there can only be one user of this nested struct */
if (RNA_property_pointer_type(ptr, iprop) == srna) {
@@ -673,7 +674,7 @@ bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
iterprop = RNA_struct_iterator_property(ptr->type);
- RNA_PROP_BEGIN(ptr, itemptr, iterprop)
+ RNA_PROP_BEGIN (ptr, itemptr, iterprop)
{
/* PropertyRNA *prop = itemptr.data; */
if (prop_test == (PropertyRNA *)itemptr.data) {
@@ -721,7 +722,7 @@ FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
func = NULL;
- RNA_PROP_BEGIN(&tptr, funcptr, iterprop)
+ RNA_PROP_BEGIN (&tptr, funcptr, iterprop)
{
if (strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) {
func = funcptr.data;
@@ -1512,14 +1513,24 @@ bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
return (prop->flag & PROP_EDITABLE) != 0;
}
-bool RNA_property_animated(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
+bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
{
- /* would need to ask animation system */
+ int len = 1, index;
+ bool driven;
+
+ if (!prop)
+ return false;
+
+ if (RNA_property_array_check(prop))
+ len = RNA_property_array_length(ptr, prop);
+
+ for (index = 0; index < len; index++)
+ if (rna_get_fcurve(ptr, prop, index, NULL, &driven))
+ return true;
return false;
}
-
/* 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)
@@ -3329,7 +3340,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
}
/* no item property pointer, can still be id property, or
* property of a type derived from the collection pointer type */
- RNA_PROP_BEGIN(ptr, itemptr, prop)
+ RNA_PROP_BEGIN (ptr, itemptr, prop)
{
if (itemptr.data) {
if (itemprop) {
@@ -4164,7 +4175,7 @@ static char *rna_idp_path_create(IDP_Chain *child_link)
{
DynStr *dynstr = BLI_dynstr_new();
char *path;
- short first = TRUE;
+ bool is_first = true;
int tot = 0;
IDP_Chain *link = child_link;
@@ -4183,13 +4194,13 @@ static char *rna_idp_path_create(IDP_Chain *child_link)
for (link = link_prev; link; link = link->up) {
/* pass */
if (link->index >= 0) {
- BLI_dynstr_appendf(dynstr, first ? "%s[%d]" : ".%s[%d]", link->name, link->index);
+ BLI_dynstr_appendf(dynstr, is_first ? "%s[%d]" : ".%s[%d]", link->name, link->index);
}
else {
- BLI_dynstr_appendf(dynstr, first ? "%s" : ".%s", link->name);
+ BLI_dynstr_appendf(dynstr, is_first ? "%s" : ".%s", link->name);
}
- first = FALSE;
+ is_first = false;
}
path = BLI_dynstr_get_cstring(dynstr);
@@ -4408,10 +4419,12 @@ char *RNA_path_full_struct_py(struct PointerRNA *ptr)
data_path = RNA_path_from_ID_to_struct(ptr);
- ret = BLI_sprintfN("%s.%s",
- id_path, data_path);
+ /* XXX data_path may be NULL (see #36788), do we want to get the 'bpy.data.foo["bar"].(null)' stuff? */
+ ret = BLI_sprintfN("%s.%s", id_path, data_path);
- MEM_freeN(data_path);
+ if (data_path) {
+ MEM_freeN(data_path);
+ }
MEM_freeN(id_path);
return ret;
@@ -4982,7 +4995,7 @@ static char *rna_pointer_as_string__idprop(bContext *C, PointerRNA *ptr)
BLI_dynstr_append(dynstr, "{");
- RNA_STRUCT_BEGIN(ptr, prop)
+ RNA_STRUCT_BEGIN (ptr, prop)
{
propname = RNA_property_identifier(prop);
@@ -5030,9 +5043,9 @@ char *RNA_pointer_as_string(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *p
}
}
-/* context and ptr_default can be NULL */
-char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA *ptr_default,
- const short as_function, const short all_args,
+/* context can be NULL */
+char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr,
+ const bool as_function, const bool all_args,
const int max_prop_length,
PropertyRNA *iterprop)
{
@@ -5042,14 +5055,10 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA
DynStr *dynstr = BLI_dynstr_new();
char *cstring, *buf;
- int first_iter = TRUE, ok = TRUE;
+ bool first_iter = true;
int flag;
- /* only to get the orginal props for comparisons */
- PropertyRNA *prop_default;
- char *buf_default;
-
- RNA_PROP_BEGIN(ptr, propptr, iterprop)
+ RNA_PROP_BEGIN (ptr, propptr, iterprop)
{
prop = propptr.data;
@@ -5068,45 +5077,37 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA
if (as_function && (flag & PROP_REQUIRED)) {
/* required args don't have useful defaults */
BLI_dynstr_appendf(dynstr, first_iter ? "%s" : ", %s", arg_name);
- first_iter = FALSE;
+ first_iter = false;
}
else {
- if (as_function && RNA_property_type(prop) == PROP_POINTER) {
- /* don't expand pointers for functions */
- if (flag & PROP_NEVER_NULL) {
- /* we cant really do the right thing here. arg=arg?, hrmf! */
- buf = BLI_strdup(arg_name);
- }
- else {
- buf = BLI_strdup("None");
- }
+ bool ok = true;
+
+ if (all_args == true) {
+ /* pass */
}
- else {
- buf = RNA_property_as_string(C, ptr, prop, -1, max_prop_length);
+ else if (RNA_struct_idprops_check(ptr->type)) {
+ ok = RNA_property_is_set(ptr, prop);
}
- ok = TRUE;
-
- if (all_args == FALSE && ptr_default) {
- /* not verbose, so only add in attributes that use non-default values
- * slow but good for tooltips */
- prop_default = RNA_struct_find_property(ptr_default, arg_name);
-
- if (prop_default) {
- buf_default = RNA_property_as_string(C, ptr_default, prop_default, -1, max_prop_length);
-
- if (strcmp(buf, buf_default) == 0)
- ok = FALSE; /* values match, don't bother printing */
-
- MEM_freeN(buf_default);
- }
- }
if (ok) {
+ if (as_function && RNA_property_type(prop) == PROP_POINTER) {
+ /* don't expand pointers for functions */
+ if (flag & PROP_NEVER_NULL) {
+ /* we cant really do the right thing here. arg=arg?, hrmf! */
+ buf = BLI_strdup(arg_name);
+ }
+ else {
+ buf = BLI_strdup("None");
+ }
+ }
+ else {
+ buf = RNA_property_as_string(C, ptr, prop, -1, max_prop_length);
+ }
+
BLI_dynstr_appendf(dynstr, first_iter ? "%s=%s" : ", %s=%s", arg_name, buf);
- first_iter = FALSE;
+ first_iter = false;
+ MEM_freeN(buf);
}
-
- MEM_freeN(buf);
}
}
RNA_PROP_END;
@@ -5116,20 +5117,20 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA
return cstring;
}
-char *RNA_pointer_as_string_keywords(bContext *C, PointerRNA *ptr, PointerRNA *ptr_default,
- const short as_function, const short all_args,
+char *RNA_pointer_as_string_keywords(bContext *C, PointerRNA *ptr,
+ const bool as_function, const bool all_args,
const int max_prop_length)
{
PropertyRNA *iterprop;
iterprop = RNA_struct_iterator_property(ptr->type);
- return RNA_pointer_as_string_keywords_ex(C, ptr, ptr_default, as_function, all_args,
+ return RNA_pointer_as_string_keywords_ex(C, ptr, as_function, all_args,
max_prop_length, iterprop);
}
-char *RNA_function_as_string_keywords(bContext *C, FunctionRNA *func, PointerRNA *ptr_default,
- const short as_function, const short all_args,
+char *RNA_function_as_string_keywords(bContext *C, FunctionRNA *func,
+ const bool as_function, const bool all_args,
const int max_prop_length)
{
PointerRNA funcptr;
@@ -5141,7 +5142,7 @@ char *RNA_function_as_string_keywords(bContext *C, FunctionRNA *func, PointerRNA
RNA_struct_iterator_property(funcptr.type);
- return RNA_pointer_as_string_keywords_ex(C, &funcptr, ptr_default, as_function, all_args,
+ return RNA_pointer_as_string_keywords_ex(C, &funcptr, as_function, all_args,
max_prop_length, iterprop);
}
@@ -5160,7 +5161,7 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, in
char *cstring;
- /* see if we can coorce into a python type - PropertyType */
+ /* see if we can coerce into a python type - PropertyType */
switch (type) {
case PROP_BOOLEAN:
if (len == 0) {
@@ -5252,11 +5253,11 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, in
RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
if (item) {
- short is_first = TRUE;
+ bool is_first = false;
for (; item->identifier; item++) {
if (item->identifier[0] && item->value & val) {
BLI_dynstr_appendf(dynstr, is_first ? "'%s'" : ", '%s'", item->identifier);
- is_first = FALSE;
+ is_first = false;
}
}
@@ -5357,7 +5358,14 @@ PropertyRNA *RNA_function_get_parameter(PointerRNA *UNUSED(ptr), FunctionRNA *fu
PropertyRNA *RNA_function_find_parameter(PointerRNA *UNUSED(ptr), FunctionRNA *func, const char *identifier)
{
- return BLI_findstring(&func->cont.properties, identifier, offsetof(PropertyRNA, identifier));
+ PropertyRNA *parm;
+
+ parm = func->cont.properties.first;
+ for (; parm; parm = parm->next)
+ if (strcmp(RNA_property_identifier(parm), identifier) == 0)
+ break;
+
+ return parm;
}
const ListBase *RNA_function_defined_parameters(FunctionRNA *func)
@@ -5529,10 +5537,19 @@ void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **value)
if (iter.parm == parm)
break;
- if (iter.valid)
- *value = iter.data;
- else
+ if (iter.valid) {
+ if (parm->flag & PROP_DYNAMIC) {
+ /* for dynamic arrays and strings, data is a pointer to an array */
+ ParameterDynAlloc *data_alloc = iter.data;
+ *value = data_alloc->array;
+ }
+ else {
+ *value = iter.data;
+ }
+ }
+ else {
*value = NULL;
+ }
RNA_parameter_list_end(&iter);
}
@@ -5560,8 +5577,35 @@ void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, const void *valu
if (iter.parm == parm)
break;
- if (iter.valid)
- memcpy(iter.data, value, iter.size);
+ if (iter.valid) {
+ if (parm->flag & PROP_DYNAMIC) {
+ /* for dynamic arrays and strings, data is a pointer to an array */
+ ParameterDynAlloc *data_alloc = iter.data;
+ size_t size = 0;
+ switch (parm->type) {
+ case PROP_STRING:
+ size = sizeof(char);
+ break;
+ case PROP_INT:
+ case PROP_BOOLEAN:
+ size = sizeof(int);
+ break;
+ case PROP_FLOAT:
+ size = sizeof(float);
+ break;
+ default:
+ break;
+ }
+ size *= data_alloc->array_tot;
+ if (data_alloc->array)
+ MEM_freeN(data_alloc->array);
+ data_alloc->array = MEM_mallocN(size, AT);
+ memcpy(data_alloc->array, value, size);
+ }
+ else {
+ memcpy(iter.data, value, iter.size);
+ }
+ }
RNA_parameter_list_end(&iter);
}
@@ -5579,7 +5623,7 @@ void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, cons
RNA_parameter_set(parms, parm, value);
}
-int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm)
+int RNA_parameter_dynamic_length_get(ParameterList *parms, PropertyRNA *parm)
{
ParameterIterator iter;
int len = 0;
@@ -5591,14 +5635,14 @@ int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm)
break;
if (iter.valid)
- len = RNA_parameter_length_get_data(parms, parm, iter.data);
+ len = RNA_parameter_dynamic_length_get_data(parms, parm, iter.data);
RNA_parameter_list_end(&iter);
return len;
}
-void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int length)
+void RNA_parameter_dynamic_length_set(ParameterList *parms, PropertyRNA *parm, int length)
{
ParameterIterator iter;
@@ -5609,19 +5653,24 @@ void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int lengt
break;
if (iter.valid)
- RNA_parameter_length_set_data(parms, parm, iter.data, length);
+ RNA_parameter_dynamic_length_set_data(parms, parm, iter.data, length);
RNA_parameter_list_end(&iter);
}
-int RNA_parameter_length_get_data(ParameterList *UNUSED(parms), PropertyRNA *UNUSED(parm), void *data)
+int RNA_parameter_dynamic_length_get_data(ParameterList *UNUSED(parms), PropertyRNA *parm, void *data)
{
- return *((int *)((char *)data));
+ if (parm->flag & PROP_DYNAMIC) {
+ return (int)((ParameterDynAlloc *)data)->array_tot;
+ }
+ return 0;
}
-void RNA_parameter_length_set_data(ParameterList *UNUSED(parms), PropertyRNA *UNUSED(parm), void *data, int length)
+void RNA_parameter_dynamic_length_set_data(ParameterList *UNUSED(parms), PropertyRNA *parm, void *data, int length)
{
- *((int *)data) = length;
+ if (parm->flag & PROP_DYNAMIC) {
+ ((ParameterDynAlloc *)data)->array_tot = (intptr_t)length;
+ }
}
int RNA_function_call(bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
@@ -6269,14 +6318,20 @@ void _RNA_warning(const char *format, ...)
#endif
}
-bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, bool is_strict)
+bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNAEqualsMode mode)
{
int len, fromlen;
- /* if not strict, uninitialized properties are assumed to match */
- if (!is_strict)
- if (!(RNA_property_is_set(a, prop) && RNA_property_is_set(b, prop)))
+ if (mode == RNA_EQ_UNSET_MATCH_ANY) {
+ /* uninitialized properties are assumed to match anything */
+ if (!RNA_property_is_set(a, prop) || !RNA_property_is_set(b, prop))
return true;
+ }
+ else if (mode == RNA_EQ_UNSET_MATCH_NONE) {
+ /* unset properties never match set properties */
+ if (RNA_property_is_set(a, prop) != RNA_property_is_set(b, prop))
+ return false;
+ }
/* get the length of the array to work with */
len = RNA_property_array_length(a, prop);
@@ -6390,7 +6445,7 @@ bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, bool i
if (!STREQ(RNA_property_identifier(prop), "rna_type")) {
PointerRNA propptr_a = RNA_property_pointer_get(a, prop);
PointerRNA propptr_b = RNA_property_pointer_get(b, prop);
- return RNA_struct_equals(&propptr_a, &propptr_b, is_strict);
+ return RNA_struct_equals(&propptr_a, &propptr_b, mode);
}
break;
}
@@ -6402,7 +6457,7 @@ bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, bool i
return true;
}
-bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, bool is_strict)
+bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, eRNAEqualsMode mode)
{
CollectionPropertyIterator iter;
// CollectionPropertyRNA *citerprop; /* UNUSED */
@@ -6423,7 +6478,7 @@ bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, bool is_strict)
for (; iter.valid; RNA_property_collection_next(&iter)) {
PropertyRNA *prop = iter.ptr.data;
- if (!RNA_property_equals(a, b, prop, is_strict)) {
+ if (!RNA_property_equals(a, b, prop, mode)) {
equals = false;
break;
}
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 44ce081f68f..c5b7c88d8fc 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -191,7 +191,8 @@ static void rna_Action_active_pose_marker_index_set(PointerRNA *ptr, int value)
act->active_marker = value + 1;
}
-static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
bAction *act = (bAction *)ptr->data;
@@ -490,7 +491,7 @@ static void rna_def_action_group(BlenderRNA *brna)
prop = RNA_def_property(srna, "channels", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "channels", NULL);
RNA_def_property_struct_type(prop, "FCurve");
- RNA_def_property_collection_funcs(prop, 0, "rna_ActionGroup_channels_next", NULL, NULL, NULL, NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, NULL, "rna_ActionGroup_channels_next", NULL, NULL, NULL, NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Channels", "F-Curves in this group");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 134c5bcbee4..a07a000dacb 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -45,7 +45,7 @@
#include "WM_types.h"
/* Always keep in alphabetical order */
-EnumPropertyItem actuator_type_items[] = {
+static EnumPropertyItem actuator_type_items[] = {
{ACT_ACTION, "ACTION", 0, "Action", ""},
{ACT_ARMATURE, "ARMATURE", 0, "Armature", ""},
{ACT_CAMERA, "CAMERA", 0, "Camera", ""},
@@ -593,6 +593,12 @@ static void rna_def_action_actuator(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_blend_items[] = {
+ {ACT_ACTION_BLEND, "BLEND", 0, "Blend", ""},
+ {ACT_ACTION_ADD, "ADD", 0, "Add", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "ActionActuator", "Actuator");
RNA_def_struct_ui_text(srna, "Action Actuator", "Actuator to control the object movement");
RNA_def_struct_sdna_from(srna, "bActionActuator", "data");
@@ -656,7 +662,7 @@ static void rna_def_action_actuator(BlenderRNA *brna)
prop = RNA_def_property(srna, "layer_weight", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Layer Weight",
- "How much of the previous layer to blend into this one (0 = add mode)");
+ "How much of the previous layer to blend into this one");
RNA_def_property_update(prop, NC_LOGIC, NULL);
prop = RNA_def_property(srna, "frame_property", PROP_STRING, PROP_NONE);
@@ -691,6 +697,12 @@ static void rna_def_action_actuator(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Child", "Update Action on all children Objects as well");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+ prop = RNA_def_property(srna, "blend_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "blend_mode");
+ RNA_def_property_enum_items(prop, prop_blend_items);
+ RNA_def_property_ui_text(prop, "Blend Mode", "How this layer is blended with previous layers");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
prop = RNA_def_property(srna, "stride_length", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "stridelength");
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 7bdaca3c847..31fdd19f169 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -408,7 +408,8 @@ static void rna_KeyingSet_active_ksPath_index_set(PointerRNA *ptr, int value)
ks->active_path = value + 1;
}
-static void rna_KeyingSet_active_ksPath_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_KeyingSet_active_ksPath_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
KeyingSet *ks = (KeyingSet *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c
index 9f8f30b00a7..ee107fdfe9f 100644
--- a/source/blender/makesrna/intern/rna_animviz.c
+++ b/source/blender/makesrna/intern/rna_animviz.c
@@ -26,8 +26,6 @@
#include <stdlib.h>
-#include "RNA_define.h"
-
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
@@ -36,6 +34,9 @@
#include "MEM_guardedalloc.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
#include "rna_internal.h"
#include "WM_types.h"
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index a832a8cdf96..b9cbbdb32f7 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -921,7 +921,7 @@ static void rna_def_armature(BlenderRNA *brna)
/* Collections */
prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL);
- RNA_def_property_collection_funcs(prop, 0, "rna_Armature_bones_next", NULL, NULL, NULL, NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop, NULL, "rna_Armature_bones_next", NULL, NULL, NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "Bone");
RNA_def_property_ui_text(prop, "Bones", "");
rna_def_armature_bones(brna, prop);
diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c
index 9b2ce863108..6233649fb12 100644
--- a/source/blender/makesrna/intern/rna_boid.c
+++ b/source/blender/makesrna/intern/rna_boid.c
@@ -41,6 +41,7 @@
#include "BLI_utildefines.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -69,7 +70,8 @@ EnumPropertyItem boidrule_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem boidruleset_type_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem boidruleset_type_items[] = {
{eBoidRulesetType_Fuzzy, "FUZZY", 0, "Fuzzy",
"Rules are gone through top to bottom (only the first rule which effect is above "
"fuzziness threshold is evaluated)"},
@@ -77,6 +79,7 @@ EnumPropertyItem boidruleset_type_items[] = {
{eBoidRulesetType_Average, "AVERAGE", 0, "Average", "All rules are averaged"},
{0, NULL, 0, NULL, NULL}
};
+#endif
#ifdef RNA_RUNTIME
@@ -161,7 +164,8 @@ static PointerRNA rna_BoidState_active_boid_rule_get(PointerRNA *ptr)
}
return rna_pointer_inherit_refine(ptr, &RNA_BoidRule, NULL);
}
-static void rna_BoidState_active_boid_rule_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_BoidState_active_boid_rule_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
BoidState *state = (BoidState *)ptr->data;
*min = 0;
@@ -227,7 +231,7 @@ static PointerRNA rna_BoidSettings_active_boid_state_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_BoidState, NULL);
}
static void rna_BoidSettings_active_boid_state_index_range(PointerRNA *ptr, int *min, int *max,
- int *softmin, int *softmax)
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
BoidSettings *boids = (BoidSettings *)ptr->data;
*min = 0;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 5d68a6905a3..405d38e9683 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -27,8 +27,6 @@
#include <stdlib.h>
#include <assert.h>
-#include "RNA_define.h"
-
#include "DNA_brush_types.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
@@ -36,6 +34,9 @@
#include "BLI_math.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
#include "rna_internal.h"
#include "IMB_imbuf.h"
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index ebd06475c79..d848acd5971 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -110,7 +110,8 @@ static void rna_CurveMapping_white_level_set(PointerRNA *ptr, const float *value
curvemapping_set_black_white(cumap, NULL, NULL);
}
-static void rna_CurveMapping_clipminx_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_CurveMapping_clipminx_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
CurveMapping *cumap = (CurveMapping *)ptr->data;
@@ -118,7 +119,8 @@ static void rna_CurveMapping_clipminx_range(PointerRNA *ptr, float *min, float *
*max = cumap->clipr.xmax;
}
-static void rna_CurveMapping_clipminy_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_CurveMapping_clipminy_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
CurveMapping *cumap = (CurveMapping *)ptr->data;
@@ -126,7 +128,8 @@ static void rna_CurveMapping_clipminy_range(PointerRNA *ptr, float *min, float *
*max = cumap->clipr.ymax;
}
-static void rna_CurveMapping_clipmaxx_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_CurveMapping_clipmaxx_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
CurveMapping *cumap = (CurveMapping *)ptr->data;
@@ -134,7 +137,8 @@ static void rna_CurveMapping_clipmaxx_range(PointerRNA *ptr, float *min, float *
*max = 100.0f;
}
-static void rna_CurveMapping_clipmaxy_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_CurveMapping_clipmaxy_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
CurveMapping *cumap = (CurveMapping *)ptr->data;
@@ -407,8 +411,8 @@ static void rna_ColorManagedDisplaySettings_display_device_set(struct PointerRNA
}
}
-static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
EnumPropertyItem *items = NULL;
int totitem = 0;
@@ -455,8 +459,8 @@ static void rna_ColorManagedViewSettings_view_transform_set(PointerRNA *ptr, int
}
}
-static EnumPropertyItem *rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_ColorManagedViewSettings_view_transform_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
Scene *scene = CTX_data_scene(C);
EnumPropertyItem *items = NULL;
@@ -470,6 +474,37 @@ static EnumPropertyItem *rna_ColorManagedViewSettings_view_transform_itemf(bCont
return items;
}
+static int rna_ColorManagedViewSettings_look_get(PointerRNA *ptr)
+{
+ ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
+
+ return IMB_colormanagement_look_get_named_index(view->look);
+}
+
+static void rna_ColorManagedViewSettings_look_set(PointerRNA *ptr, int value)
+{
+ ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
+
+ const char *name = IMB_colormanagement_look_get_indexed_name(value);
+
+ if (name) {
+ BLI_strncpy(view->look, name, sizeof(view->look));
+ }
+}
+
+static EnumPropertyItem *rna_ColorManagedViewSettings_look_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ EnumPropertyItem *items = NULL;
+ int totitem = 0;
+
+ IMB_colormanagement_look_items_add(&items, &totitem);
+ RNA_enum_item_end(&items, &totitem);
+
+ *free = TRUE;
+ return items;
+}
+
static void rna_ColorManagedViewSettings_use_curves_set(PointerRNA *ptr, int value)
{
ColorManagedViewSettings *view_settings = (ColorManagedViewSettings *) ptr->data;
@@ -503,8 +538,8 @@ static void rna_ColorManagedColorspaceSettings_colorspace_set(struct PointerRNA
}
}
-static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(
+ bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
EnumPropertyItem *items = NULL;
int totitem = 0;
@@ -584,16 +619,25 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
return;
if (GS(id->name) == ID_SCE) {
+ DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
}
/* this function only exists because #curvemap_evaluateF uses a 'const' qualifier */
-static float rna_CurveMap_evaluateF(struct CurveMap *cuma, float value)
+static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, float value)
{
+ if (!cuma->table) {
+ BKE_reportf(reports, RPT_ERROR, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap");
+ return 0.0f;
+ }
return curvemap_evaluateF(cuma, value);
}
+static void rna_CurveMap_initialize(struct CurveMapping *cumap)
+{
+ curvemapping_initialize(cumap);
+}
#else
static void rna_def_curvemappoint(BlenderRNA *brna)
@@ -679,6 +723,7 @@ static void rna_def_curvemap(BlenderRNA *brna)
rna_def_curvemap_points_api(brna, prop);
func = RNA_def_function(srna, "evaluate", "rna_CurveMap_evaluateF");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Evaluate curve at given location");
parm = RNA_def_float(func, "position", 0.0f, -FLT_MAX, FLT_MAX, "Position", "Position to evaluate curve at", -FLT_MAX, FLT_MAX);
RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -747,6 +792,9 @@ static void rna_def_curvemapping(BlenderRNA *brna)
func = RNA_def_function(srna, "update", "curvemapping_changed_all");
RNA_def_function_ui_description(func, "Update curve mapping after making changes");
+
+ func = RNA_def_function(srna, "initialize", "rna_CurveMap_initialize");
+ RNA_def_function_ui_description(func, "Initialize curve");
}
static void rna_def_color_ramp_element(BlenderRNA *brna)
@@ -946,6 +994,11 @@ static void rna_def_colormanage(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem look_items[] = {
+ {0, "NONE", 0, "None", "Do not modify image in an artistic manner"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
static EnumPropertyItem view_transform_items[] = {
{0, "NONE", 0, "None", "Do not perform any color transform on display, use old non-color managed technique for display"},
{0, NULL, 0, NULL, NULL}
@@ -972,12 +1025,20 @@ static void rna_def_colormanage(BlenderRNA *brna)
srna = RNA_def_struct(brna, "ColorManagedViewSettings", NULL);
RNA_def_struct_ui_text(srna, "ColorManagedViewSettings", "Color management settings used for displaying images on the display");
+ prop = RNA_def_property(srna, "look", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, look_items);
+ RNA_def_property_enum_funcs(prop, "rna_ColorManagedViewSettings_look_get",
+ "rna_ColorManagedViewSettings_look_set",
+ "rna_ColorManagedViewSettings_look_itemf");
+ RNA_def_property_ui_text(prop, "Look", "Additional transform applied before view transform for an artistic needs");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
+
prop = RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, view_transform_items);
RNA_def_property_enum_funcs(prop, "rna_ColorManagedViewSettings_view_transform_get",
"rna_ColorManagedViewSettings_view_transform_set",
"rna_ColorManagedViewSettings_view_transform_itemf");
- RNA_def_property_ui_text(prop, "View Transform", "View used ");
+ RNA_def_property_ui_text(prop, "View Transform", "View used when converting image to a display space");
RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_FACTOR);
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 05d4c5a59d2..f8483d7b221 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -37,6 +37,7 @@
#include "DNA_scene_types.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -343,7 +344,8 @@ static EnumPropertyItem *rna_Constraint_target_space_itemf(bContext *UNUSED(C),
return space_object_items;
}
-static void rna_ActionConstraint_minmax_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_ActionConstraint_minmax_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
bConstraint *con = (bConstraint *)ptr->data;
bActionConstraint *acon = (bActionConstraint *)con->data;
@@ -464,7 +466,7 @@ static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, PointerRNA v
#else
-EnumPropertyItem constraint_distance_items[] = {
+static EnumPropertyItem constraint_distance_items[] = {
{LIMITDIST_INSIDE, "LIMITDIST_INSIDE", 0, "Inside",
"The object is constrained inside a virtual sphere around the target object, "
"with a radius defined by the limit distance"},
@@ -1083,7 +1085,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_range(prop, 0.0, 100.f);
+ RNA_def_property_range(prop, -1000.0, 1000.0f);
+ RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, -1);
RNA_def_property_ui_text(prop, "Offset", "Offset of floor from object origin");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
@@ -2024,20 +2027,23 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 100.f);
RNA_def_property_ui_text(prop, "Distance", "Distance to Target");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
-
- prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS);
- RNA_def_property_ui_text(prop, "Axis X", "Projection over X Axis");
- RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
-
- prop = RNA_def_property(srna, "use_y", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS);
- RNA_def_property_ui_text(prop, "Axis Y", "Projection over Y Axis");
+
+ prop = RNA_def_property(srna, "project_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "projAxis");
+ RNA_def_property_enum_items(prop, object_axis_items);
+ RNA_def_property_ui_text(prop, "Project Axis", "Axis constrain to");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
-
- prop = RNA_def_property(srna, "use_z", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS);
- RNA_def_property_ui_text(prop, "Axis Z", "Projection over Z Axis");
+
+ prop = RNA_def_property(srna, "project_axis_space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "projAxisSpace");
+ RNA_def_property_enum_items(prop, owner_space_pchan_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Constraint_owner_space_itemf");
+ RNA_def_property_ui_text(prop, "Axis Space", "Space for the projection axis");
+
+ prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "projLimit");
+ RNA_def_property_range(prop, 0.0, 100.f);
+ RNA_def_property_ui_text(prop, "Project Distance", "Limit the distance used for projection (zero disables)");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c
index 28a2ca7cb75..3b789b16f52 100644
--- a/source/blender/makesrna/intern/rna_controller.c
+++ b/source/blender/makesrna/intern/rna_controller.c
@@ -34,6 +34,7 @@
#include "BLF_translation.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 21bf2ec6719..bd4b8dd76b1 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -46,13 +46,15 @@
#include "BKE_curve.h"
#include "ED_curve.h"
-EnumPropertyItem beztriple_handle_type_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem beztriple_handle_type_items[] = {
{HD_FREE, "FREE", 0, "Free", ""},
{HD_VECT, "VECTOR", 0, "Vector", ""},
{HD_ALIGN, "ALIGNED", 0, "Aligned", ""},
{HD_AUTO, "AUTO", 0, "Auto", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
EnumPropertyItem keyframe_handle_type_items[] = {
{HD_FREE, "FREE", 0, "Free", ""},
@@ -70,7 +72,8 @@ EnumPropertyItem beztriple_interpolation_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem curve_type_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem curve_type_items[] = {
{CU_POLY, "POLY", 0, "Poly", ""},
{CU_BEZIER, "BEZIER", 0, "Bezier", ""},
{CU_BSPLINE, "BSPLINE", 0, "BSpline", ""},
@@ -78,6 +81,7 @@ EnumPropertyItem curve_type_items[] = {
{CU_NURBS, "NURBS", 0, "Ease", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
static const EnumPropertyItem curve3d_fill_mode_items[] = {
{0, "FULL", 0, "Full", ""},
@@ -239,14 +243,16 @@ static void rna_Curve_texspace_size_set(PointerRNA *ptr, const float *values)
copy_v3_v3(cu->size, values);
}
-static void rna_Curve_material_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Curve_material_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Curve *cu = (Curve *)ptr->id.data;
*min = 0;
*max = max_ii(0, cu->totcol - 1);
}
-static void rna_Curve_active_textbox_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Curve_active_textbox_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Curve *cu = (Curve *)ptr->id.data;
*min = 0;
@@ -568,6 +574,10 @@ static Nurb *rna_Curve_spline_new(Curve *cu, int type)
nu->resolu = nu->resolv = 12;
nu->flag = CU_SMOOTH;
+ if ((cu->flag & CU_3D) == 0) {
+ nu->flag |= CU_2D;
+ }
+
BLI_addtail(BKE_curve_nurbs_get(cu), nu);
return nu;
@@ -1484,7 +1494,7 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Material");
RNA_def_property_ui_text(prop, "Materials", "");
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
- RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
prop = RNA_def_property(srna, "bevel_factor_start", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "bevfac1");
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 723f158bb50..b153728050c 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -574,13 +574,13 @@ void RNA_define_free(BlenderRNA *UNUSED(brna))
DefRNA.error = 0;
}
-void RNA_define_verify_sdna(int verify)
+void RNA_define_verify_sdna(bool verify)
{
DefRNA.verify = verify;
}
#ifndef RNA_RUNTIME
-void RNA_define_animate_sdna(int animate)
+void RNA_define_animate_sdna(bool animate)
{
DefRNA.animate = animate;
}
@@ -1321,6 +1321,26 @@ void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double
{
StructRNA *srna = DefRNA.laststruct;
+#ifdef DEBUG
+ if (min > max) {
+ fprintf(stderr, "%s: \"%s.%s\", min > max.\n",
+ __func__, srna->identifier, prop->identifier);
+ DefRNA.error = 1;
+ }
+
+ if (step < 0 || step > 100) {
+ fprintf(stderr, "%s: \"%s.%s\", step outside range.\n",
+ __func__, srna->identifier, prop->identifier);
+ DefRNA.error = 1;
+ }
+
+ if (precision < -1 || precision > 10) {
+ fprintf(stderr, "%s: \"%s.%s\", step outside range.\n",
+ __func__, srna->identifier, prop->identifier);
+ DefRNA.error = 1;
+ }
+#endif
+
switch (prop->type) {
case PROP_INT:
{
@@ -1366,6 +1386,14 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max)
{
StructRNA *srna = DefRNA.laststruct;
+#ifdef DEBUG
+ if (min > max) {
+ fprintf(stderr, "%s: \"%s.%s\", min > max.\n",
+ __func__, srna->identifier, prop->identifier);
+ DefRNA.error = 1;
+ }
+#endif
+
switch (prop->type) {
case PROP_INT:
{
@@ -2096,7 +2124,7 @@ void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *func)
prop->update = (UpdateFunc)func;
}
-void RNA_def_property_update_runtime(PropertyRNA *prop, void *func)
+void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func)
{
prop->update = func;
}
@@ -3207,9 +3235,8 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA
* in the first place */
if (prop->identifier) {
if (cont->prophash) {
- BLI_ghash_remove(cont->prophash, (void *)prop->identifier, NULL, NULL);
prop->identifier = BLI_strdup(prop->identifier);
- BLI_ghash_insert(cont->prophash, (void *)prop->identifier, prop);
+ BLI_ghash_reinsert(cont->prophash, (void *)prop->identifier, prop, NULL, NULL);
}
else {
prop->identifier = BLI_strdup(prop->identifier);
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index c716c3263d1..e13ec1f09a4 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -39,6 +39,7 @@
#include "DNA_scene_types.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -95,12 +96,12 @@ static char *rna_DynamicPaintSurface_path(PointerRNA *ptr)
* Surfaces
*/
-static void rna_DynamicPaint_redoModifier(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_DynamicPaint_redoModifier(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
-static void rna_DynamicPaintSurfaces_updateFrames(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_DynamicPaintSurfaces_updateFrames(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
dynamicPaint_cacheUpdateFrames((DynamicPaintSurface *)ptr->data);
}
@@ -134,7 +135,7 @@ static void rna_DynamicPaintSurface_changePreview(Main *bmain, Scene *scene, Poi
rna_DynamicPaint_redoModifier(bmain, scene, ptr);
}
-static void rna_DynamicPaintSurface_uniqueName(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_DynamicPaintSurface_uniqueName(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
dynamicPaintSurface_setUniqueName((DynamicPaintSurface *)ptr->data, ((DynamicPaintSurface *)ptr->data)->name);
}
@@ -196,7 +197,8 @@ static void rna_Surface_active_point_index_set(struct PointerRNA *ptr, int value
return;
}
-static void rna_Surface_active_point_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Surface_active_point_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
DynamicPaintCanvasSettings *canvas = (DynamicPaintCanvasSettings *)ptr->data;
@@ -243,8 +245,8 @@ static int rna_DynamicPaint_is_output_exists(DynamicPaintSurface *surface, Objec
}
-static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
{
DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 2ad8ded4656..4b50127d999 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -459,7 +459,8 @@ static void rna_FModifier_active_set(PointerRNA *ptr, int UNUSED(value))
fm->flag |= FMODIFIER_FLAG_ACTIVE;
}
-static void rna_FModifier_start_frame_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_FModifier_start_frame_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
@@ -467,7 +468,8 @@ static void rna_FModifier_start_frame_range(PointerRNA *ptr, float *min, float *
*max = (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) ? fcm->efra : MAXFRAMEF;
}
-static void rna_FModifier_end_frame_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_FModifier_end_frame_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
@@ -475,7 +477,8 @@ static void rna_FModifier_end_frame_range(PointerRNA *ptr, float *min, float *ma
*max = MAXFRAMEF;
}
-static void rna_FModifier_blending_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_FModifier_blending_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
@@ -524,7 +527,8 @@ static void rna_FModifierGenerator_coefficients_set(PointerRNA *ptr, const float
memcpy(gen->coefficients, values, gen->arraysize * sizeof(float));
}
-static void rna_FModifierLimits_minx_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_FModifierLimits_minx_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
FMod_Limits *data = fcm->data;
@@ -533,7 +537,8 @@ static void rna_FModifierLimits_minx_range(PointerRNA *ptr, float *min, float *m
*max = (data->flag & FCM_LIMIT_XMAX) ? data->rect.xmax : MAXFRAMEF;
}
-static void rna_FModifierLimits_maxx_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_FModifierLimits_maxx_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
FMod_Limits *data = fcm->data;
@@ -542,7 +547,8 @@ static void rna_FModifierLimits_maxx_range(PointerRNA *ptr, float *min, float *m
*max = MAXFRAMEF;
}
-static void rna_FModifierLimits_miny_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_FModifierLimits_miny_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
FMod_Limits *data = fcm->data;
@@ -551,7 +557,8 @@ static void rna_FModifierLimits_miny_range(PointerRNA *ptr, float *min, float *m
*max = (data->flag & FCM_LIMIT_YMAX) ? data->rect.ymax : FLT_MAX;
}
-static void rna_FModifierLimits_maxy_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_FModifierLimits_maxy_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
FMod_Limits *data = fcm->data;
@@ -562,7 +569,7 @@ static void rna_FModifierLimits_maxy_range(PointerRNA *ptr, float *min, float *m
static void rna_FModifierStepped_start_frame_range(PointerRNA *ptr, float *min, float *max,
- float *softmin, float *softmax)
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
FMod_Stepped *data = fcm->data;
@@ -572,7 +579,7 @@ static void rna_FModifierStepped_start_frame_range(PointerRNA *ptr, float *min,
}
static void rna_FModifierStepped_end_frame_range(PointerRNA *ptr, float *min, float *max,
- float *softmin, float *softmax)
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
FModifier *fcm = (FModifier *)ptr->data;
FMod_Stepped *data = fcm->data;
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 439bc51896f..6423763c49c 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -354,15 +354,15 @@ static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_srna(cprop, "GPencilStrokes");
srna = RNA_def_struct(brna, "GPencilStrokes", NULL);
RNA_def_struct_sdna(srna, "bGPDframe");
- RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil frames");
+ RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil stroke");
func = RNA_def_function(srna, "new", "rna_GPencil_stroke_new");
- RNA_def_function_ui_description(func, "Add a new grease pencil frame");
+ RNA_def_function_ui_description(func, "Add a new grease pencil stroke");
parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "", "The newly created stroke");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_GPencil_stroke_remove");
- RNA_def_function_ui_description(func, "Remove a grease pencil frame");
+ RNA_def_function_ui_description(func, "Remove a grease pencil stroke");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "Stroke", "The stroke to remove");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
@@ -390,7 +390,8 @@ static void rna_def_gpencil_frame(BlenderRNA *brna)
/* Frame Number */
prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "framenum");
- RNA_def_property_range(prop, MINFRAME, MAXFRAME); /* XXX note: this cannot occur on the same frame as another sketch */
+ /* XXX note: this cannot occur on the same frame as another sketch */
+ RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears");
/* Flags */
@@ -421,7 +422,8 @@ static void rna_def_gpencil_frames_api(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new", "rna_GPencil_frame_new");
RNA_def_function_ui_description(func, "Add a new grease pencil frame");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_int(func, "frame_number", 1, MINFRAME, MAXFRAME, "Frame Number", "The frame on which this sketch appears", MINFRAME, MAXFRAME);
+ parm = RNA_def_int(func, "frame_number", 1, MINAFRAME, MAXFRAME, "Frame Number",
+ "The frame on which this sketch appears", MINAFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "frame", "GPencilFrame", "", "The newly created frame");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index c1769f02974..f0322bac756 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -87,7 +87,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports
else {
ImBuf *write_ibuf;
- write_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings,
+ write_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings,
&scene->display_settings, &scene->r.im_format);
write_ibuf->planes = scene->r.im_format.planes;
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 72985f7b6e6..7950ed424ee 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -124,8 +124,9 @@ typedef struct BlenderDefRNA {
extern BlenderDefRNA DefRNA;
/* Define functions for all types */
-
+#ifndef __RNA_ACCESS_H__
extern BlenderRNA BLENDER_RNA;
+#endif
void RNA_def_ID(struct BlenderRNA *brna);
void RNA_def_action(struct BlenderRNA *brna);
@@ -278,6 +279,7 @@ void RNA_api_scene_render(struct StructRNA *srna);
void RNA_api_sequence_strip(StructRNA *srna);
void RNA_api_text(struct StructRNA *srna);
void RNA_api_ui_layout(struct StructRNA *srna);
+void RNA_api_window(struct StructRNA *srna);
void RNA_api_wm(struct StructRNA *srna);
void RNA_api_sensor(struct StructRNA *srna);
void RNA_api_controller(struct StructRNA *srna);
@@ -331,8 +333,10 @@ extern CollectionPropertyRNA rna_PropertyGroupItem_idp_array;
extern FloatPropertyRNA rna_PropertyGroupItem_double;
extern FloatPropertyRNA rna_PropertyGroupItem_double_array;
+#ifndef __RNA_ACCESS_H__
extern StructRNA RNA_PropertyGroupItem;
extern StructRNA RNA_PropertyGroup;
+#endif
struct IDProperty *rna_idproperty_check(struct PropertyRNA **prop, struct PointerRNA *ptr);
@@ -420,4 +424,10 @@ int rna_IDMaterials_assign_int(struct PointerRNA *ptr, int key, const struct Poi
void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
+#ifdef RNA_RUNTIME
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+# endif
+#endif
+
#endif /* __RNA_INTERNAL_H__ */
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 49d760adb32..a20cb73b3aa 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -39,6 +39,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -98,7 +99,8 @@ static void rna_ShapeKey_value_set(PointerRNA *ptr, float value)
data->curval = value;
}
-static void rna_ShapeKey_value_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_ShapeKey_value_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
KeyBlock *data = (KeyBlock *)ptr->data;
@@ -109,7 +111,8 @@ static void rna_ShapeKey_value_range(PointerRNA *ptr, float *min, float *max, fl
/* epsilon for how close one end of shapekey range can get to the other */
#define SHAPEKEY_SLIDER_TOL 0.001f
-static void rna_ShapeKey_slider_min_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_ShapeKey_slider_min_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
KeyBlock *data = (KeyBlock *)ptr->data;
@@ -127,7 +130,8 @@ static void rna_ShapeKey_slider_min_set(PointerRNA *ptr, float value)
data->slidermin = value;
}
-static void rna_ShapeKey_slider_max_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_ShapeKey_slider_max_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
KeyBlock *data = (KeyBlock *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index ffc9ac0e52e..63fc5dbdbbd 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
+#include "BLI_sys_types.h"
#include "BLI_math_base.h"
#include "BLI_math_rotation.h"
@@ -131,7 +132,7 @@ static StructRNA *rna_Lamp_refine(struct PointerRNA *ptr)
}
}
-static void rna_Lamp_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_Lamp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Lamp *la = ptr->id.data;
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 660ef57dbfe..03319a9ccf8 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -254,7 +254,7 @@ static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char *
#include "BLI_math.h"
static void rna_def_modifier_type_common(StructRNA *srna, EnumPropertyItem *modifier_type_items,
- char *set_name_func, int blend, int color)
+ const char *set_name_func, const bool blend, const bool color)
{
PropertyRNA *prop;
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index fd931262904..dffe392e6f1 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -361,8 +361,13 @@ Mesh *rna_Main_meshes_new_from_object(
BKE_mesh_from_metaball(&disp, tmpmesh);
BKE_displist_free(&disp);
}
- else
- BKE_mesh_from_metaball(&ob->disp, tmpmesh);
+ else {
+ ListBase disp = {NULL, NULL};
+ if (ob->curve_cache) {
+ disp = ob->curve_cache->disp;
+ }
+ BKE_mesh_from_metaball(&disp, tmpmesh);
+ }
BKE_mesh_texspace_copy_from_object(tmpmesh, ob);
@@ -827,7 +832,7 @@ static Mask *rna_Main_mask_new(Main *bmain, const char *name)
{
Mask *mask;
- mask = BKE_mask_new(bmain, "Mask");
+ mask = BKE_mask_new(bmain, name);
return mask;
}
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index 65e6b15d676..77d593b67b6 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -84,21 +84,33 @@ static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr)
MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, parent->parent);
if (object) {
- MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, object, parent->sub_parent);
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
- if (track) {
- int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_framenr);
- float marker_pos_ofs[2], parmask_pos[2];
- MovieClipUser user = {0};
+ if (parent->type == MASK_PARENT_POINT_TRACK) {
+ MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, object, parent->sub_parent);
- BKE_movieclip_user_set_frame(&user, scene->r.cfra);
+ if (track) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_framenr);
+ float marker_pos_ofs[2], parmask_pos[2];
+ MovieClipUser user = {0};
- add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
+ BKE_movieclip_user_set_frame(&user, scene->r.cfra);
- BKE_mask_coord_from_movieclip(clip, &user, parmask_pos, marker_pos_ofs);
+ add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
- copy_v2_v2(parent->parent_orig, parmask_pos);
+ BKE_mask_coord_from_movieclip(clip, &user, parmask_pos, marker_pos_ofs);
+
+ copy_v2_v2(parent->parent_orig, parmask_pos);
+ }
+ }
+ else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+ MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, object, parent->sub_parent);
+ if (plane_track) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+
+ memcpy(parent->parent_corners_orig, plane_marker->corners, sizeof(parent->parent_corners_orig));
+ zero_v2(parent->parent_orig);
+ }
}
}
}
@@ -504,7 +516,7 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
}
#else
- void rna_def_maskParent(BlenderRNA *brna)
+static void rna_def_maskParent(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@@ -513,6 +525,11 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
{ID_MC, "MOVIECLIP", ICON_SEQUENCE, "Movie Clip", ""},
{0, NULL, 0, NULL, NULL}};
+ static EnumPropertyItem parent_type_items[] = {
+ {MASK_PARENT_POINT_TRACK, "POINT_TRACK", 0, "Point Track", ""},
+ {MASK_PARENT_PLANE_TRACK, "PLANE_TRACK", 0, "Plane Track", ""},
+ {0, NULL, 0, NULL, NULL}};
+
srna = RNA_def_struct(brna, "MaskParent", NULL);
RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for masking element");
@@ -535,6 +552,12 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used");
RNA_def_property_update(prop, 0, "rna_Mask_update_parent");
+ /* type */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, parent_type_items);
+ RNA_def_property_ui_text(prop, "Parent Type", "Parent Type");
+ RNA_def_property_update(prop, 0, "rna_Mask_update_parent");
+
/* parent */
prop = RNA_def_property(srna, "parent", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Parent", "Name of parent object in specified data block to which parenting happens");
@@ -804,7 +827,7 @@ static void rna_def_mask_layer(BlenderRNA *brna)
/* splines */
prop = RNA_def_property(srna, "splines", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_funcs(prop, "rna_MaskLayer_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0);
+ RNA_def_property_collection_funcs(prop, "rna_MaskLayer_splines_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MaskSpline");
RNA_def_property_ui_text(prop, "Splines", "Collection of splines which defines this layer");
RNA_def_property_srna(prop, "MaskSplines");
@@ -914,7 +937,7 @@ static void rna_def_mask(BlenderRNA *brna)
/* mask layers */
prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_funcs(prop, "rna_Mask_layers_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0);
+ RNA_def_property_collection_funcs(prop, "rna_Mask_layers_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "MaskLayer");
RNA_def_property_ui_text(prop, "Layers", "Collection of layers which defines this mask");
rna_def_masklayers(brna, prop);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index b30bdaf9009..e9f506b6f0b 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -31,6 +31,7 @@
#include "DNA_texture_types.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -92,7 +93,7 @@ EnumPropertyItem ramp_blend_items[] = {
#include "ED_node.h"
-static void rna_Material_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Material *ma = ptr->id.data;
@@ -100,7 +101,7 @@ static void rna_Material_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *p
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
}
-static void rna_Material_update_previews(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Material_update_previews(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Material *ma = ptr->id.data;
@@ -110,7 +111,7 @@ static void rna_Material_update_previews(Main *bmain, Scene *scene, PointerRNA *
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_PREVIEW, ma);
}
-static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Material *ma = ptr->id.data;
@@ -201,7 +202,8 @@ static void rna_Material_active_node_material_set(PointerRNA *ptr, PointerRNA va
nodeSetActiveID(ma->nodetree, ID_MA, &ma_act->id);
}
-static void rna_MaterialStrand_start_size_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_MaterialStrand_start_size_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
Material *ma = (Material *)ptr->id.data;
@@ -215,7 +217,8 @@ static void rna_MaterialStrand_start_size_range(PointerRNA *ptr, float *min, flo
}
}
-static void rna_MaterialStrand_end_size_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_MaterialStrand_end_size_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
Material *ma = (Material *)ptr->id.data;
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 35d8a0fb433..fe6f33abc8c 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -184,18 +184,22 @@ static void rna_MeshEdgeLayer_name_set(PointerRNA *ptr, const char *value)
rna_cd_layer_name_set(rna_mesh_edata(ptr), (CustomDataLayer *)ptr->data, value);
}
#endif
+#if 0
static void rna_MeshPolyLayer_name_set(PointerRNA *ptr, const char *value)
{
rna_cd_layer_name_set(rna_mesh_pdata(ptr), (CustomDataLayer *)ptr->data, value);
}
+#endif
static void rna_MeshLoopLayer_name_set(PointerRNA *ptr, const char *value)
{
rna_cd_layer_name_set(rna_mesh_ldata(ptr), (CustomDataLayer *)ptr->data, value);
}
+#if 0
static void rna_MeshTessfaceLayer_name_set(PointerRNA *ptr, const char *value)
{
rna_cd_layer_name_set(rna_mesh_fdata(ptr), (CustomDataLayer *)ptr->data, value);
}
+#endif
/* only for layers shared between types */
static void rna_MeshAnyLayer_name_set(PointerRNA *ptr, const char *value)
{
@@ -207,7 +211,7 @@ static void rna_MeshAnyLayer_name_set(PointerRNA *ptr, const char *value)
/* -------------------------------------------------------------------- */
/* Update Callbacks */
-static void rna_Mesh_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Mesh_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -227,7 +231,7 @@ static void rna_Mesh_update_data_edit_color(Main *bmain, Scene *scene, PointerRN
}
}
-static void rna_Mesh_update_select(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
/* cheating way for importers to avoid slow updates */
@@ -236,7 +240,7 @@ static void rna_Mesh_update_select(Main *bmain, Scene *scene, PointerRNA *ptr)
}
}
-void rna_Mesh_update_draw(Main *bmain, Scene *scene, PointerRNA *ptr)
+void rna_Mesh_update_draw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
/* cheating way for importers to avoid slow updates */
@@ -320,6 +324,20 @@ static void rna_MEdge_crease_set(PointerRNA *ptr, float value)
medge->crease = (char)(CLAMPIS(value * 255.0f, 0, 255));
}
+static void rna_MeshLoop_normal_get(PointerRNA *ptr, float *values)
+{
+ Mesh *me = rna_mesh(ptr);
+ MLoop *ml = (MLoop *)ptr->data;
+ const float (*vec)[3] = CustomData_get(&me->ldata, (int)(ml - me->mloop), CD_NORMAL);
+
+ if (!vec) {
+ zero_v3(values);
+ }
+ else {
+ copy_v3_v3(values, (const float *)vec);
+ }
+}
+
static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values)
{
Mesh *me = rna_mesh(ptr);
@@ -575,8 +593,9 @@ static void rna_Mesh_texspace_size_get(PointerRNA *ptr, float values[3])
{
Mesh *me = (Mesh *)ptr->data;
- if (!me->bb)
+ if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
BKE_mesh_texspace_calc(me);
+ }
copy_v3_v3(values, me->size);
}
@@ -585,8 +604,9 @@ static void rna_Mesh_texspace_loc_get(PointerRNA *ptr, float values[3])
{
Mesh *me = (Mesh *)ptr->data;
- if (!me->bb)
+ if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
BKE_mesh_texspace_calc(me);
+ }
copy_v3_v3(values, me->loc);
}
@@ -630,7 +650,7 @@ static int rna_CustomDataLayer_active_get(PointerRNA *ptr, CustomData *data, int
else return (n == CustomData_get_active_layer_index(data, type));
}
-static int rna_CustomDataLayer_clone_get(PointerRNA *ptr, CustomData *data, int type, int render)
+static int rna_CustomDataLayer_clone_get(PointerRNA *ptr, CustomData *data, int type)
{
int n = ((CustomDataLayer *)ptr->data) - data->layers;
@@ -658,7 +678,7 @@ static void rna_CustomDataLayer_active_set(PointerRNA *ptr, CustomData *data, in
BKE_mesh_update_customdata_pointers(me, true);
}
-static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, CustomData *data, int value, int type, int render)
+static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, CustomData *data, int value, int type)
{
int n = ((CustomDataLayer *)ptr->data) - data->layers;
@@ -668,6 +688,14 @@ static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, CustomData *data, int
CustomData_set_layer_clone_index(data, type, n);
}
+/* Generic UV rename! */
+static void rna_MeshUVLayer_name_set(PointerRNA *ptr, const char *name)
+{
+ char buf[MAX_CUSTOMDATA_LAYER_NAME];
+ BLI_strncpy_utf8(buf, name, MAX_CUSTOMDATA_LAYER_NAME);
+ BKE_mesh_uv_cdlayer_rename(rna_mesh(ptr), ((CustomDataLayer *)ptr->data)->name, buf, true);
+}
+
/* uv_layers */
DEFINE_CUSTOMDATA_LAYER_COLLECTION(uv_layer, ldata, CD_MLOOPUV)
@@ -732,7 +760,7 @@ static int rna_MeshTextureFaceLayer_active_get(PointerRNA *ptr)
static int rna_MeshTextureFaceLayer_clone_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_clone_get(ptr, rna_mesh_fdata(ptr), CD_MTFACE, 0);
+ return rna_CustomDataLayer_clone_get(ptr, rna_mesh_fdata(ptr), CD_MTFACE);
}
static void rna_MeshTextureFaceLayer_active_render_set(PointerRNA *ptr, int value)
@@ -747,7 +775,7 @@ static void rna_MeshTextureFaceLayer_active_set(PointerRNA *ptr, int value)
static void rna_MeshTextureFaceLayer_clone_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_clone_set(ptr, rna_mesh_fdata(ptr), value, CD_MTFACE, 0);
+ rna_CustomDataLayer_clone_set(ptr, rna_mesh_fdata(ptr), value, CD_MTFACE);
}
/* poly uv_textures */
@@ -783,7 +811,7 @@ static int rna_MeshTexturePolyLayer_active_get(PointerRNA *ptr)
static int rna_MeshTexturePolyLayer_clone_get(PointerRNA *ptr)
{
- return rna_CustomDataLayer_clone_get(ptr, rna_mesh_pdata(ptr), CD_MTEXPOLY, 0);
+ return rna_CustomDataLayer_clone_get(ptr, rna_mesh_pdata(ptr), CD_MTEXPOLY);
}
static void rna_MeshTexturePolyLayer_active_render_set(PointerRNA *ptr, int value)
@@ -798,7 +826,7 @@ static void rna_MeshTexturePolyLayer_active_set(PointerRNA *ptr, int value)
static void rna_MeshTexturePolyLayer_clone_set(PointerRNA *ptr, int value)
{
- rna_CustomDataLayer_clone_set(ptr, rna_mesh_pdata(ptr), value, CD_MTEXPOLY, 0);
+ rna_CustomDataLayer_clone_set(ptr, rna_mesh_pdata(ptr), value, CD_MTEXPOLY);
}
/* vertex_color_layers */
@@ -890,7 +918,7 @@ static int rna_MeshFloatPropertyLayer_data_length(PointerRNA *ptr)
return me->totpoly;
}
-static int rna_float_layer_check(CollectionPropertyIterator *iter, void *data)
+static int rna_float_layer_check(CollectionPropertyIterator *UNUSED(iter), void *data)
{
CustomDataLayer *layer = (CustomDataLayer *)data;
return (layer->type != CD_PROP_FLT);
@@ -908,7 +936,7 @@ static int rna_Mesh_polygon_float_layers_length(PointerRNA *ptr)
return CustomData_number_of_layers(rna_mesh_pdata(ptr), CD_PROP_FLT);
}
-static int rna_int_layer_check(CollectionPropertyIterator *iter, void *data)
+static int rna_int_layer_check(CollectionPropertyIterator *UNUSED(iter), void *data)
{
CustomDataLayer *layer = (CustomDataLayer *)data;
return (layer->type != CD_PROP_INT);
@@ -939,7 +967,7 @@ static int rna_Mesh_polygon_int_layers_length(PointerRNA *ptr)
return CustomData_number_of_layers(rna_mesh_pdata(ptr), CD_PROP_INT);
}
-static int rna_string_layer_check(CollectionPropertyIterator *iter, void *data)
+static int rna_string_layer_check(CollectionPropertyIterator *UNUSED(iter), void *data)
{
CustomDataLayer *layer = (CustomDataLayer *)data;
return (layer->type != CD_PROP_STR);
@@ -981,7 +1009,7 @@ static char *rna_MeshSkinVertexLayer_path(PointerRNA *ptr)
return BLI_sprintfN("skin_vertices[\"%s\"]", name_esc);
}
-static char *rna_VertCustomData_data_path(PointerRNA *ptr, char *collection, int type);
+static char *rna_VertCustomData_data_path(PointerRNA *ptr, const char *collection, int type);
static char *rna_MeshSkinVertex_path(PointerRNA *ptr)
{
return rna_VertCustomData_data_path(ptr, "skin_vertices", CD_MVERT_SKIN);
@@ -1106,12 +1134,15 @@ static void rna_MeshPoly_vertices_set(PointerRNA *ptr, const int *values)
}
}
+/* disabling, some importers don't know the total material count when assigning materials */
+#if 0
static void rna_MeshPoly_material_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
Mesh *me = rna_mesh(ptr);
*min = 0;
*max = max_ii(0, me->totcol - 1);
}
+#endif
static int rna_MeshVertex_index_get(PointerRNA *ptr)
{
@@ -1207,7 +1238,7 @@ static char *rna_MeshTexturePolyLayer_path(PointerRNA *ptr)
return BLI_sprintfN("uv_textures[\"%s\"]", name_esc);
}
-static char *rna_VertCustomData_data_path(PointerRNA *ptr, char *collection, int type)
+static char *rna_VertCustomData_data_path(PointerRNA *ptr, const char *collection, int type)
{
CustomDataLayer *cdl;
Mesh *me = rna_mesh(ptr);
@@ -1228,7 +1259,7 @@ static char *rna_VertCustomData_data_path(PointerRNA *ptr, char *collection, int
return NULL;
}
-static char *rna_PolyCustomData_data_path(PointerRNA *ptr, char *collection, int type)
+static char *rna_PolyCustomData_data_path(PointerRNA *ptr, const char *collection, int type)
{
CustomDataLayer *cdl;
Mesh *me = rna_mesh(ptr);
@@ -1249,7 +1280,7 @@ static char *rna_PolyCustomData_data_path(PointerRNA *ptr, char *collection, int
return NULL;
}
-static char *rna_LoopCustomData_data_path(PointerRNA *ptr, char *collection, int type)
+static char *rna_LoopCustomData_data_path(PointerRNA *ptr, const char *collection, int type)
{
CustomDataLayer *cdl;
Mesh *me = rna_mesh(ptr);
@@ -1270,7 +1301,7 @@ static char *rna_LoopCustomData_data_path(PointerRNA *ptr, char *collection, int
return NULL;
}
-static char *rna_FaceCustomData_data_path(PointerRNA *ptr, char *collection, int type)
+static char *rna_FaceCustomData_data_path(PointerRNA *ptr, const char *collection, int type)
{
CustomDataLayer *cdl;
Mesh *me = rna_mesh(ptr);
@@ -1456,7 +1487,7 @@ static PointerRNA rna_Mesh_tessface_vertex_color_new(struct Mesh *me, ReportList
return ptr;
}
-static PointerRNA rna_Mesh_polygon_int_property_new(struct Mesh *me, struct bContext *C, const char *name)
+static PointerRNA rna_Mesh_polygon_int_property_new(struct Mesh *me, const char *name)
{
PointerRNA ptr;
CustomDataLayer *cdl = NULL;
@@ -1471,7 +1502,7 @@ static PointerRNA rna_Mesh_polygon_int_property_new(struct Mesh *me, struct bCon
return ptr;
}
-static PointerRNA rna_Mesh_polygon_float_property_new(struct Mesh *me, struct bContext *C, const char *name)
+static PointerRNA rna_Mesh_polygon_float_property_new(struct Mesh *me, const char *name)
{
PointerRNA ptr;
CustomDataLayer *cdl = NULL;
@@ -1486,7 +1517,7 @@ static PointerRNA rna_Mesh_polygon_float_property_new(struct Mesh *me, struct bC
return ptr;
}
-static PointerRNA rna_Mesh_polygon_string_property_new(struct Mesh *me, struct bContext *C, const char *name)
+static PointerRNA rna_Mesh_polygon_string_property_new(struct Mesh *me, const char *name)
{
PointerRNA ptr;
CustomDataLayer *cdl = NULL;
@@ -1675,7 +1706,7 @@ static void rna_def_mvert(BlenderRNA *brna)
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_MeshVertex_index_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Index", "Index number of the vertex");
+ RNA_def_property_ui_text(prop, "Index", "Index of this vertex");
prop = RNA_def_property(srna, "undeformed_co", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_array(prop, 3);
@@ -1740,7 +1771,7 @@ static void rna_def_medge(BlenderRNA *brna)
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_MeshEdge_index_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Index", "Index number of the vertex");
+ RNA_def_property_ui_text(prop, "Index", "Index of this edge");
}
static void rna_def_mface(BlenderRNA *brna)
@@ -1771,7 +1802,9 @@ static void rna_def_mface(BlenderRNA *brna)
prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "mat_nr");
RNA_def_property_ui_text(prop, "Material Index", "");
+#if 0
RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range"); /* reuse for tessface is ok */
+#endif
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
@@ -1794,17 +1827,17 @@ static void rna_def_mface(BlenderRNA *brna)
RNA_def_property_range(prop, -1.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_MeshTessFace_normal_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Face normal", "Local space unit length normal vector for this face");
+ RNA_def_property_ui_text(prop, "Face Normal", "Local space unit length normal vector for this face");
prop = RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_MeshTessFace_area_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Face area", "Read only area of the face");
+ RNA_def_property_ui_text(prop, "Face Area", "Read only area of this face");
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_MeshTessFace_index_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Index", "Index number of the vertex");
+ RNA_def_property_ui_text(prop, "Index", "Index of this face");
}
@@ -1830,7 +1863,17 @@ static void rna_def_mloop(BlenderRNA *brna)
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_MeshLoop_index_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Index", "Index number of the loop");
+ RNA_def_property_ui_text(prop, "Index", "Index of this loop");
+
+ prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_range(prop, -1.0f, 1.0f);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_float_funcs(prop, "rna_MeshLoop_normal_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Loop Normal",
+ "Local space unit length split normal vector of this vertex for this polygon "
+ "(only computed on demand!)");
+
}
static void rna_def_mpolygon(BlenderRNA *brna)
@@ -1859,16 +1902,18 @@ static void rna_def_mpolygon(BlenderRNA *brna)
/* these are both very low level access */
prop = RNA_def_property(srna, "loop_start", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "loopstart");
- RNA_def_property_ui_text(prop, "Loop Start", "");
+ RNA_def_property_ui_text(prop, "Loop Start", "Index of the first loop of this polygon");
/* also low level */
prop = RNA_def_property(srna, "loop_total", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "totloop");
- RNA_def_property_ui_text(prop, "Loop Total", "");
+ RNA_def_property_ui_text(prop, "Loop Total", "Number of loops used by this polygon");
prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "mat_nr");
RNA_def_property_ui_text(prop, "Material Index", "");
+#if 0
RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range");
+#endif
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
@@ -1891,23 +1936,23 @@ static void rna_def_mpolygon(BlenderRNA *brna)
RNA_def_property_range(prop, -1.0f, 1.0f);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_MeshPolygon_normal_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Face normal", "Local space unit length normal vector for this polygon");
+ RNA_def_property_ui_text(prop, "Polygon Normal", "Local space unit length normal vector for this polygon");
prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE);
RNA_def_property_array(prop, 3);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_MeshPolygon_center_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Face center", "Center of the polygon");
+ RNA_def_property_ui_text(prop, "Polygon Center", "Center of this polygon");
prop = RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_MeshPolygon_area_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Face area", "Read only area of the face");
+ RNA_def_property_ui_text(prop, "Polygon Area", "Read only area of this polygon");
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_MeshPolygon_index_get", NULL, NULL);
- RNA_def_property_ui_text(prop, "Index", "Index number of the vertex");
+ RNA_def_property_ui_text(prop, "Index", "Index of this polygon");
}
/* mesh.loop_uvs */
@@ -1928,7 +1973,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshLoopLayer_name_set");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
RNA_def_property_ui_text(prop, "Name", "Name of UV map");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -1966,7 +2011,7 @@ static void rna_def_mtface(BlenderRNA *brna)
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshTessfaceLayer_name_set");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
RNA_def_property_ui_text(prop, "Name", "Name of UV map");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -2058,7 +2103,7 @@ static void rna_def_mtface(BlenderRNA *brna)
prop = RNA_def_property(srna, "uv_raw", PROP_FLOAT, PROP_NONE);
RNA_def_property_multi_array(prop, 2, uv_dim);
RNA_def_property_float_sdna(prop, NULL, "uv");
- RNA_def_property_ui_text(prop, "UV", "Fixed size UV coordinates array");
+ RNA_def_property_ui_text(prop, "UV Raw", "Fixed size UV coordinates array");
}
@@ -2078,7 +2123,7 @@ static void rna_def_mtexpoly(BlenderRNA *brna)
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshPolyLayer_name_set");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
RNA_def_property_ui_text(prop, "Name", "Name of UV map");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -2397,7 +2442,7 @@ void rna_def_texmat_common(StructRNA *srna, const char *texspace_editable)
RNA_def_property_struct_type(prop, "Material");
RNA_def_property_ui_text(prop, "Materials", "");
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
- RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
}
@@ -2644,7 +2689,6 @@ static void rna_def_polygon_int_layers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "Int Properties", "Collection of int properties");
func = RNA_def_function(srna, "new", "rna_Mesh_polygon_int_property_new");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Add a integer property layer to Mesh");
RNA_def_string(func, "name", "Int Prop", 0, "", "Int property name");
parm = RNA_def_pointer(func, "layer", "MeshIntPropertyLayer", "", "The newly created layer");
@@ -2666,7 +2710,6 @@ static void rna_def_polygon_float_layers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "Float Properties", "Collection of float properties");
func = RNA_def_function(srna, "new", "rna_Mesh_polygon_float_property_new");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Add a float property layer to Mesh");
RNA_def_string(func, "name", "Float Prop", 0, "", "Float property name");
parm = RNA_def_pointer(func, "layer", "MeshFloatPropertyLayer", "", "The newly created layer");
@@ -2688,7 +2731,6 @@ static void rna_def_polygon_string_layers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "String Properties", "Collection of string properties");
func = RNA_def_function(srna, "new", "rna_Mesh_polygon_string_property_new");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Add a string property layer to Mesh");
RNA_def_string(func, "name", "String Prop", 0, "", "String property name");
parm = RNA_def_pointer(func, "layer", "MeshStringPropertyLayer", "", "The newly created layer");
@@ -2848,7 +2890,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "tessfaces", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "mface", "totface");
RNA_def_property_struct_type(prop, "MeshTessFace");
- RNA_def_property_ui_text(prop, "TessFaces", "Tessellation faces of the mesh (derived from polygons)");
+ RNA_def_property_ui_text(prop, "TessFaces", "Tessellated faces of the mesh (derived from polygons)");
rna_def_mesh_tessfaces(brna, prop);
prop = RNA_def_property(srna, "loops", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index ad9977fef50..a25f56f2259 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -37,6 +37,7 @@
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "BKE_mesh.h"
#include "ED_mesh.h"
@@ -47,7 +48,7 @@
#include "DNA_mesh_types.h"
-static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, struct Mesh *mesh2)
+static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, struct Mesh *mesh2)
{
const char *ret = BKE_mesh_cmp(mesh, mesh2, FLT_EPSILON * 60);
@@ -57,14 +58,56 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, st
return ret;
}
-void rna_Mesh_calc_smooth_groups(struct Mesh *mesh, int *r_poly_group_len, int **r_poly_group, int *r_group_total)
+static void rna_Mesh_calc_normals_split(Mesh *mesh, float min_angle)
+{
+ float (*r_loopnors)[3];
+ float (*polynors)[3];
+ bool free_polynors = false;
+
+ if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
+ r_loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop);
+ }
+ else {
+ r_loopnors = CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_CALLOC, NULL, mesh->totloop);
+ CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+ }
+
+ if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
+ /* This assume that layer is always up to date, not sure this is the case (esp. in Edit mode?)... */
+ polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+ free_polynors = false;
+ }
+ else {
+ polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
+ BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
+ polynors, false);
+ free_polynors = true;
+ }
+
+ BKE_mesh_normals_loop_split(mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
+ mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, polynors, mesh->totpoly,
+ min_angle);
+
+ if (free_polynors) {
+ MEM_freeN(polynors);
+ }
+}
+
+static void rna_Mesh_free_normals_split(Mesh *mesh)
+{
+ CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
+}
+
+static void rna_Mesh_calc_smooth_groups(Mesh *mesh, int use_bitflags, int *r_poly_group_len,
+ int **r_poly_group, int *r_group_total)
{
*r_poly_group_len = mesh->totpoly;
*r_poly_group = BKE_mesh_calc_smoothgroups(
mesh->medge, mesh->totedge,
mesh->mpoly, mesh->totpoly,
mesh->mloop, mesh->totloop,
- r_group_total);
+ r_group_total, use_bitflags);
}
#else
@@ -82,11 +125,22 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "calc_normals", "BKE_mesh_calc_normals");
RNA_def_function_ui_description(func, "Calculate vertex normals");
+ func = RNA_def_function(srna, "calc_normals_split", "rna_Mesh_calc_normals_split");
+ RNA_def_function_ui_description(func, "Calculate split vertex normals, which preserve sharp edges");
+ parm = RNA_def_float(func, "split_angle", M_PI, 0.0f, M_PI, "",
+ "Angle between polys' normals above which an edge is always sharp (180° to disable)",
+ 0.0f, M_PI);
+ RNA_def_property_subtype(parm, (PropertySubType)PROP_UNIT_ROTATION);
+
+ func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
+ RNA_def_function_ui_description(func, "Free split vertex normals");
+
func = RNA_def_function(srna, "calc_tessface", "ED_mesh_calc_tessface");
RNA_def_function_ui_description(func, "Calculate face tessellation (supports editmode too)");
func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
+ RNA_def_boolean(func, "use_bitflags", false, "", "Produce bitflags groups instead of simple numeric values");
/* return values */
parm = RNA_def_int_array(func, "poly_groups", 1, NULL, 0, 0, "", "Smooth Groups", 0, 0);
RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT);
@@ -101,7 +155,6 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "unit_test_compare", "rna_Mesh_unit_test_compare");
RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
/* return value */
parm = RNA_def_string(func, "result", "nothing", 64, "Return value", "String description of result of comparison");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h
index dfe36da033b..c0ea1a153ff 100644
--- a/source/blender/makesrna/intern/rna_mesh_utils.h
+++ b/source/blender/makesrna/intern/rna_mesh_utils.h
@@ -32,7 +32,8 @@
/* Define the accessors for a basic CustomDataLayer collection */
#define DEFINE_CUSTOMDATA_LAYER_COLLECTION(collection_name, customdata_type, layer_type) \
/* check */ \
- static int rna_##collection_name##_check(CollectionPropertyIterator *iter, void *data) \
+ static int rna_##collection_name##_check( \
+ CollectionPropertyIterator *UNUSED(iter), void *data) \
{ \
CustomDataLayer *layer = (CustomDataLayer *)data; \
return (layer->type != layer_type); \
@@ -59,8 +60,9 @@
return data ? CustomData_number_of_layers(data, layer_type) : 0; \
} \
/* index range */ \
- static void rna_Mesh_##collection_name##_index_range(PointerRNA *ptr, int *min, int *max, \
- int *softmin, int *softmax) \
+ static void rna_Mesh_##collection_name##_index_range( \
+ PointerRNA *ptr, int *min, int *max, \
+ int *UNUSED(softmin), int *UNUSED(softmax)) \
{ \
CustomData *data = rna_mesh_##customdata_type(ptr); \
*min = 0; \
diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c
index 11f0e48012b..6bf7c8926e8 100644
--- a/source/blender/makesrna/intern/rna_meta.c
+++ b/source/blender/makesrna/intern/rna_meta.c
@@ -320,13 +320,15 @@ static void rna_def_metaball(BlenderRNA *brna)
/* number values */
prop = RNA_def_property(srna, "resolution", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "wiresize");
- RNA_def_property_range(prop, 0.050f, 1.0f);
+ RNA_def_property_range(prop, 0.005f, 10000.0f);
+ RNA_def_property_ui_range(prop, 0.05f, 1000.0f, 2.5f, 3);
RNA_def_property_ui_text(prop, "Wire Size", "Polygonization resolution in the 3D viewport");
RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
prop = RNA_def_property(srna, "render_resolution", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "rendersize");
- RNA_def_property_range(prop, 0.050f, 1.0f);
+ RNA_def_property_range(prop, 0.005f, 10000.0f);
+ RNA_def_property_ui_range(prop, 0.025f, 1000.0f, 2.5f, 3);
RNA_def_property_ui_text(prop, "Render Size", "Polygonization resolution in rendering");
RNA_def_property_update(prop, 0, "rna_MetaBall_update_data");
@@ -371,7 +373,7 @@ static void rna_def_metaball(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Material");
RNA_def_property_ui_text(prop, "Materials", "");
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
- RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
prop = RNA_def_property(srna, "is_editmode", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_Meta_is_editmode_get", NULL);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index ebaec5c7c09..744d41b198e 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -495,7 +495,8 @@ static void rna_MultiresModifier_type_set(PointerRNA *ptr, int value)
mmd->simple = value;
}
-static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
MultiresModifierData *mmd = (MultiresModifierData *)ptr->data;
@@ -670,8 +671,8 @@ static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value)
UVProjectModifierData *md = (UVProjectModifierData *)ptr->data;
int a;
- md->num_projectors = CLAMPIS(value, 1, MOD_UVPROJECT_MAX);
- for (a = md->num_projectors; a < MOD_UVPROJECT_MAX; a++)
+ md->num_projectors = CLAMPIS(value, 1, MOD_UVPROJECT_MAXPROJECTORS);
+ for (a = md->num_projectors; a < MOD_UVPROJECT_MAXPROJECTORS; a++)
md->projectors[a] = NULL;
}
@@ -1729,7 +1730,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "num_projectors");
RNA_def_property_ui_text(prop, "Number of Projectors", "Number of projectors to use");
RNA_def_property_int_funcs(prop, NULL, "rna_UVProjectModifier_num_projectors_set", NULL);
- RNA_def_property_range(prop, 1, MOD_UVPROJECT_MAX);
+ RNA_def_property_range(prop, 1, MOD_UVPROJECT_MAXPROJECTORS);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "projectors", PROP_COLLECTION, PROP_NONE);
@@ -2790,7 +2791,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_ui_range(prop, 0, -M_PI * 2, M_PI * 2, 2);
+ RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 2, -1);
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_text(prop, "Angle", "Angle of revolution");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 399131bbd61..d905e6a014a 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -36,6 +36,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -97,7 +98,7 @@ static char *rna_NlaStrip_path(PointerRNA *ptr)
}
/* no path */
- return "";
+ return BLI_strdup("");
}
static void rna_NlaStrip_transform_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -415,7 +416,9 @@ EnumPropertyItem nla_mode_blend_items[] = {
"Weighted result of strip is removed from the accumulated results"},
{NLASTRIP_MODE_MULTIPLY, "MULITPLY", 0, "Multiply",
"Weighted result of strip is multiplied with the accumulated results"},
- {0, NULL, 0, NULL, NULL}};
+ {0, NULL, 0, NULL, NULL}
+};
+
EnumPropertyItem nla_mode_extend_items[] = {
{NLASTRIP_EXTEND_NOTHING, "NOTHING", 0, "Nothing", "Strip has no influence past its extents"},
{NLASTRIP_EXTEND_HOLD, "HOLD", 0, "Hold",
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 535c279c02f..8ad19735517 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -70,7 +70,8 @@ EnumPropertyItem node_socket_in_out_items[] = {
{ 0, NULL, 0, NULL, NULL }
};
-EnumPropertyItem node_socket_type_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem node_socket_type_items[] = {
{SOCK_CUSTOM, "CUSTOM", 0, "Custom", ""},
{SOCK_FLOAT, "VALUE", 0, "Value", ""},
{SOCK_INT, "INT", 0, "Int", ""},
@@ -82,14 +83,14 @@ EnumPropertyItem node_socket_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem node_quality_items[] = {
+static EnumPropertyItem node_quality_items[] = {
{NTREE_QUALITY_HIGH, "HIGH", 0, "High", "High quality"},
{NTREE_QUALITY_MEDIUM, "MEDIUM", 0, "Medium", "Medium quality"},
{NTREE_QUALITY_LOW, "LOW", 0, "Low", "Low quality"},
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem node_chunksize_items[] = {
+static EnumPropertyItem node_chunksize_items[] = {
{NTREE_CHUNCKSIZE_32, "32", 0, "32x32", "Chunksize of 32x32"},
{NTREE_CHUNCKSIZE_64, "64", 0, "64x64", "Chunksize of 64x64"},
{NTREE_CHUNCKSIZE_128, "128", 0, "128x128", "Chunksize of 128x128"},
@@ -98,6 +99,7 @@ EnumPropertyItem node_chunksize_items[] = {
{NTREE_CHUNCKSIZE_1024, "1024", 0, "1024x1024", "Chunksize of 1024x1024"},
{0, NULL, 0, NULL, NULL}
};
+#endif
#define DEF_ICON_BLANK_SKIP
#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
@@ -152,39 +154,13 @@ EnumPropertyItem node_filter_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem node_sampler_type_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem node_sampler_type_items[] = {
{0, "NEAREST", 0, "Nearest", ""},
{1, "BILINEAR", 0, "Bilinear", ""},
{2, "BICUBIC", 0, "Bicubic", ""},
{0, NULL, 0, NULL, NULL}
};
-
-
-EnumPropertyItem prop_noise_basis_items[] = {
- {SHD_NOISE_PERLIN, "PERLIN", 0, "Perlin", ""},
- {SHD_NOISE_VORONOI_F1, "VORONOI_F1", 0, "Voronoi F1", ""},
- {SHD_NOISE_VORONOI_F2, "VORONOI_F2", 0, "Voronoi F2", ""},
- {SHD_NOISE_VORONOI_F3, "VORONOI_F3", 0, "Voronoi F3", ""},
- {SHD_NOISE_VORONOI_F4, "VORONOI_F4", 0, "Voronoi F4", ""},
- {SHD_NOISE_VORONOI_F2_F1, "VORONOI_F2_F1", 0, "Voronoi F2-F1", ""},
- {SHD_NOISE_VORONOI_CRACKLE, "VORONOI_CRACKLE", 0, "Voronoi Crackle", ""},
- {SHD_NOISE_CELL_NOISE, "CELL_NOISE", 0, "Cell Noise", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-EnumPropertyItem prop_noise_type_items[] = {
- {SHD_NOISE_SOFT, "SOFT", 0, "Soft", ""},
- {SHD_NOISE_HARD, "HARD", 0, "Hard", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-#if 0
-EnumPropertyItem prop_wave_items[] = {
- {SHD_WAVE_SINE, "SINE", 0, "Sine", "Use a sine wave to produce bands"},
- {SHD_WAVE_SAW, "SAW", 0, "Saw", "Use a saw wave to produce bands"},
- {SHD_WAVE_TRI, "TRI", 0, "Tri", "Use a triangle wave to produce bands"},
- {0, NULL, 0, NULL, NULL}
-};
#endif
#ifdef RNA_RUNTIME
@@ -214,26 +190,30 @@ EnumPropertyItem prop_wave_items[] = {
int rna_node_tree_type_to_enum(bNodeTreeType *typeinfo)
{
int i = 0, result = -1;
- NODE_TREE_TYPES_BEGIN(nt)
+ NODE_TREE_TYPES_BEGIN (nt)
+ {
if (nt == typeinfo) {
result = i;
break;
}
++i;
- NODE_TREE_TYPES_END
+ }
+ NODE_TREE_TYPES_END;
return result;
}
int rna_node_tree_idname_to_enum(const char *idname)
{
int i = 0, result = -1;
- NODE_TREE_TYPES_BEGIN(nt)
+ NODE_TREE_TYPES_BEGIN (nt)
+ {
if (STREQ(nt->idname, idname)) {
result = i;
break;
}
++i;
- NODE_TREE_TYPES_END
+ }
+ NODE_TREE_TYPES_END;
return result;
}
@@ -241,13 +221,15 @@ bNodeTreeType *rna_node_tree_type_from_enum(int value)
{
int i = 0;
bNodeTreeType *result = NULL;
- NODE_TREE_TYPES_BEGIN(nt)
+ NODE_TREE_TYPES_BEGIN (nt)
+ {
if (i == value) {
result = nt;
break;
}
++i;
- NODE_TREE_TYPES_END
+ }
+ NODE_TREE_TYPES_END;
return result;
}
@@ -257,7 +239,8 @@ EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, b
EnumPropertyItem *item = NULL;
int totitem = 0, i = 0;
- NODE_TREE_TYPES_BEGIN(nt)
+ NODE_TREE_TYPES_BEGIN (nt)
+ {
if (poll && !poll(data, nt)) {
++i;
continue;
@@ -272,7 +255,8 @@ EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, b
RNA_enum_item_add(&item, &totitem, &tmp);
++i;
- NODE_TREE_TYPES_END
+ }
+ NODE_TREE_TYPES_END;
RNA_enum_item_end(&item, &totitem);
*free = 1;
@@ -600,8 +584,9 @@ static void rna_NodeTree_unregister(Main *UNUSED(bmain), StructRNA *type)
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
}
-static StructRNA *rna_NodeTree_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_NodeTree_register(
+ Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeTreeType *nt, dummynt;
bNodeTree dummyntree;
@@ -668,7 +653,7 @@ static bool rna_NodeTree_check(bNodeTree *ntree, ReportList *reports)
return true;
}
-static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeTree_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@ -931,22 +916,6 @@ static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value)
}
}
-static int rna_NodeTree_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_IN, key);
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
- return (sock != NULL);
-}
-
-static int rna_NodeTree_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_OUT, key);
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
- return (sock != NULL);
-}
-
static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name)
{
bNodeSocket *sock;
@@ -1422,9 +1391,10 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc
return nt;
}
-static StructRNA *rna_Node_register(Main *bmain, ReportList *reports,
- void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_Node_register(
+ Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_Node, data, identifier, validate, call, free);
if (!nt)
@@ -1438,9 +1408,10 @@ static StructRNA *rna_Node_register(Main *bmain, ReportList *reports,
return nt->ext.srna;
}
-static StructRNA *rna_ShaderNode_register(Main *bmain, ReportList *reports,
- void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_ShaderNode_register(
+ Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_ShaderNode, data, identifier, validate, call, free);
if (!nt)
@@ -1454,9 +1425,10 @@ static StructRNA *rna_ShaderNode_register(Main *bmain, ReportList *reports,
return nt->ext.srna;
}
-static StructRNA *rna_CompositorNode_register(Main *bmain, ReportList *reports,
- void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_CompositorNode_register(
+ Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_CompositorNode, data, identifier, validate, call, free);
if (!nt)
@@ -1470,9 +1442,10 @@ static StructRNA *rna_CompositorNode_register(Main *bmain, ReportList *reports,
return nt->ext.srna;
}
-static StructRNA *rna_TextureNode_register(Main *bmain, ReportList *reports,
- void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_TextureNode_register(
+ Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_TextureNode, data, identifier, validate, call, free);
if (!nt)
@@ -1573,22 +1546,6 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value)
BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name);
}
-static int rna_Node_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
-{
- bNode *node = (bNode *)ptr->data;
- bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, key);
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
- return (sock != NULL);
-}
-
-static int rna_Node_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
-{
- bNode *node = (bNode *)ptr->data;
- bNodeSocket *sock = nodeFindSocket(node, SOCK_OUT, key);
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
- return (sock != NULL);
-}
-
static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
{
bNodeTree *ntree = (bNodeTree *)id;
@@ -1810,8 +1767,9 @@ static void rna_NodeSocket_unregister(Main *UNUSED(bmain), StructRNA *type)
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
}
-static StructRNA *rna_NodeSocket_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_NodeSocket_register(
+ Main *UNUSED(bmain), ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeSocketType *st, dummyst;
bNodeSocket dummysock;
@@ -2081,8 +2039,9 @@ static void rna_NodeSocketInterface_unregister(Main *UNUSED(bmain), StructRNA *t
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
}
-static StructRNA *rna_NodeSocketInterface_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_NodeSocketInterface_register(
+ Main *UNUSED(bmain), ReportList *UNUSED(reports), void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeSocketType *st, dummyst;
bNodeSocket dummysock;
@@ -2398,9 +2357,10 @@ static void rna_NodeInternal_draw_buttons_ext(ID *id, bNode *node, struct bConte
}
}
-static StructRNA *rna_NodeCustomGroup_register(Main *bmain, ReportList *reports,
- void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_NodeCustomGroup_register(
+ Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_NodeCustomGroup, data, identifier, validate, call, free);
if (!nt)
@@ -2782,6 +2742,23 @@ static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *va
}
}
+static bNodeSocket *rna_NodeOutputFile_slots_new(ID *id, bNode *node, bContext *C, ReportList *UNUSED(reports), const char *name)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ Scene *scene = CTX_data_scene(C);
+ ImageFormatData *im_format = NULL;
+ bNodeSocket *sock;
+ if (scene)
+ im_format = &scene->r.im_format;
+
+ sock = ntreeCompositOutputFileAddSocket(ntree, node, name, im_format);
+
+ ntreeUpdateTree(CTX_data_main(C), ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+
+ return sock;
+}
+
static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
{
bNode *node = (bNode *)ptr->data;
@@ -2861,6 +2838,24 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
ED_node_tag_update_nodetree(bmain, ntree);
}
+static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+
+ nodeUpdate(ntree, node);
+ rna_Node_update(bmain, scene, ptr);
+}
+
+static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+
+ nodeUpdate(ntree, node);
+ rna_Node_update(bmain, scene, ptr);
+}
+
#else
static EnumPropertyItem prop_image_layer_items[] = {
@@ -2907,6 +2902,12 @@ static EnumPropertyItem node_toon_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem node_hair_items[] = {
+ {SHD_HAIR_REFLECTION, "Reflection", 0, "Reflection", ""},
+ {SHD_HAIR_TRANSMISSION, "Transmission", 0, "Transmission", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
static EnumPropertyItem node_script_mode_items[] = {
{NODE_SCRIPT_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"},
{NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or .oso file"},
@@ -3143,10 +3144,24 @@ static void def_sh_material(StructRNA *srna)
static void def_sh_mapping(StructRNA *srna)
{
+ static EnumPropertyItem prop_vect_type_items[] = {
+ {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transform a texture by inverse mapping the texture coordinate"},
+ {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"},
+ {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"},
+ {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "TexMapping", "storage");
+ prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, prop_vect_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms");
+ RNA_def_property_update(prop, 0, "rna_Mapping_Node_update");
+
prop = RNA_def_property(srna, "translation", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "loc");
RNA_def_property_ui_text(prop, "Location", "");
@@ -3230,19 +3245,37 @@ static void def_sh_tex(StructRNA *srna)
static void def_sh_tex_sky(StructRNA *srna)
{
+ static EnumPropertyItem prop_sky_type[] = {
+ {SHD_SKY_OLD, "PREETHAM", 0, "Preetham", ""},
+ {SHD_SKY_NEW, "HOSEK_WILKIE", 0, "Hosek / Wilkie", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeTexSky", "storage");
def_sh_tex(srna);
+
+ prop = RNA_def_property(srna, "sky_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "sky_model");
+ RNA_def_property_enum_items(prop, prop_sky_type);
+ RNA_def_property_ui_text(prop, "Sky Type", "");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "sun_direction", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_ui_text(prop, "Sun Direction", "Direction from where the sun is shining");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "turbidity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 1.0f, 30.0f);
+ RNA_def_property_range(prop, 1.0f, 10.0f);
+ RNA_def_property_ui_range(prop, 1.0f, 10.0f, 10, 3);
RNA_def_property_ui_text(prop, "Turbidity", "Atmospheric turbidity");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "ground_albedo", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Ground Albedo", "Ground color that is subtly reflected in the sky");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_sh_tex_environment(StructRNA *srna)
@@ -3512,9 +3545,9 @@ static void def_sh_tex_coord(StructRNA *srna)
static void def_sh_vect_transform(StructRNA *srna)
{
static EnumPropertyItem prop_vect_type_items[] = {
- {SHD_VECT_TRANSFORM_TYPE_VECTOR, "VECTOR", 0, "Vector", ""},
- {SHD_VECT_TRANSFORM_TYPE_POINT, "POINT", 0, "Point", ""},
- {SHD_VECT_TRANSFORM_TYPE_NORMAL, "NORMAL", 0, "Normal", ""},
+ {SHD_VECT_TRANSFORM_TYPE_POINT, "POINT", 0, "Point", "Transform a point"},
+ {SHD_VECT_TRANSFORM_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"},
+ {SHD_VECT_TRANSFORM_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"},
{0, NULL, 0, NULL, NULL}
};
@@ -3529,7 +3562,8 @@ static void def_sh_vect_transform(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeShaderVectTransform", "storage");
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_vect_type_items);
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_update(prop, 0, "rna_Node_update");
@@ -3587,6 +3621,17 @@ static void def_sh_bump(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_hair(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "component", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, node_hair_items);
+ RNA_def_property_ui_text(prop, "Component", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_sh_normal_map(StructRNA *srna)
{
static EnumPropertyItem prop_space_items[] = {
@@ -3650,6 +3695,24 @@ static void def_sh_tangent(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "bNode", NULL);
}
+
+static void def_sh_subsurface(StructRNA *srna)
+{
+ static EnumPropertyItem prop_subsurface_falloff_items[] = {
+ {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"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "falloff", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, prop_subsurface_falloff_items);
+ RNA_def_property_ui_text(prop, "Falloff", "Function to determine how much light nearby points contribute based on their distance to the shading point");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeSubsurface_update");
+}
+
static void def_sh_script(StructRNA *srna)
{
PropertyRNA *prop;
@@ -4121,7 +4184,49 @@ static void rna_def_cmp_output_file_slot_layer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Name", "OpenEXR layer name used for this slot");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
}
-static void def_cmp_output_file(StructRNA *srna)
+static void rna_def_cmp_output_file_slots_api(BlenderRNA *brna, PropertyRNA *cprop, const char *struct_name)
+{
+ StructRNA *srna;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+
+ RNA_def_property_srna(cprop, struct_name);
+ srna = RNA_def_struct(brna, struct_name, NULL);
+ RNA_def_struct_sdna(srna, "bNode");
+ RNA_def_struct_ui_text(srna, "File Output Slots", "Collection of File Output node slots");
+
+ func = RNA_def_function(srna, "new", "rna_NodeOutputFile_slots_new");
+ RNA_def_function_ui_description(func, "Add a file slot to this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
+ parm = RNA_def_string(func, "name", "", MAX_NAME, "Name", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return value */
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ RNA_def_function_return(func, parm);
+
+ /* NB: methods below can use the standard node socket API functions,
+ * included here for completeness.
+ */
+
+ func = RNA_def_function(srna, "remove", "rna_Node_socket_remove");
+ RNA_def_function_ui_description(func, "Remove a file slot from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "clear", "rna_Node_inputs_clear");
+ RNA_def_function_ui_description(func, "Remove all file slots from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+
+ func = RNA_def_function(srna, "move", "rna_Node_inputs_move");
+ RNA_def_function_ui_description(func, "Move a file slot to another position");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the socket to move", 0, 10000);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the socket", 0, 10000);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+}
+static void def_cmp_output_file(BlenderRNA *brna, StructRNA *srna)
{
PropertyRNA *prop;
@@ -4149,12 +4254,14 @@ static void def_cmp_output_file(StructRNA *srna)
"rna_NodeOutputFile_slot_file_get", NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "NodeOutputFileSlotFile");
RNA_def_property_ui_text(prop, "File Slots", "");
+ rna_def_cmp_output_file_slots_api(brna, prop, "CompositorNodeOutputFileFileSlots");
prop = RNA_def_property(srna, "layer_slots", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_funcs(prop, "rna_NodeOutputFile_slots_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end",
"rna_NodeOutputFile_slot_layer_get", NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "NodeOutputFileSlotLayer");
RNA_def_property_ui_text(prop, "EXR Layer Slots", "");
+ rna_def_cmp_output_file_slots_api(brna, prop, "CompositorNodeOutputFileLayerSlots");
}
static void def_cmp_dilate_erode(StructRNA *srna)
@@ -4261,7 +4368,7 @@ static void def_cmp_scale(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, space_items);
RNA_def_property_ui_text(prop, "Space", "Coordinate space to scale relative to");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_CompositorNodeScale_update");
/* expose 2 flags as a enum of 3 items */
prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
@@ -5336,7 +5443,7 @@ static void dev_cmd_transform(StructRNA *srna)
/* -- Compositor Nodes ------------------------------------------------------ */
-EnumPropertyItem node_masktype_items[] = {
+static EnumPropertyItem node_masktype_items[] = {
{0, "ADD", 0, "Add", ""},
{1, "SUBTRACT", 0, "Subtract", ""},
{2, "MULTIPLY", 0, "Multiply", ""},
@@ -5919,6 +6026,29 @@ static void def_cmp_translate(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_planetrackdeform(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "MovieClip");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Movie Clip", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "NodePlaneTrackDeformData", "storage");
+
+ prop = RNA_def_property(srna, "tracking_object", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "tracking_object");
+ RNA_def_property_ui_text(prop, "Tracking Object", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "plane_track_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "plane_track_name");
+ RNA_def_property_ui_text(prop, "Plane Track", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
/* -- Texture Nodes --------------------------------------------------------- */
@@ -6809,16 +6939,12 @@ static void rna_def_node(BlenderRNA *brna)
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
- "rna_Node_inputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Inputs", "");
rna_def_node_sockets_api(brna, prop, SOCK_IN);
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
- "rna_Node_outputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Outputs", "");
rna_def_node_sockets_api(brna, prop, SOCK_OUT);
@@ -7234,8 +7360,6 @@ static void rna_def_nodetree(BlenderRNA *brna)
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
- "rna_NodeTree_inputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocketInterface");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Inputs", "Node tree inputs");
@@ -7248,8 +7372,6 @@ static void rna_def_nodetree(BlenderRNA *brna)
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
- "rna_NodeTree_outputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocketInterface");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Outputs", "Node tree outputs");
@@ -7381,8 +7503,8 @@ static void rna_def_texture_nodetree(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_TEXTURE);
}
-static void define_specific_node(BlenderRNA *brna, const char *struct_name, const char *base_name,
- const char *ui_name, const char *ui_desc, void (*def_func)(StructRNA *))
+static StructRNA *define_specific_node(BlenderRNA *brna, const char *struct_name, const char *base_name,
+ const char *ui_name, const char *ui_desc, void (*def_func)(StructRNA *))
{
StructRNA *srna;
FunctionRNA *func;
@@ -7429,6 +7551,8 @@ static void define_specific_node(BlenderRNA *brna, const char *struct_name, cons
if (def_func)
def_func(srna);
+
+ return srna;
}
static void rna_def_node_instance_hash(BlenderRNA *brna)
@@ -7446,6 +7570,8 @@ static void rna_def_node_instance_hash(BlenderRNA *brna)
void RNA_def_nodetree(BlenderRNA *brna)
{
+ StructRNA *srna;
+
rna_def_node_socket(brna);
rna_def_node_socket_interface(brna);
@@ -7466,7 +7592,13 @@ void RNA_def_nodetree(BlenderRNA *brna)
rna_def_texture_nodetree(brna);
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- define_specific_node(brna, #Category #StructName, #Category, UIName, UIDesc, DefFunc);
+ { \
+ srna = define_specific_node(brna, #Category #StructName, #Category, UIName, UIDesc, DefFunc); \
+ if (ID == CMP_NODE_OUTPUT_FILE) { \
+ /* needs brna argument, can't use NOD_static_types.h */ \
+ def_cmp_output_file(brna, srna); \
+ } \
+ }
/* hack, don't want to add include path to RNA just for this, since in the future RNA types
* for nodes should be defined locally at runtime anyway ...
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index e71d1d22c4b..dffdc988ca6 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -465,7 +465,7 @@ static EnumPropertyItem *rna_Object_parent_type_itemf(bContext *UNUSED(C), Point
RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARBONE);
}
- if (ELEM4(par->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE)) {
+ if (OB_TYPE_SUPPORT_PARVERT(par->type)) {
RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARVERT1);
RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARVERT3);
}
@@ -556,7 +556,8 @@ static void rna_Object_active_vertex_group_index_set(PointerRNA *ptr, int value)
ob->actdef = value + 1;
}
-static void rna_Object_active_vertex_group_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Object_active_vertex_group_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->id.data;
@@ -667,7 +668,8 @@ static void rna_Object_active_material_index_set(PointerRNA *ptr, int value)
}
}
-static void rna_Object_active_material_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Object_active_material_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->id.data;
*min = 0;
@@ -693,7 +695,7 @@ static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value)
}
static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int *min, int *max,
- int *softmin, int *softmax)
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->id.data;
*min = 0;
@@ -903,6 +905,16 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Object_internal_update(bmain, scene, ptr);
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->id.data);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+}
+
+static char *rna_MaterialSlot_path(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+ int index = (Material **)ptr->data - ob->mat;
+
+ /* from armature... */
+ return BLI_sprintfN("material_slots[%d]", index);
}
/* why does this have to be so complicated?, can't all this crap be
@@ -1183,7 +1195,8 @@ static void rna_GameObjectSettings_col_mask_set(PointerRNA *ptr, const int *valu
}
-static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->id.data;
Key *key = BKE_key_from_object(ob);
@@ -1549,6 +1562,8 @@ static void rna_def_material_slot(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Name", "Material slot name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
+
+ RNA_def_struct_path_func(srna, "rna_MaterialSlot_path");
}
static void rna_def_object_game_settings(BlenderRNA *brna)
@@ -2349,7 +2364,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Constraint");
RNA_def_property_ui_text(prop, "Constraints", "Constraints affecting the transformation of the object");
-/* RNA_def_property_collection_funcs(prop, 0, 0, 0, 0, 0, 0, 0, "constraints__add", "constraints__remove"); */
+/* RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "constraints__add", "constraints__remove"); */
rna_def_object_constraints(brna, prop);
/* game engine */
@@ -2762,11 +2777,14 @@ static void rna_def_object_base(BlenderRNA *brna)
void RNA_def_object(BlenderRNA *brna)
{
rna_def_object(brna);
+
+ RNA_define_animate_sdna(false);
rna_def_object_game_settings(brna);
rna_def_object_base(brna);
rna_def_vertex_group(brna);
rna_def_material_slot(brna);
rna_def_dupli_object(brna);
+ RNA_define_animate_sdna(true);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 1d2aa08e7cd..146ba6e4b7d 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -228,7 +228,8 @@ static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *p
rna_iterator_listbase_begin(iter, &lb, NULL);
}
-static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = ptr->id.data;
PointCache *cache = ptr->data;
@@ -291,7 +292,8 @@ static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int v
BLI_freelistN(&pidlist);
}
-static void rna_PointCache_frame_step_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_PointCache_frame_step_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = ptr->id.data;
PointCache *cache = ptr->data;
@@ -861,7 +863,9 @@ static void rna_def_pointcache(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_library_path", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PTCACHE_IGNORE_LIBPATH);
- RNA_def_property_ui_text(prop, "Library Path", "Use this files path when library linked into another file");
+ RNA_def_property_ui_text(prop, "Library Path",
+ "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");
prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_packedfile.c b/source/blender/makesrna/intern/rna_packedfile.c
index a72188591a1..365ad5fdb9a 100644
--- a/source/blender/makesrna/intern/rna_packedfile.c
+++ b/source/blender/makesrna/intern/rna_packedfile.c
@@ -31,6 +31,7 @@
#include "DNA_packedFile_types.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index b966a7d7f2c..8dafe54e678 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -52,34 +52,40 @@
#include "WM_types.h"
#include "WM_api.h"
-EnumPropertyItem part_from_items[] = {
+#ifdef RNA_RUNTIME
+static EnumPropertyItem part_from_items[] = {
{PART_FROM_VERT, "VERT", 0, "Verts", ""},
{PART_FROM_FACE, "FACE", 0, "Faces", ""},
{PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
-EnumPropertyItem part_reactor_from_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem part_reactor_from_items[] = {
{PART_FROM_VERT, "VERT", 0, "Verts", ""},
{PART_FROM_FACE, "FACE", 0, "Faces", ""},
{PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
-EnumPropertyItem part_dist_items[] = {
+static EnumPropertyItem part_dist_items[] = {
{PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
{PART_DISTR_RAND, "RAND", 0, "Random", ""},
{PART_DISTR_GRID, "GRID", 0, "Grid", ""},
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem part_hair_dist_items[] = {
+#ifdef RNA_RUNTIME
+static EnumPropertyItem part_hair_dist_items[] = {
{PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
{PART_DISTR_RAND, "RAND", 0, "Random", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
-EnumPropertyItem part_draw_as_items[] = {
+static EnumPropertyItem part_draw_as_items[] = {
{PART_DRAW_NOT, "NONE", 0, "None", ""},
{PART_DRAW_REND, "RENDER", 0, "Rendered", ""},
{PART_DRAW_DOT, "DOT", 0, "Point", ""},
@@ -89,14 +95,16 @@ EnumPropertyItem part_draw_as_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem part_hair_draw_as_items[] = {
+#ifdef RNA_RUNTIME
+static EnumPropertyItem part_hair_draw_as_items[] = {
{PART_DRAW_NOT, "NONE", 0, "None", ""},
{PART_DRAW_REND, "RENDER", 0, "Rendered", ""},
{PART_DRAW_PATH, "PATH", 0, "Path", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
-EnumPropertyItem part_ren_as_items[] = {
+static EnumPropertyItem part_ren_as_items[] = {
{PART_DRAW_NOT, "NONE", 0, "None", ""},
{PART_DRAW_HALO, "HALO", 0, "Halo", ""},
{PART_DRAW_LINE, "LINE", 0, "Line", ""},
@@ -107,13 +115,15 @@ EnumPropertyItem part_ren_as_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem part_hair_ren_as_items[] = {
+#ifdef RNA_RUNTIME
+static EnumPropertyItem part_hair_ren_as_items[] = {
{PART_DRAW_NOT, "NONE", 0, "None", ""},
{PART_DRAW_PATH, "PATH", 0, "Path", ""},
{PART_DRAW_OB, "OBJECT", 0, "Object", ""},
{PART_DRAW_GR, "GROUP", 0, "Group", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
#ifdef RNA_RUNTIME
@@ -261,7 +271,8 @@ static void rna_ParticleHairKey_co_object(HairKey *hairkey, Object *object, Part
}
}
-static void rna_Particle_uv_on_emitter(ParticleData *particle, ParticleSystemModifierData *modifier, float n_uv[2])
+static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *reports,
+ ParticleSystemModifierData *modifier, float r_uv[2])
{
/*psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, nor, 0, 0, sd.orco, 0);*/
@@ -269,28 +280,39 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle, ParticleSystemMod
int num = particle->num_dmcache;
int from = modifier->psys->part->from;
+ if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
+ BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
+ return;
+ }
+ DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+
if (num == DMCACHE_NOTFOUND)
if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
num = particle->num;
/* get uvco */
- if (n_uv && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (r_uv && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
- mtface += num;
-
- psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
- }
- else {
- n_uv[0] = 0.0f;
- n_uv[1] = 0.0f;
+ MFace *mface;
+ MTFace *mtface;
+
+ mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+
+ if (mface && mtface) {
+ mtface += num;
+ psys_interpolate_uvs(mtface, mface->v4, particle->fuv, r_uv);
+ return;
+ }
}
}
+
+ r_uv[0] = 0.0f;
+ r_uv[1] = 0.0f;
}
-static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object, ParticleSystemModifierData *modifier,
+static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object,
int particle_no, int step, float n_co[3])
{
ParticleSettings *part = 0;
@@ -368,14 +390,22 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o
}
-static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no, int uv_no,
- float n_uv[2])
+static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
+ ParticleSystemModifierData *modifier, ParticleData *particle,
+ int particle_no, int uv_no,
+ float r_uv[2])
{
ParticleSettings *part = 0;
int totpart;
int totchild = 0;
int num;
+ if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
+ BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
+ return;
+ }
+ DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+
/* 1. check that everything is ok & updated */
if (particlesystem == NULL)
return;
@@ -409,17 +439,17 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
num = particle->num;
- if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (r_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
if (num != DMCACHE_NOTFOUND) {
MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
mtface += num;
- psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
+ psys_interpolate_uvs(mtface, mface->v4, particle->fuv, r_uv);
}
else {
- n_uv[0] = 0.0f;
- n_uv[1] = 0.0f;
+ r_uv[0] = 0.0f;
+ r_uv[1] = 0.0f;
}
}
}
@@ -430,17 +460,17 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
/* get uvco & mcol */
if (part->childtype == PART_CHILD_FACES) {
- if (n_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (r_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
if (cpa->num != DMCACHE_NOTFOUND) {
MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
mtface += cpa->num;
- psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, n_uv);
+ psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, r_uv);
}
else {
- n_uv[0] = 0.0f;
- n_uv[1] = 0.0f;
+ r_uv[0] = 0.0f;
+ r_uv[1] = 0.0f;
}
}
}
@@ -452,17 +482,17 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par
if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
num = parent->num;
- if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (r_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
if (num != DMCACHE_NOTFOUND) {
MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
mtface += num;
- psys_interpolate_uvs(mtface, mface->v4, parent->fuv, n_uv);
+ psys_interpolate_uvs(mtface, mface->v4, parent->fuv, r_uv);
}
else {
- n_uv[0] = 0.0f;
- n_uv[1] = 0.0f;
+ r_uv[0] = 0.0f;
+ r_uv[1] = 0.0f;
}
}
}
@@ -832,7 +862,8 @@ static float rna_PartSetting_linelentail_get(struct PointerRNA *ptr)
ParticleSettings *settings = (ParticleSettings *)ptr->data;
return settings->draw_line[0];
}
-static void rna_PartSetting_pathstartend_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_PartSetting_pathstartend_range(PointerRNA *ptr, float *min, float *max,
+ float *UNUSED(softmin), float *UNUSED(softmax))
{
ParticleSettings *settings = (ParticleSettings *)ptr->data;
@@ -889,7 +920,7 @@ static PointerRNA rna_ParticleSystem_active_particle_target_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL);
}
static void rna_ParticleSystem_active_particle_target_index_range(PointerRNA *ptr, int *min, int *max,
- int *softmin, int *softmax)
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
ParticleSystem *psys = (ParticleSystem *)ptr->data;
*min = 0;
@@ -1011,7 +1042,8 @@ static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr)
}
return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL);
}
-static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
ParticleSettings *part = (ParticleSettings *)ptr->id.data;
*min = 0;
@@ -1284,8 +1316,11 @@ static void rna_def_particle_hair_key(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Obtain hairkey location with particle and modifier data");
prop = RNA_def_pointer(func, "object", "Object", "", "Object");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_pointer(func, "particle", "Particle", "", "hair particle");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co",
"Exported hairkey location", -1e4, 1e4);
@@ -1451,7 +1486,9 @@ static void rna_def_particle(BlenderRNA *brna)
/* UVs */
func = RNA_def_function(srna, "uv_on_emitter", "rna_Particle_uv_on_emitter");
RNA_def_function_ui_description(func, "Obtain uv for particle on derived mesh");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
RNA_def_property_array(prop, 2);
RNA_def_property_flag(prop, PROP_THICK_WRAP);
@@ -3378,7 +3415,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Obtain cache hair data");
prop = RNA_def_pointer(func, "object", "Object", "", "Object");
- prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
prop = RNA_def_int(func, "step", 0, INT_MIN, INT_MAX, "step no", "", INT_MIN, INT_MAX);
@@ -3390,8 +3427,11 @@ static void rna_def_particle_system(BlenderRNA *brna)
/* extract hair UVs */
func = RNA_def_function(srna, "uv_on_emitter", "rna_ParticleSystem_uv_on_emitter");
RNA_def_function_ui_description(func, "Obtain uv for all particles");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
prop = RNA_def_int(func, "uv_no", 0, INT_MIN, INT_MAX, "UV no", "", INT_MIN, INT_MAX);
prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
@@ -3403,7 +3443,9 @@ static void rna_def_particle_system(BlenderRNA *brna)
func = RNA_def_function(srna, "mcol_on_emitter", "rna_ParticleSystem_mcol_on_emitter");
RNA_def_function_ui_description(func, "Obtain mcol for all particles");
prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
prop = RNA_def_int(func, "vcol_no", 0, INT_MIN, INT_MAX, "vcol no", "", INT_MIN, INT_MAX);
prop = RNA_def_property(func, "mcol", PROP_FLOAT, PROP_COLOR);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 8c73aacc724..58217206add 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -261,7 +261,7 @@ static int rna_PoseChannel_has_ik_get(PointerRNA *ptr)
Object *ob = (Object *)ptr->id.data;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- return ED_pose_channel_in_IK_chain(ob, pchan);
+ return BKE_pose_channel_in_IK_chain(ob, pchan);
}
static StructRNA *rna_IKParam_refine(PointerRNA *ptr)
@@ -382,7 +382,8 @@ static void rna_PoseChannel_bone_group_index_set(PointerRNA *ptr, int value)
pchan->agrp_index = value + 1;
}
-static void rna_PoseChannel_bone_group_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_PoseChannel_bone_group_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
Object *ob = (Object *)ptr->id.data;
bPose *pose = (ob) ? ob->pose : NULL;
@@ -415,7 +416,8 @@ static void rna_Pose_active_bone_group_index_set(PointerRNA *ptr, int value)
pose->active_group = value + 1;
}
-static void rna_Pose_active_bone_group_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_Pose_active_bone_group_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
bPose *pose = (bPose *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_property.c b/source/blender/makesrna/intern/rna_property.c
index fc3697633a4..c6b8e89c282 100644
--- a/source/blender/makesrna/intern/rna_property.c
+++ b/source/blender/makesrna/intern/rna_property.c
@@ -27,11 +27,13 @@
#include <stdlib.h>
+#include "DNA_property_types.h"
+
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
-#include "DNA_property_types.h"
#include "WM_types.h"
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 82cdfcdd631..5b809a51705 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -49,6 +49,9 @@
#include "BKE_context.h"
#include "BKE_report.h"
+#include "IMB_colormanagement.h"
+#include "GPU_extensions.h"
+
/* RenderEngine Callbacks */
static void engine_tag_redraw(RenderEngine *engine)
@@ -61,6 +64,23 @@ static void engine_tag_update(RenderEngine *engine)
engine->flag |= RE_ENGINE_DO_UPDATE;
}
+static int engine_support_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene)
+{
+ return IMB_colormanagement_support_glsl_draw(&scene->view_settings, true);
+}
+
+static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene)
+{
+ IMB_colormanagement_setup_glsl_draw(&scene->view_settings,
+ &scene->display_settings,
+ false, true);
+}
+
+static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine))
+{
+ IMB_colormanagement_finish_glsl_draw();
+}
+
static void engine_update(RenderEngine *engine, Main *bmain, Scene *scene)
{
extern FunctionRNA rna_RenderEngine_update_func;
@@ -342,14 +362,15 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_RNAPTR);
/* tag for redraw */
- RNA_def_function(srna, "tag_redraw", "engine_tag_redraw");
+ func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw");
RNA_def_function_ui_description(func, "Request redraw for viewport rendering");
/* tag for update */
- RNA_def_function(srna, "tag_update", "engine_tag_update");
+ func = RNA_def_function(srna, "tag_update", "engine_tag_update");
RNA_def_function_ui_description(func, "Request update call for viewport rendering");
func = RNA_def_function(srna, "begin_result", "RE_engine_begin_result");
+ RNA_def_function_ui_description(func, "Create render result to write linear floating point render layers and passes");
prop = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_REQUIRED);
prop = RNA_def_int(func, "y", 0, 0, INT_MAX, "Y", "", 0, INT_MAX);
@@ -363,39 +384,61 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_function_return(func, prop);
func = RNA_def_function(srna, "update_result", "RE_engine_update_result");
+ RNA_def_function_ui_description(func, "Signal that pixels have been updated and can be redrawn in the user interface");
prop = RNA_def_pointer(func, "result", "RenderResult", "Result", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
func = RNA_def_function(srna, "end_result", "RE_engine_end_result");
+ RNA_def_function_ui_description(func, "All pixels in the render result have been set and are final");
prop = RNA_def_pointer(func, "result", "RenderResult", "Result", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't merge back results");
func = RNA_def_function(srna, "test_break", "RE_engine_test_break");
+ RNA_def_function_ui_description(func, "Test if the render operation should been cancelled, this is a fast call that should be used regularly for responsiveness");
prop = RNA_def_boolean(func, "do_break", 0, "Break", "");
RNA_def_function_return(func, prop);
func = RNA_def_function(srna, "update_stats", "RE_engine_update_stats");
+ RNA_def_function_ui_description(func, "Update and signal to redraw render status text");
prop = RNA_def_string(func, "stats", "", 0, "Stats", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
prop = RNA_def_string(func, "info", "", 0, "Info", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
func = RNA_def_function(srna, "update_progress", "RE_engine_update_progress");
+ RNA_def_function_ui_description(func, "Update progress percentage of render");
prop = RNA_def_float(func, "progress", 0, 0.0f, 1.0f, "", "Percentage of render that's done", 0.0f, 1.0f);
RNA_def_property_flag(prop, PROP_REQUIRED);
func = RNA_def_function(srna, "update_memory_stats", "RE_engine_update_memory_stats");
+ RNA_def_function_ui_description(func, "Update memory usage statistics");
RNA_def_float(func, "memory_used", 0, 0.0f, FLT_MAX, "", "Current memory usage in megabytes", 0.0f, FLT_MAX);
RNA_def_float(func, "memory_peak", 0, 0.0f, FLT_MAX, "", "Peak memory usage in megabytes", 0.0f, FLT_MAX);
RNA_def_property_flag(prop, PROP_REQUIRED);
func = RNA_def_function(srna, "report", "RE_engine_report");
+ RNA_def_function_ui_description(func, "Report info, warning or error messages");
prop = RNA_def_enum_flag(func, "type", wm_report_items, 0, "Type", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
prop = RNA_def_string(func, "message", "", 0, "Report Message", "");
RNA_def_property_flag(prop, PROP_REQUIRED);
+ func = RNA_def_function(srna, "bind_display_space_shader", "engine_bind_display_space_shader");
+ RNA_def_function_ui_description(func, "Bind GLSL fragment shader that converts linear colors to display space colors using scene color management settings");
+ prop = RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "unbind_display_space_shader", "engine_unbind_display_space_shader");
+ RNA_def_function_ui_description(func, "Unbind GLSL display space shader, must always be called after binding the shader");
+
+ func = RNA_def_function(srna, "support_display_space_shader", "engine_support_display_space_shader");
+ RNA_def_function_ui_description(func, "Test if GLSL display space shader is supported for the combination of graphics card and scene settings");
+ prop = RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_property_flag(prop, PROP_REQUIRED);
+ prop = RNA_def_boolean(func, "supported", 0, "Supported", "");
+ RNA_def_function_return(func, prop);
+
RNA_define_verify_sdna(0);
prop = RNA_def_property(srna, "is_animation", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index a4e02d6e835..cc14e60f45a 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -29,6 +29,7 @@
#include <string.h>
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -95,14 +96,14 @@ EnumPropertyItem rigidbody_constraint_type_items[] = {
/* ******************************** */
-static void rna_RigidBodyWorld_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_RigidBodyWorld_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
BKE_rigidbody_cache_reset(rbw);
}
-static char *rna_RigidBodyWorld_path(PointerRNA *ptr)
+static char *rna_RigidBodyWorld_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("rigidbody_world");
}
@@ -135,14 +136,14 @@ static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value)
/* ******************************** */
-static void rna_RigidBodyOb_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_RigidBodyOb_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
RigidBodyWorld *rbw = scene->rigidbody_world;
BKE_rigidbody_cache_reset(rbw);
}
-static void rna_RigidBodyOb_shape_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_RigidBodyOb_shape_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
@@ -152,7 +153,7 @@ static void rna_RigidBodyOb_shape_reset(Main *bmain, Scene *scene, PointerRNA *p
rbo->flag |= RBO_FLAG_NEEDS_RESHAPE;
}
-static char *rna_RigidBodyOb_path(PointerRNA *ptr)
+static char *rna_RigidBodyOb_path(PointerRNA *UNUSED(ptr))
{
/* NOTE: this hardcoded path should work as long as only Objects have this */
return BLI_sprintfN("rigid_body");
@@ -166,6 +167,14 @@ static void rna_RigidBodyOb_type_set(PointerRNA *ptr, int value)
rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
}
+static void rna_RigidBodyOb_shape_set(PointerRNA *ptr, int value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->shape = value;
+ rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+}
+
static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value)
{
RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
@@ -334,7 +343,7 @@ static void rna_RigidBodyOb_angular_damping_set(PointerRNA *ptr, float value)
#endif
}
-static char *rna_RigidBodyCon_path(PointerRNA *ptr)
+static char *rna_RigidBodyCon_path(PointerRNA *UNUSED(ptr))
{
/* NOTE: this hardcoded path should work as long as only Objects have this */
return BLI_sprintfN("rigid_body_constraint");
@@ -595,13 +604,17 @@ static void rna_RigidBodyCon_motor_ang_target_velocity_set(PointerRNA *ptr, floa
}
/* Sweep test */
-static void rna_RigidBodyWorld_convex_sweep_test(RigidBodyWorld *rbw, ReportList *reports, Object *object, float ray_start[3], float ray_end[3], float r_location[3], float r_hitpoint[3], float r_normal[3], int *r_hit)
+static void rna_RigidBodyWorld_convex_sweep_test(
+ RigidBodyWorld *rbw, ReportList *reports,
+ Object *object, float ray_start[3], float ray_end[3],
+ float r_location[3], float r_hitpoint[3], float r_normal[3], int *r_hit)
{
#ifdef WITH_BULLET
RigidBodyOb *rob = object->rigidbody_object;
if (rbw->physics_world != NULL && rob->physics_object != NULL) {
- RB_world_convex_sweep_test(rbw->physics_world, rob->physics_object, ray_start, ray_end, r_location, r_hitpoint, r_normal, r_hit);
+ RB_world_convex_sweep_test(rbw->physics_world, rob->physics_object, ray_start, ray_end,
+ r_location, r_hitpoint, r_normal, r_hit);
if (*r_hit == -2) {
BKE_report(reports, RPT_ERROR,
"A non convex collision shape was passed to the function, use only convex collision shapes");
@@ -611,6 +624,9 @@ static void rna_RigidBodyWorld_convex_sweep_test(RigidBodyWorld *rbw, ReportList
*r_hit = -1;
BKE_report(reports, RPT_ERROR, "Rigidbody world was not properly initialized, need to step the simulation first");
}
+#else
+ (void)rbw, (void)reports, (void)object, (void)ray_start, (void)ray_end;
+ (void)r_location, (void)r_hitpoint, (void)r_normal, (void)r_hit;
#endif
}
@@ -763,6 +779,7 @@ static void rna_def_rigidbody_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "collision_shape", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "shape");
RNA_def_property_enum_items(prop, rigidbody_object_shape_items);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyOb_shape_set", NULL);
RNA_def_property_ui_text(prop, "Collision Shape", "Collision Shape of object in Rigid Body Simulations");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 67fc3056485..380bde90ff9 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -566,6 +566,12 @@ static int rna_Property_is_required_get(PointerRNA *ptr)
return prop->flag & PROP_REQUIRED ? 1 : 0;
}
+static int rna_Property_is_argument_optional_get(PointerRNA *ptr)
+{
+ PropertyRNA *prop = (PropertyRNA *)ptr->data;
+ return prop->flag & PROP_PYFUNC_OPTIONAL ? 1 : 0;
+}
+
static int rna_Property_is_never_none_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
@@ -1171,6 +1177,12 @@ static void rna_def_property(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_Property_is_required_get", NULL);
RNA_def_property_ui_text(prop, "Required", "False when this property is an optional argument in an RNA function");
+ prop = RNA_def_property(srna, "is_argument_optional", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Property_is_argument_optional_get", NULL);
+ RNA_def_property_ui_text(prop, "Optional Argument",
+ "True when the property is optional in a Python function implementing an RNA function");
+
prop = RNA_def_property(srna, "is_never_none", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Property_is_never_none_get", NULL);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 83dbd79024e..0cfb399c470 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -487,7 +487,11 @@ static void rna_Scene_view3d_update(Main *bmain, Scene *UNUSED(scene_unused), Po
static void rna_Scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Scene_view3d_update(bmain, scene, ptr);
- DAG_on_visible_update(bmain, FALSE);
+ /* XXX We would need do_time=true here, else we can have update issues like [#36289]...
+ * However, this has too much drawbacks (like slower layer switch, undesired updates...).
+ * That's TODO for future DAG updates.
+ */
+ DAG_on_visible_update(bmain, false);
}
static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
@@ -777,7 +781,7 @@ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value)
}
}
-static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *C, PointerRNA *ptr,
+static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), int *UNUSED(free))
{
ID *id = ptr->id.data;
@@ -789,7 +793,7 @@ static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *C,
}
}
-static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *C, PointerRNA *ptr,
+static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), int *free)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
@@ -834,7 +838,7 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *C, P
}
}
-static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *C, PointerRNA *ptr,
+static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), int *free)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
@@ -1028,7 +1032,8 @@ static void rna_RenderSettings_active_layer_index_set(PointerRNA *ptr, int value
rd->actlay = value;
}
-static void rna_RenderSettings_active_layer_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_RenderSettings_active_layer_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
RenderData *rd = (RenderData *)ptr->data;
@@ -1309,7 +1314,7 @@ static void rna_Scene_simplify_update(Main *bmain, Scene *UNUSED(scene), Pointer
rna_Scene_use_simplify_update(bmain, sce, ptr);
}
-static void rna_Scene_use_persistent_data_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *sce = ptr->id.data;
@@ -1458,13 +1463,13 @@ static void rna_UnifiedPaintSettings_unprojected_radius_set(PointerRNA *ptr, flo
ups->unprojected_radius = value;
}
-static void rna_UnifiedPaintSettings_radius_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_UnifiedPaintSettings_radius_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
/* changing the unified size should invalidate */
BKE_paint_invalidate_overlay_all();
}
-static char *rna_UnifiedPaintSettings_path(PointerRNA *ptr)
+static char *rna_UnifiedPaintSettings_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.unified_paint_settings");
}
@@ -1486,7 +1491,7 @@ static void rna_EditMesh_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *U
}
}
-static char *rna_MeshStatVis_path(PointerRNA *ptr)
+static char *rna_MeshStatVis_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.statvis");
}
@@ -1520,7 +1525,7 @@ static void rna_SceneSequencer_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
BKE_sequencer_preprocessed_cache_cleanup();
}
-static char *rna_ToolSettings_path(PointerRNA *ptr)
+static char *rna_ToolSettings_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings");
}
@@ -1536,7 +1541,8 @@ static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value
{
FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data;
- lineset->linestyle->id.us--;
+ if (lineset->linestyle)
+ lineset->linestyle->id.us--;
lineset->linestyle = (FreestyleLineStyle *)value.data;
lineset->linestyle->id.us++;
}
@@ -1549,7 +1555,7 @@ static PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr)
}
static void rna_FreestyleSettings_active_lineset_index_range(PointerRNA *ptr, int *min, int *max,
- int *softmin, int *softmax)
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
FreestyleConfig *config = (FreestyleConfig *)ptr->data;
@@ -2067,8 +2073,8 @@ static void rna_def_statvis(BlenderRNA *brna)
{SCE_STATVIS_OVERHANG, "OVERHANG", 0, "Overhang", ""},
{SCE_STATVIS_THICKNESS, "THICKNESS", 0, "Thickness", ""},
{SCE_STATVIS_INTERSECT, "INTERSECT", 0, "Intersect", ""},
- {SCE_STATVIS_DISTORT, "DISTORT", 0, "Distort", ""},
- {SCE_STATVIS_SHARP, "SHARP", 0, "Sharp", ""},
+ {SCE_STATVIS_DISTORT, "DISTORT", 0, "Distortion", ""},
+ {SCE_STATVIS_SHARP, "SHARP", 0, "Sharp", ""},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "MeshStatVis", NULL);
@@ -2690,202 +2696,202 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, "rna_FreestyleLineSet_linestyle_get",
"rna_FreestyleLineSet_linestyle_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Line Style", "Line style settings");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "Line Set Name", "Line set name");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
RNA_def_struct_name_property(srna, prop);
prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_LINESET_ENABLED);
RNA_def_property_ui_text(prop, "Render", "Enable or disable this line set during stroke rendering");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_by_visibility", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_VISIBILITY);
RNA_def_property_ui_text(prop, "Selection by Visibility", "Select feature edges based on visibility");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_by_edge_types", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_EDGE_TYPES);
RNA_def_property_ui_text(prop, "Selection by Edge Types", "Select feature edges based on edge types");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_by_group", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_GROUP);
RNA_def_property_ui_text(prop, "Selection by Group", "Select feature edges based on a group of objects");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_by_image_border", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_IMAGE_BORDER);
RNA_def_property_ui_text(prop, "Selection by Image Border",
"Select feature edges by image border (less memory consumption)");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_by_face_marks", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_FACE_MARK);
RNA_def_property_ui_text(prop, "Selection by Face Marks", "Select feature edges by face marks");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "edge_type_negation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
RNA_def_property_enum_items(prop, edge_type_negation_items);
RNA_def_property_ui_text(prop, "Edge Type Negation",
"Set the negation operation for conditions on feature edge types");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "edge_type_combination", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
RNA_def_property_enum_items(prop, edge_type_combination_items);
RNA_def_property_ui_text(prop, "Edge Type Combination",
"Set the combination operation for conditions on feature edge types");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "group");
RNA_def_property_struct_type(prop, "Group");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Group", "A group of objects based on which feature edges are selected");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "group_negation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
RNA_def_property_enum_items(prop, group_negation_items);
RNA_def_property_ui_text(prop, "Group Negation",
"Set the negation operation for conditions on feature edge types");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "face_mark_negation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
RNA_def_property_enum_items(prop, face_mark_negation_items);
RNA_def_property_ui_text(prop, "Face Mark Negation",
"Set the negation operation for the condition on face marks");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "face_mark_condition", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
RNA_def_property_enum_items(prop, face_mark_condition_items);
RNA_def_property_ui_text(prop, "Face Mark Condition", "Set a feature edge selection condition on face marks");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SILHOUETTE);
RNA_def_property_ui_text(prop, "Silhouette", "Select silhouette edges");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_border", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_BORDER);
RNA_def_property_ui_text(prop, "Border", "Select border edges");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_crease", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CREASE);
RNA_def_property_ui_text(prop, "Crease", "Select crease edges");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_ridge_valley", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_RIDGE_VALLEY);
RNA_def_property_ui_text(prop, "Ridge & Valley", "Select ridges and valleys");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_suggestive_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR);
RNA_def_property_ui_text(prop, "Suggestive Contour", "Select suggestive contours");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_material_boundary", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY);
RNA_def_property_ui_text(prop, "Material Boundary", "Select edges at material boundaries");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CONTOUR);
RNA_def_property_ui_text(prop, "Contour", "Select contours");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_external_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR);
RNA_def_property_ui_text(prop, "External Contour", "Select external contours");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "select_edge_mark", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EDGE_MARK);
RNA_def_property_ui_text(prop, "Edge Mark", "Select edge marks");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_silhouette", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SILHOUETTE);
RNA_def_property_ui_text(prop, "Silhouette", "Exclude silhouette edges");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_border", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_BORDER);
RNA_def_property_ui_text(prop, "Border", "Exclude border edges");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_crease", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CREASE);
RNA_def_property_ui_text(prop, "Crease", "Exclude crease edges");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_ridge_valley", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_RIDGE_VALLEY);
RNA_def_property_ui_text(prop, "Ridge & Valley", "Exclude ridges and valleys");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_suggestive_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR);
RNA_def_property_ui_text(prop, "Suggestive Contour", "Exclude suggestive contours");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_material_boundary", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY);
RNA_def_property_ui_text(prop, "Material Boundary", "Exclude edges at material boundaries");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CONTOUR);
RNA_def_property_ui_text(prop, "Contour", "Exclude contours");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_external_contour", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR);
RNA_def_property_ui_text(prop, "External Contour", "Exclude external contours");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "exclude_edge_mark", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EDGE_MARK);
RNA_def_property_ui_text(prop, "Edge Mark", "Exclude edge marks");
RNA_def_property_ui_icon(prop, ICON_X, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "visibility", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "qi");
RNA_def_property_enum_items(prop, visibility_items);
RNA_def_property_ui_text(prop, "Visibility", "Determine how to use visibility for feature edge selection");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "qi_start", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "qi_start");
RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop, "Start", "First QI value of the QI range");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "qi_end", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "qi_end");
RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop, "End", "Last QI value of the QI range");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* FreestyleModuleSettings */
@@ -2897,12 +2903,12 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Text");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Style Module", "Python script to define a style module");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "is_displayed", 1);
RNA_def_property_ui_text(prop, "Use", "Enable or disable this style module during stroke rendering");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* FreestyleSettings */
@@ -2920,62 +2926,62 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, freestyle_ui_mode_items);
RNA_def_property_ui_text(prop, "Control Mode", "Select the Freestyle control mode");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "raycasting_algorithm", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "raycasting_algorithm");
RNA_def_property_enum_items(prop, freestyle_raycasting_algorithm_items);
RNA_def_property_ui_text(prop, "Raycasting Algorithm", "Select the Freestyle raycasting algorithm");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_culling", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_CULLING);
RNA_def_property_ui_text(prop, "Culling", "If enabled, out-of-view edges are ignored");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_suggestive_contours", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_SUGGESTIVE_CONTOURS_FLAG);
RNA_def_property_ui_text(prop, "Suggestive Contours", "Enable suggestive contours");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_ridges_and_valleys", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_RIDGES_AND_VALLEYS_FLAG);
RNA_def_property_ui_text(prop, "Ridges and Valleys", "Enable ridges and valleys");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_material_boundaries", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_MATERIAL_BOUNDARIES_FLAG);
RNA_def_property_ui_text(prop, "Material Boundaries", "Enable material boundaries");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_smoothness", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_FACE_SMOOTHNESS_FLAG);
RNA_def_property_ui_text(prop, "Face Smoothness", "Take face smoothness into account in view map calculation");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_advanced_options", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_ADVANCED_OPTIONS_FLAG);
RNA_def_property_ui_text(prop, "Advanced Options",
"Enable advanced edge detection options (sphere radius and Kr derivative epsilon)");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sphere_radius");
RNA_def_property_range(prop, 0.0, 1000.0);
RNA_def_property_ui_text(prop, "Sphere Radius", "Sphere radius for computing curvatures");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "kr_derivative_epsilon", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "dkr_epsilon");
RNA_def_property_range(prop, -1000.0, 1000.0);
RNA_def_property_ui_text(prop, "Kr Derivative Epsilon", "Kr derivative epsilon for computing suggestive contours");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "crease_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "crease_angle");
RNA_def_property_range(prop, 0.0, DEG2RAD(180.0));
RNA_def_property_ui_text(prop, "Crease Angle", "Angular threshold for detecting crease edges");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "linesets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "linesets", NULL);
@@ -4190,12 +4196,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "tilex");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 8, 65536);
RNA_def_property_ui_text(prop, "Tile X", "Horizontal tile size to use while rendering");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "tiley");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 8, 65536);
RNA_def_property_ui_text(prop, "Tile Y", "Vertical tile size to use while rendering");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 375b31e0586..ae6c5e71e6e 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -142,12 +142,12 @@ static void rna_Scene_collada_export(
int use_object_instantiation,
int sort_by_name,
int export_transformation_type,
- int second_life)
+ int open_sim)
{
collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected,
include_children, include_armatures, include_shapekeys, deform_bones_only,
active_uv_only, include_uv_textures, include_material_textures,
- use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, second_life);
+ use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, open_sim);
}
#endif
@@ -218,7 +218,7 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export");
parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data");
parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
- parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life");
+ parm = RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds");
parm = RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
"Transformation", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index f9171887bfb..b8269c428a1 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -94,7 +94,7 @@ static void rna_Screen_redraw_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
}
-static int rna_Screen_is_animation_playing_get(PointerRNA *ptr)
+static int rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr))
{
return (ED_screen_animation_playing(G.main->wm.first) != NULL);
}
@@ -213,6 +213,7 @@ static void rna_def_area(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "spacetype");
RNA_def_property_enum_items(prop, space_type_items);
+ RNA_def_property_enum_default(prop, SPACE_VIEW3D);
RNA_def_property_enum_funcs(prop, NULL, "rna_Area_type_set", "rna_Area_type_itemf");
RNA_def_property_ui_text(prop, "Editor Type", "Current editor type for this area");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 11b3f94a446..89714e49ebf 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -190,7 +190,7 @@ static int rna_ParticleEdit_hair_get(PointerRNA *ptr)
return 0;
}
-static char *rna_ParticleEdit_path(PointerRNA *ptr)
+static char *rna_ParticleEdit_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.particle_edit");
}
@@ -247,7 +247,7 @@ static void rna_Sculpt_ShowDiffuseColor_update(Main *UNUSED(bmain), Scene *scene
}
}
-static char *rna_Sculpt_path(PointerRNA *ptr)
+static char *rna_Sculpt_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.sculpt");
}
@@ -264,17 +264,17 @@ static char *rna_VertexPaint_path(PointerRNA *ptr)
}
}
-static char *rna_ImagePaintSettings_path(PointerRNA *ptr)
+static char *rna_ImagePaintSettings_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.image_paint");
}
-static char *rna_UvSculpt_path(PointerRNA *ptr)
+static char *rna_UvSculpt_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.uv_sculpt");
}
-static char *rna_ParticleBrush_path(PointerRNA *ptr)
+static char *rna_ParticleBrush_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("tool_settings.particle_edit.brush");
}
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index 278dc074c50..71546c7fad4 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -43,7 +43,7 @@
#include "WM_types.h"
/* Always keep in alphabetical order */
-EnumPropertyItem sensor_type_items[] = {
+static EnumPropertyItem sensor_type_items[] = {
{SENS_ACTUATOR, "ACTUATOR", 0, "Actuator", ""},
{SENS_ALWAYS, "ALWAYS", 0, "Always", ""},
{SENS_ARMATURE, "ARMATURE", 0, "Armature", ""},
@@ -58,7 +58,6 @@ EnumPropertyItem sensor_type_items[] = {
{SENS_RADAR, "RADAR", 0, "Radar", ""},
{SENS_RANDOM, "RANDOM", 0, "Random", ""},
{SENS_RAY, "RAY", 0, "Ray", ""},
- {SENS_TOUCH, "TOUCH", 0, "Touch", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -74,8 +73,6 @@ static StructRNA *rna_Sensor_refine(struct PointerRNA *ptr)
switch (sensor->type) {
case SENS_ALWAYS:
return &RNA_AlwaysSensor;
- case SENS_TOUCH:
- return &RNA_TouchSensor;
case SENS_NEAR:
return &RNA_NearSensor;
case SENS_KEYBOARD:
@@ -267,15 +264,6 @@ static void rna_Sensor_Armature_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
posechannel[0] = 0;
constraint[0] = 0;
}
-
-/* note: the following set functions exists only to avoid id refcounting */
-static void rna_Sensor_touch_material_set(PointerRNA *ptr, PointerRNA value)
-{
- bSensor *sens = (bSensor *)ptr->data;
- bTouchSensor *ts = (bTouchSensor *) sens->data;
-
- ts->ma = value.data;
-}
#else
static void rna_def_sensor(BlenderRNA *brna)
@@ -427,25 +415,6 @@ static void rna_def_mouse_sensor(BlenderRNA *brna)
RNA_def_property_update(prop, NC_LOGIC, NULL);
}
-static void rna_def_touch_sensor(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "TouchSensor", "Sensor");
- RNA_def_struct_ui_text(srna, "Touch Sensor", "Sensor to detect objects colliding with the current object");
- RNA_def_struct_sdna_from(srna, "bTouchSensor", "data");
-
- prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Material");
- RNA_def_property_pointer_sdna(prop, NULL, "ma");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Material", "Only look for objects with this material (blank = all objects)");
- /* note: custom set function is ONLY to avoid rna setting a user for this. */
- RNA_def_property_pointer_funcs(prop, NULL, "rna_Sensor_touch_material_set", NULL, NULL);
- RNA_def_property_update(prop, NC_LOGIC, NULL);
-}
-
static void rna_def_keyboard_sensor(BlenderRNA *brna)
{
StructRNA *srna;
@@ -917,7 +886,6 @@ void RNA_def_sensor(BlenderRNA *brna)
rna_def_always_sensor(brna);
rna_def_near_sensor(brna);
rna_def_mouse_sensor(brna);
- rna_def_touch_sensor(brna);
rna_def_keyboard_sensor(brna);
rna_def_property_sensor(brna);
rna_def_armature_sensor(brna);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 650453ebc69..342d94c7667 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -93,6 +93,23 @@ static void meta_tmp_ref(Sequence *seq_par, Sequence *seq)
}
}
+static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Scene *scene = (Scene *) ptr->id.data;
+ Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+
+ if (ed) {
+ StripElem *se = (StripElem *)ptr->data;
+ Sequence *seq;
+
+ /* slow but we can't avoid! */
+ seq = BKE_sequencer_from_elem(&ed->seqbase, se);
+ if (seq) {
+ BKE_sequence_invalidate_cache(scene, seq);
+ }
+ }
+}
+
static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *) ptr->id.data;
@@ -703,7 +720,7 @@ static Sequence *sequence_get_by_proxy(Editing *ed, StripProxy *proxy)
return data.seq;
}
-static void rna_Sequence_tcindex_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Sequence_tcindex_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
@@ -1063,7 +1080,7 @@ static void rna_def_strip_element(BlenderRNA *brna)
prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "Filename", "");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceElement_update");
prop = RNA_def_property(srna, "orig_width", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "orig_width");
@@ -1281,7 +1298,7 @@ static void rna_def_strip_color_balance(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "StripColorBalance");
}
-EnumPropertyItem blend_mode_items[] = {
+static EnumPropertyItem blend_mode_items[] = {
{SEQ_BLEND_REPLACE, "REPLACE", 0, "Replace", ""},
{SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""},
{SEQ_TYPE_ADD, "ADD", 0, "Add", ""},
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 8b01a785f1e..ba90e3b1e4a 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -65,7 +65,7 @@ static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *p
DAG_relations_tag_update(bmain);
}
-static void rna_Smoke_resetCache(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
if (settings->smd && settings->smd->domain)
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index f7a0d865274..d494d6ae1cb 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -109,13 +109,15 @@ static EnumPropertyItem transform_orientation_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem autosnap_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem autosnap_items[] = {
{SACTSNAP_OFF, "NONE", 0, "No Auto-Snap", ""},
{SACTSNAP_STEP, "STEP", 0, "Time Step", "Snap to 1.0 frame/second intervals"},
{SACTSNAP_FRAME, "FRAME", 0, "Nearest Frame", "Snap to actual frames/seconds (nla-action time)"},
{SACTSNAP_MARKER, "MARKER", 0, "Nearest Marker", "Snap to nearest marker"},
{0, NULL, 0, NULL, NULL}
};
+#endif
EnumPropertyItem viewport_shade_items[] = {
{OB_BOUNDBOX, "BOUNDBOX", ICON_BBOX, "Bounding Box", "Display the object's local bounding boxes only"},
@@ -172,6 +174,7 @@ static EnumPropertyItem buttons_texture_context_items[] = {
#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
#include "BLI_math.h"
@@ -197,6 +200,9 @@ static EnumPropertyItem buttons_texture_context_items[] = {
#include "IMB_imbuf_types.h"
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
static StructRNA *rna_Space_refine(struct PointerRNA *ptr)
{
SpaceLink *space = (SpaceLink *)ptr->data;
@@ -400,23 +406,12 @@ static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), Poin
DAG_on_visible_update(bmain, FALSE);
}
-static void rna_SpaceView3D_viewport_shade_update(Main *UNUSED(bmain), Scene *UNUSED(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);
- if (v3d->drawtype != OB_RENDER) {
- ARegion *ar;
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d && rv3d->render_engine) {
- RE_engine_free(rv3d->render_engine);
- rv3d->render_engine = NULL;
- }
- }
- }
+ ED_view3d_shade_update(bmain, v3d, sa);
}
static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -622,7 +617,7 @@ static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_SpaceUVEditor, ptr->data);
}
-static void rna_SpaceImageEditor_mode_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_SpaceImageEditor_mode_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
ED_space_image_paint_update(bmain->wm.first, scene->toolsettings);
}
@@ -850,8 +845,8 @@ static void rna_SpaceProperties_context_set(PointerRNA *ptr, int value)
sbuts->mainbuser = value;
}
-static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *C, PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), int *free)
{
SpaceButs *sbuts = (SpaceButs *)(ptr->data);
EnumPropertyItem *item = NULL;
@@ -959,6 +954,14 @@ static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C,
return item;
}
+static void rna_SpaceProperties_texture_context_set(PointerRNA *ptr, int value)
+{
+ SpaceButs *sbuts = (SpaceButs *)(ptr->data);
+
+ /* User action, no need to keep "better" value in prev here! */
+ sbuts->texture_context = sbuts->texture_context_prev = value;
+}
+
/* Space Console */
static void rna_ConsoleLine_body_get(PointerRNA *ptr, char *value)
{
@@ -989,7 +992,8 @@ static void rna_ConsoleLine_body_set(PointerRNA *ptr, const char *value)
ci->cursor = len;
}
-static void rna_ConsoleLine_cursor_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_ConsoleLine_cursor_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
ConsoleLine *ci = (ConsoleLine *)ptr->data;
@@ -1255,6 +1259,15 @@ static void rna_SpaceNodeEditor_show_backdrop_update(Main *UNUSED(bmain), Scene
WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
}
+static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode, bContext *C, int x, int y)
+{
+ ARegion *ar = CTX_wm_region(C);
+
+ UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]);
+ snode->cursor[0] /= UI_DPI_FAC;
+ snode->cursor[1] /= UI_DPI_FAC;
+}
+
static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, PointerRNA value)
{
SpaceClip *sc = (SpaceClip *)(ptr->data);
@@ -2194,7 +2207,8 @@ static void rna_def_space_buttons(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture_context", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, buttons_texture_context_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceProperties_texture_context_itemf");
+ RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_texture_context_set",
+ "rna_SpaceProperties_texture_context_itemf");
RNA_def_property_ui_text(prop, "Texture Context", "Type of texture data to display and edit");
RNA_def_property_update(prop, NC_TEXTURE, NULL);
@@ -2573,6 +2587,16 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Margin Column", "Column number to show right margin at");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
+ prop = RNA_def_property(srna, "top", PROP_INT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_sdna(prop, NULL, "top");
+ RNA_def_property_ui_text(prop, "Top Line", "Top line visible");
+
+ prop = RNA_def_property(srna, "visible_lines", PROP_INT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_sdna(prop, NULL, "viewlines");
+ RNA_def_property_ui_text(prop, "Top Line", "Amount of lines that can be visible in current editor");
+
/* functionality options */
prop = RNA_def_property(srna, "use_overwrite", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overwrite", 1);
@@ -3292,7 +3316,8 @@ static void rna_def_space_node_path_api(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_space_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
+ PropertyRNA *prop, *parm;
+ FunctionRNA *func;
static EnumPropertyItem texture_type_items[] = {
{SNODE_TEX_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Edit texture nodes from Object"},
@@ -3433,6 +3458,14 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "cursor");
RNA_def_property_ui_text(prop, "Cursor Location", "Location for adding new nodes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+
+ func = RNA_def_function(srna, "cursor_location_from_region", "rna_SpaceNodeEditor_cursor_location_from_region");
+ RNA_def_function_ui_description(func, "Set the cursor location using region coordinates");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "x", "Region x coordinate", -10000, 10000);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "y", 0, INT_MIN, INT_MAX, "y", "Region y coordinate", -10000, 10000);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
}
static void rna_def_space_logic(BlenderRNA *brna)
@@ -3525,6 +3558,7 @@ static void rna_def_space_clip(BlenderRNA *brna)
static EnumPropertyItem pivot_items[] = {
{V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
"Pivot around bounding box center of selected object(s)"},
+ {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", "Pivot around the 2D cursor"},
{V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
"Individual Origins", "Pivot around each object's own origin"},
{V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
diff --git a/source/blender/makesrna/intern/rna_test.c b/source/blender/makesrna/intern/rna_test.c
index 22b6f323647..cf0dc5e332d 100644
--- a/source/blender/makesrna/intern/rna_test.c
+++ b/source/blender/makesrna/intern/rna_test.c
@@ -34,6 +34,8 @@
#include "rna_internal.h"
+#ifdef RNA_RUNTIME
+
#define ARRAY_SIZE 3
#define DYNAMIC_ARRAY_SIZE 64
#define MARRAY_DIM [3][4][5]
@@ -43,8 +45,6 @@
#define DYNAMIC_MARRAY_DIM [3][4][5]
#define DYNAMIC_MARRAY_SIZE(type) (sizeof(type DYNAMIC_MARRAY_DIM) / sizeof(type))
-#ifdef RNA_RUNTIME
-
#ifdef UNIT_TEST
#define DEF_VARS(type, prefix) \
@@ -185,7 +185,8 @@ void RNA_def_test(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_DYNAMIC);
RNA_def_property_dynamic_array_funcs(prop, "rna_Test_bdmarr_get_length", "rna_Test_bdmarr_set_length");
RNA_def_property_boolean_funcs(prop, "rna_Test_bdmarr_get", "rna_Test_bdmarr_set");
-
+#else
+ (void)brna;
#endif
}
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index df6181af4b2..24695928679 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -81,6 +81,12 @@ static int rna_Text_modified_get(PointerRNA *ptr)
return text_file_modified(text);
}
+static int rna_Text_current_line_index_get(PointerRNA *ptr)
+{
+ Text *text = (Text *)ptr->data;
+ return BLI_findindex(&text->lines, text->curl);
+}
+
static void rna_TextLine_body_get(PointerRNA *ptr, char *value)
{
TextLine *line = (TextLine *)ptr->data;
@@ -141,6 +147,11 @@ static void rna_def_text(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Text", "Text datablock referencing an external or packed text file");
RNA_def_struct_ui_icon(srna, ICON_TEXT);
RNA_def_struct_clear_flag(srna, STRUCT_ID_REFCOUNT);
+
+ prop = RNA_def_property(srna, "current_line_index", PROP_INT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_Text_current_line_index_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Current Line Index", "Index of current TextLine in TextLine collection");
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_Text_filename_get", "rna_Text_filename_length", "rna_Text_filename_set");
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index be6defa11d7..a26272b34ce 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -51,13 +51,15 @@
#include "WM_api.h"
#include "WM_types.h"
-EnumPropertyItem texture_filter_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem texture_filter_items[] = {
{TXF_BOX, "BOX", 0, "Box", ""},
{TXF_EWA, "EWA", 0, "EWA", ""},
{TXF_FELINE, "FELINE", 0, "FELINE", ""},
{TXF_AREA, "AREA", 0, "Area", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
EnumPropertyItem texture_type_items[] = {
{0, "NONE", 0, "None", ""},
@@ -82,7 +84,8 @@ EnumPropertyItem texture_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem blend_type_items[] = {
+#ifndef RNA_RUNTIME
+static EnumPropertyItem blend_type_items[] = {
{MTEX_BLEND, "MIX", 0, "Mix", ""},
{MTEX_ADD, "ADD", 0, "Add", ""},
{MTEX_SUB, "SUBTRACT", 0, "Subtract", ""},
@@ -101,6 +104,7 @@ EnumPropertyItem blend_type_items[] = {
{MTEX_LIN_LIGHT, "LINEAR_LIGHT", 0, "Linear Light", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
#ifdef RNA_RUNTIME
@@ -180,7 +184,7 @@ static void rna_Texture_mapping_update(Main *bmain, Scene *scene, PointerRNA *pt
rna_Texture_update(bmain, scene, ptr);
}
-static void rna_Color_mapping_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Color_mapping_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
/* nothing to do */
}
@@ -362,7 +366,7 @@ static int rna_TextureSlot_output_node_get(PointerRNA *ptr)
}
-static EnumPropertyItem *rna_TextureSlot_output_node_itemf(bContext *C, PointerRNA *ptr,
+static EnumPropertyItem *rna_TextureSlot_output_node_itemf(bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), int *free)
{
MTex *mtex = ptr->data;
@@ -474,7 +478,7 @@ static char *rna_VoxelData_path(PointerRNA *UNUSED(ptr))
return BLI_sprintfN("voxel_data");
}
-static char *rna_OceanTex_path(PointerRNA *ptr)
+static char *rna_OceanTex_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("ocean");
}
@@ -491,6 +495,14 @@ static void rna_def_texmapping(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_vect_type_items[] = {
+ {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transform a texture by inverse mapping the texture coordinate"},
+ {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"},
+ {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"},
+ {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
static EnumPropertyItem prop_xyz_mapping_items[] = {
{0, "NONE", 0, "None", ""},
{1, "X", 0, "X", ""},
@@ -505,6 +517,12 @@ static void rna_def_texmapping(BlenderRNA *brna)
srna = RNA_def_struct(brna, "TexMapping", NULL);
RNA_def_struct_ui_text(srna, "Texture Mapping", "Texture coordinate mapping settings");
+ prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, prop_vect_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms");
+ RNA_def_property_update(prop, 0, "rna_Texture_mapping_update");
+
prop = RNA_def_property(srna, "translation", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "loc");
RNA_def_property_ui_text(prop, "Location", "");
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 4c47bbf93a6..2b3cf58d452 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -95,6 +95,13 @@ static void rna_trackingTracks_begin(CollectionPropertyIterator *iter, PointerRN
rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL);
}
+static void rna_trackingPlaneTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+
+ rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
+}
+
static void rna_trackingObjects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -117,7 +124,8 @@ static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value)
BKE_tracking_dopesheet_tag_update(&clip->tracking);
}
-static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -146,6 +154,27 @@ static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value)
clip->tracking.act_track = NULL;
}
+static PointerRNA rna_tracking_active_plane_track_get(PointerRNA *ptr)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
+
+ return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingPlaneTrack, act_plane_track);
+}
+
+static void rna_tracking_active_plane_track_set(PointerRNA *ptr, PointerRNA value)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *) value.data;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ int index = BLI_findindex(plane_tracks_base, plane_track);
+
+ if (index >= 0)
+ clip->tracking.act_plane_track = plane_track;
+ else
+ clip->tracking.act_plane_track = NULL;
+}
+
static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -197,6 +226,81 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, int value)
}
}
+static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value)
+{
+ MovieClip *clip = (MovieClip *) ptr->id.data;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingPlaneMarker *plane_marker = (MovieTrackingPlaneMarker *) ptr->data;
+ MovieTrackingObject *tracking_object;
+ bool found = false;
+ MovieTrackingPlaneTrack *plane_track = NULL;
+
+ for (tracking_object = tracking->objects.first;
+ tracking_object;
+ tracking_object = tracking_object->next)
+ {
+ ListBase *tracksbase = BKE_tracking_object_get_plane_tracks(tracking, tracking_object);
+
+ for (plane_track = tracksbase->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (plane_marker >= plane_track->markers && plane_marker < plane_track->markers + plane_track->markersnr) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ break;
+ }
+ }
+
+ if (found) {
+ MovieTrackingPlaneMarker new_plane_marker = *plane_marker;
+ new_plane_marker.framenr = value;
+
+ BKE_tracking_plane_marker_delete(plane_track, plane_marker->framenr);
+ BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker);
+ }
+}
+
+static char *rna_trackingPlaneTrack_path(PointerRNA *ptr)
+{
+ MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
+ char name_esc[sizeof(plane_track->name) * 2];
+ BLI_strescape(name_esc, plane_track->name, sizeof(name_esc));
+ return BLI_sprintfN("tracking.plane_tracks[\"%s\"]", name_esc);
+}
+
+static void rna_trackingPlaneTrack_name_set(PointerRNA *ptr, const char *value)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
+ ListBase *plane_tracks_base = &tracking->plane_tracks;
+
+ BLI_strncpy(plane_track->name, value, sizeof(plane_track->name));
+
+ /* TODO: it's a bit difficult to find list track came from knowing just
+ * movie clip ID and MovieTracking structure, so keep this naive
+ * search for a while */
+ if (BLI_findindex(plane_tracks_base, plane_track) < 0) {
+ MovieTrackingObject *object = tracking->objects.first;
+
+ while (object) {
+ if (BLI_findindex(&object->plane_tracks, plane_track)) {
+ plane_tracks_base = &object->plane_tracks;
+ break;
+ }
+
+ object = object->next;
+ }
+ }
+
+ BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
+}
+
static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("tracking.camera");
@@ -259,7 +363,8 @@ static void rna_tracking_stabTracks_active_index_set(PointerRNA *ptr, int value)
clip->tracking.stabilization.act_track = value;
}
-static void rna_tracking_stabTracks_active_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+static void rna_tracking_stabTracks_active_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
{
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -294,6 +399,20 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po
}
}
+static void rna_trackingObject_plane_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
+
+ if (object->flag & TRACKING_OBJECT_CAMERA) {
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+
+ rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
+ }
+ else {
+ rna_iterator_listbase_begin(iter, &object->plane_tracks, NULL);
+ }
+}
+
static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr)
{
MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
@@ -348,19 +467,33 @@ static void rna_trackingMarker_frame_set(PointerRNA *ptr, int value)
{
MovieClip *clip = (MovieClip *) ptr->id.data;
MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *track;
MovieTrackingMarker *marker = (MovieTrackingMarker *) ptr->data;
+ MovieTrackingObject *tracking_object;
+ bool found = false;
+ MovieTrackingTrack *track = NULL;
+
+ for (tracking_object = tracking->objects.first;
+ tracking_object;
+ tracking_object = tracking_object->next)
+ {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+
+ for (track = tracksbase->first;
+ track;
+ track = track->next)
+ {
+ if (marker >= track->markers && marker < track->markers + track->markersnr) {
+ found = true;
+ break;
+ }
+ }
- track = tracking->tracks.first;
- while (track) {
- if (marker >= track->markers && marker < track->markers + track->markersnr) {
+ if (found) {
break;
}
-
- track = track->next;
}
- if (track) {
+ if (found) {
MovieTrackingMarker new_marker = *marker;
new_marker.framenr = value;
@@ -394,7 +527,7 @@ static void rna_tracking_markerPattern_boundbox_get(PointerRNA *ptr, float *valu
copy_v2_v2(values + 2, max);
}
-static void rna_trackingDopesheet_tagUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_trackingDopesheet_tagUpdate(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingDopesheet *dopesheet = &clip->tracking.dopesheet;
@@ -404,7 +537,8 @@ static void rna_trackingDopesheet_tagUpdate(Main *UNUSED(bmain), Scene *scene, P
/* API */
-static MovieTrackingTrack *add_track_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, const char *name, int frame)
+static MovieTrackingTrack *add_track_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase,
+ const char *name, int frame)
{
int width, height;
MovieClipUser user = {0};
@@ -515,6 +649,44 @@ static void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int fram
WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL);
}
+static MovieTrackingPlaneMarker *rna_trackingPlaneMarkers_find_frame(MovieTrackingPlaneTrack *plane_track, int framenr, int exact)
+{
+ if (exact)
+ return BKE_tracking_plane_marker_get_exact(plane_track, framenr);
+ else
+ return BKE_tracking_plane_marker_get(plane_track, framenr);
+}
+
+static MovieTrackingPlaneMarker *rna_trackingPlaneMarkers_insert_frame(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+ MovieTrackingPlaneMarker plane_marker, *new_plane_marker;
+
+ memset(&plane_marker, 0, sizeof(plane_marker));
+ plane_marker.framenr = framenr;
+
+ /* a bit arbitrary, but better than creating zero markers */
+ copy_v2_v2(plane_marker.corners[0], plane_track->markers[0].corners[0]);
+ copy_v2_v2(plane_marker.corners[1], plane_track->markers[0].corners[1]);
+ copy_v2_v2(plane_marker.corners[2], plane_track->markers[0].corners[2]);
+ copy_v2_v2(plane_marker.corners[3], plane_track->markers[0].corners[3]);
+
+ new_plane_marker = BKE_tracking_plane_marker_insert(plane_track, &plane_marker);
+
+ WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL);
+
+ return new_plane_marker;
+}
+
+static void rna_trackingPlaneMarkers_delete_frame(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+ if (plane_track->markersnr == 1)
+ return;
+
+ BKE_tracking_plane_marker_delete(plane_track, framenr);
+
+ WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL);
+}
+
#else
static EnumPropertyItem tracker_motion_model[] = {
@@ -891,7 +1063,7 @@ static void rna_def_trackingMarker(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "framenr");
RNA_def_property_ui_text(prop, "Frame", "Frame number marker is keyframed on");
RNA_def_property_int_funcs(prop, NULL, "rna_trackingMarker_frame_set", NULL);
- RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, 0);
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
/* enable */
prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
@@ -960,11 +1132,11 @@ static void rna_def_trackingMarkers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "insert_frame", "rna_trackingMarkers_insert_frame");
- RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip");
+ RNA_def_function_ui_description(func, "Insert a new marker at the specified frame");
parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame",
"Frame number to insert marker to", MINFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_float_vector(func, "co", 2, 0, -1.0, 1.0, "Coordinate",
+ RNA_def_float_vector(func, "co", 2, NULL, -1.0, 1.0, "Coordinate",
"Place new marker at the given frame using specified in normalized space coordinates",
-1.0, 1.0);
RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -1188,6 +1360,116 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
}
+static void rna_def_trackingPlaneMarker(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneMarker", NULL);
+ RNA_def_struct_ui_text(srna, "Movie Tracking Plane Marker Data", "Match-moving plane marker data for tracking");
+
+ /* frame */
+ prop = RNA_def_property(srna, "frame", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "framenr");
+ RNA_def_property_ui_text(prop, "Frame", "Frame number marker is keyframed on");
+ RNA_def_property_int_funcs(prop, NULL, "rna_trackingPlaneMarker_frame_set", NULL);
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+
+ /* Corners */
+ prop = RNA_def_property(srna, "corners", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "corners");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x2);
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_ui_text(prop, "Corners",
+ "Array of coordinates which represents UI rectangle corners in "
+ "frame normalized coordinates");
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+
+ /* enable */
+ prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", PLANE_MARKER_DISABLED);
+ RNA_def_property_ui_text(prop, "Mode", "Is marker muted for current frame");
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+}
+
+static void rna_def_trackingPlaneMarkers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "MovieTrackingPlaneMarkers");
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneMarkers", NULL);
+ RNA_def_struct_sdna(srna, "MovieTrackingPlaneTrack");
+ RNA_def_struct_ui_text(srna, "Movie Tracking Plane Markers",
+ "Collection of markers for movie tracking plane track");
+
+ func = RNA_def_function(srna, "find_frame", "rna_trackingPlaneMarkers_find_frame");
+ RNA_def_function_ui_description(func, "Get plane marker for specified frame");
+ parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame",
+ "Frame number to find marker for", MINFRAME, MAXFRAME);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "exact", TRUE, "Exact",
+ "Get plane marker at exact frame number rather than get estimated marker");
+ parm = RNA_def_pointer(func, "plane_marker", "MovieTrackingPlaneMarker", "", "Plane marker for specified frame");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "insert_frame", "rna_trackingPlaneMarkers_insert_frame");
+ RNA_def_function_ui_description(func, "Insert a new plane marker at the specified frame");
+ parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame",
+ "Frame number to insert marker to", MINFRAME, MAXFRAME);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "plane_marker", "MovieTrackingPlaneMarker", "", "Newly created plane marker");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "delete_frame", "rna_trackingPlaneMarkers_delete_frame");
+ RNA_def_function_ui_description(func, "Delete plane marker at specified frame");
+ parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame",
+ "Frame number to delete plane marker from", MINFRAME, MAXFRAME);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+}
+
+static void rna_def_trackingPlaneTrack(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ rna_def_trackingPlaneMarker(brna);
+
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneTrack", NULL);
+ RNA_def_struct_path_func(srna, "rna_trackingPlaneTrack_path");
+ RNA_def_struct_ui_text(srna, "Movie tracking plane track data", "Match-moving plane track data for tracking");
+ RNA_def_struct_ui_icon(srna, ICON_ANIM_DATA);
+
+ /* name */
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Unique name of track");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_trackingPlaneTrack_name_set");
+ RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2);
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ /* markers */
+ prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneMarker");
+ RNA_def_property_collection_sdna(prop, NULL, "markers", "markersnr");
+ RNA_def_property_ui_text(prop, "Markers", "Collection of markers in track");
+ rna_def_trackingPlaneMarkers(brna, prop);
+
+ /* select */
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
+ RNA_def_property_ui_text(prop, "Select", "Plane track is selected");
+ RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
+
+ /* auto keyframing */
+ prop = RNA_def_property(srna, "use_auto_keying", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", PLANE_TRACK_AUTOKEY);
+ RNA_def_property_ui_text(prop, "Auto Keyframe", "Automatic keyframe insertion when moving plane corners");
+ RNA_def_property_ui_icon(prop, ICON_REC, 0);
+}
+
static void rna_def_trackingStabilization(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1373,6 +1655,26 @@ static void rna_def_trackingTracks(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
}
+static void rna_def_trackingPlaneTracks(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneTracks", NULL);
+ RNA_def_struct_sdna(srna, "MovieTracking");
+ RNA_def_struct_ui_text(srna, "Movie Plane Tracks", "Collection of movie tracking plane tracks");
+
+ /* TODO(sergey): Add API to create new plane tracks */
+
+ /* active plane track */
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+ RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set",
+ NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Plane Track", "Active plane track in this tracking data object");
+}
+
static void rna_def_trackingObjectTracks(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1400,6 +1702,24 @@ static void rna_def_trackingObjectTracks(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
}
+static void rna_def_trackingObjectPlaneTracks(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MovieTrackingObjectPlaneTracks", NULL);
+ RNA_def_struct_sdna(srna, "MovieTrackingObject");
+ RNA_def_struct_ui_text(srna, "Plane Tracks", "Collection of tracking plane tracks");
+
+ /* active track */
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MovieTrackingTrack");
+ RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set",
+ NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
+}
+
static void rna_def_trackingObject(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1432,6 +1752,15 @@ static void rna_def_trackingObject(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
RNA_def_property_srna(prop, "MovieTrackingObjectTracks");
+ /* plane tracks */
+ prop = RNA_def_property(srna, "plane_tracks", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop, "rna_trackingObject_plane_tracks_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+ NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+ RNA_def_property_ui_text(prop, "Plane Tracks", "Collection of plane tracks in this tracking data object");
+ RNA_def_property_srna(prop, "MovieTrackingObjectPlaneTracks");
+
/* reconstruction */
prop = RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MovieTrackingReconstruction");
@@ -1549,8 +1878,11 @@ static void rna_def_tracking(BlenderRNA *brna)
rna_def_trackingSettings(brna);
rna_def_trackingCamera(brna);
rna_def_trackingTrack(brna);
+ rna_def_trackingPlaneTrack(brna);
rna_def_trackingTracks(brna);
+ rna_def_trackingPlaneTracks(brna);
rna_def_trackingObjectTracks(brna);
+ rna_def_trackingObjectPlaneTracks(brna);
rna_def_trackingStabilization(brna);
rna_def_trackingReconstruction(brna);
rna_def_trackingObject(brna);
@@ -1577,6 +1909,15 @@ static void rna_def_tracking(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
RNA_def_property_srna(prop, "MovieTrackingTracks");
+ /* tracks */
+ prop = RNA_def_property(srna, "plane_tracks", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop, "rna_trackingPlaneTracks_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+ NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+ RNA_def_property_ui_text(prop, "Plane Tracks", "Collection of plane tracks in this tracking data object");
+ RNA_def_property_srna(prop, "MovieTrackingPlaneTracks");
+
/* stabilization */
prop = RNA_def_property(srna, "stabilization", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MovieTrackingStabilization");
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 9efe3d9f1d6..39f305f7d47 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -31,6 +31,8 @@
#include "BLF_translation.h"
+#include "BKE_idprop.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
@@ -58,12 +60,9 @@ EnumPropertyItem operator_context_items[] = {
};
EnumPropertyItem uilist_layout_type_items[] = {
- {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout",
- "Use the default, multi-rows layout"},
- {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout",
- "Use the compact, single-row layout"},
- {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout",
- "Use the grid-based layout"},
+ {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout", "Use the default, multi-rows layout"},
+ {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout", "Use the compact, single-row layout"},
+ {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout", "Use the grid-based layout"},
{0, NULL, 0, NULL, NULL}
};
@@ -167,7 +166,7 @@ static void panel_draw_header(const bContext *C, Panel *pnl)
RNA_parameter_list_free(&list);
}
-static void rna_Panel_unregister(Main *bmain, StructRNA *type)
+static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
{
ARegionType *art;
PanelType *pt = RNA_struct_blender_type_get(type);
@@ -269,8 +268,24 @@ static StructRNA *rna_Panel_refine(PointerRNA *ptr)
}
/* UIList */
+static unsigned int rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA *UNUSED(ptr))
+{
+ return UILST_FLT_ITEM;
+}
+
+static IDProperty *rna_UIList_idprops(PointerRNA *ptr, bool create)
+{
+ uiList *ui_list = (uiList *)ptr->data;
+ if (create && !ui_list->properties) {
+ IDPropertyTemplate val = {0};
+ ui_list->properties = IDP_New(IDP_GROUP, &val, "RNA_UIList IDproperties group");
+ }
+
+ return ui_list->properties;
+}
+
static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
- int icon, PointerRNA *active_dataptr, const char *active_propname, int index)
+ int icon, PointerRNA *active_dataptr, const char *active_propname, int index, int flt_flag)
{
extern FunctionRNA rna_UIList_draw_item_func;
@@ -290,11 +305,139 @@ static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, Poi
RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
RNA_parameter_set_lookup(&list, "active_property", &active_propname);
RNA_parameter_set_lookup(&list, "index", &index);
+ RNA_parameter_set_lookup(&list, "flt_flag", &flt_flag);
+ ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void uilist_draw_filter(uiList *ui_list, bContext *C, uiLayout *layout)
+{
+ extern FunctionRNA rna_UIList_draw_filter_func;
+
+ PointerRNA ul_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
+ func = &rna_UIList_draw_filter_func; /* RNA_struct_find_function(&ul_ptr, "draw_filter"); */
+
+ RNA_parameter_list_create(&list, &ul_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
RNA_parameter_list_free(&list);
}
+static void uilist_filter_items(uiList *ui_list, bContext *C, PointerRNA *dataptr, const char *propname)
+{
+ extern FunctionRNA rna_UIList_filter_items_func;
+
+ PointerRNA ul_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ uiListDyn *flt_data = ui_list->dyn_data;
+ int *filter_flags, *filter_neworder;
+ void *ret1, *ret2;
+ int ret_len;
+ int len = flt_data->items_len = RNA_collection_length(dataptr, propname);
+
+ RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
+ func = &rna_UIList_filter_items_func; /* RNA_struct_find_function(&ul_ptr, "filter_items"); */
+
+ RNA_parameter_list_create(&list, &ul_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "data", dataptr);
+ RNA_parameter_set_lookup(&list, "property", &propname);
+
+ ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
+
+ parm = RNA_function_find_parameter(NULL, func, "filter_flags");
+ ret_len = RNA_parameter_dynamic_length_get(&list, parm);
+ if (ret_len != len && ret_len != 0) {
+ printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", AT,
+ RNA_parameter_dynamic_length_get(&list, parm), "filter_flags", len);
+ RNA_parameter_list_free(&list);
+ return;
+ }
+ RNA_parameter_get(&list, parm, &ret1);
+ filter_flags = (int *)ret1;
+
+ parm = RNA_function_find_parameter(NULL, func, "filter_neworder");
+ ret_len = RNA_parameter_dynamic_length_get(&list, parm);
+ if (ret_len != len && ret_len != 0) {
+ printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", AT,
+ RNA_parameter_dynamic_length_get(&list, parm), "filter_neworder", len);
+ RNA_parameter_list_free(&list);
+ return;
+ }
+ RNA_parameter_get(&list, parm, &ret2);
+ filter_neworder = (int *)ret2;
+
+ /* We have to do some final checks and transforms... */
+ {
+ int i, filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
+ if (filter_flags) {
+ flt_data->items_filter_flags = MEM_mallocN(sizeof(int) * len, AT);
+ memcpy(flt_data->items_filter_flags, filter_flags, sizeof(int) * len);
+
+ if (filter_neworder) {
+ /* For sake of simplicity, py filtering is expected to filter all items, but we actually only want
+ * reordering data for shown items!
+ */
+ int items_shown, shown_idx;
+ int t_idx, t_ni, prev_ni;
+ flt_data->items_shown = 0;
+ for (i = 0, shown_idx = 0; i < len; i++) {
+ if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) {
+ filter_neworder[shown_idx++] = filter_neworder[i];
+ }
+ }
+ items_shown = flt_data->items_shown = shown_idx;
+ flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * items_shown, AT);
+ /* And now, bring back new indices into the [0, items_shown[ range!
+ * XXX This is O(N²)... :/
+ */
+ for (shown_idx = 0, prev_ni = -1; shown_idx < items_shown; shown_idx++) {
+ for (i = 0, t_ni = len, t_idx = -1; i < items_shown; i++) {
+ int ni = filter_neworder[i];
+ if (ni > prev_ni && ni < t_ni) {
+ t_idx = i;
+ t_ni = ni;
+ }
+ }
+ if (t_idx >= 0) {
+ prev_ni = t_ni;
+ flt_data->items_filter_neworder[t_idx] = shown_idx;
+ }
+ }
+ }
+ else {
+ /* we still have to set flt_data->items_shown... */
+ flt_data->items_shown = 0;
+ for (i = 0; i < len; i++) {
+ if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) {
+ flt_data->items_shown++;
+ }
+ }
+ }
+ }
+ else {
+ flt_data->items_shown = len;
+
+ if (filter_neworder) {
+ flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * len, AT);
+ memcpy(flt_data->items_filter_neworder, filter_neworder, sizeof(int) * len);
+ }
+ }
+ }
+
+ RNA_parameter_list_free(&list);
+}
+
static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
{
uiListType *ult = RNA_struct_blender_type_get(type);
@@ -318,7 +461,7 @@ static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *da
uiListType *ult, dummyult = {NULL};
uiList dummyuilist = {NULL};
PointerRNA dummyul_ptr;
- int have_function[1];
+ int have_function[3];
size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
/* setup dummy menu & menu type to store static properties in */
@@ -349,9 +492,10 @@ static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *da
ult->ext.call = call;
ult->ext.free = free;
RNA_struct_blender_type_set(ult->ext.srna, ult);
- RNA_def_struct_flag(ult->ext.srna, STRUCT_NO_IDPROPERTIES);
ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL;
+ ult->draw_filter = (have_function[1]) ? uilist_draw_filter : NULL;
+ ult->filter_items = (have_function[2]) ? uilist_filter_items : NULL;
WM_uilisttype_add(ult);
@@ -874,8 +1018,46 @@ static void rna_def_uilist(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "uiList");
RNA_def_struct_refine_func(srna, "rna_UIList_refine");
RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_UIList_idprops");
- /* draw */
+ /* Registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->idname");
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name",
+ "If this is set, the uilist gets a custom ID, otherwise it takes the "
+ "name of the class used to define the uilist (for example, if the "
+ "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
+ "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+
+ /* Data */
+ prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, uilist_layout_type_items);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ /* Filter options */
+ prop = RNA_def_property(srna, "use_filter_show", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_SHOW);
+ RNA_def_property_ui_text(prop, "Show Filter", "Show filtering options");
+
+ prop = RNA_def_property(srna, "filter_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "filter_byname");
+ RNA_def_property_ui_text(prop, "Filter by Name", "Only show items matching this name (use '*' as wildcard)");
+
+ prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_EXCLUDE);
+ RNA_def_property_ui_text(prop, "Invert", "Invert filtering (show hidden items, and vice-versa)");
+
+ prop = RNA_def_property(srna, "use_filter_sort_alpha", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_ALPHA);
+ RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
+ RNA_def_property_ui_text(prop, "Sort by Name", "Sort items by their name");
+
+ prop = RNA_def_property(srna, "use_filter_sort_reverse", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_REVERSE);
+ RNA_def_property_ui_text(prop, "Invert", "Invert the order of shown items");
+
+ /* draw_item */
func = RNA_def_function(srna, "draw_item", NULL);
RNA_def_function_ui_description(func, "Draw an item in the list (NOTE: when you define your own draw_item "
"function, you may want to check given 'item' is of the right type...)");
@@ -897,21 +1079,52 @@ static void rna_def_uilist(BlenderRNA *brna)
"Identifier of property in active_data, for the active element");
RNA_def_property_flag(parm, PROP_REQUIRED);
RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_PYFUNC_OPTIONAL);
+ prop = RNA_def_property(func, "flt_flag", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(prop, "", "The filter-flag result for this item");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_PYFUNC_OPTIONAL);
+
+ /* draw_filter */
+ func = RNA_def_function(srna, "draw_filter", NULL);
+ RNA_def_function_ui_description(func, "Draw filtering options");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, uilist_layout_type_items);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ /* filter */
+ func = RNA_def_function(srna, "filter_items", NULL);
+ RNA_def_function_ui_description(func, "Filter and/or re-order items of the collection (output filter results in "
+ "filter_flags, and reorder results in filter_neworder arrays)");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+ parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data, for the collection");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ prop = RNA_def_property(func, "filter_flags", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_DYNAMIC);
+ RNA_def_property_array(prop, 1); /* XXX Dummy value, default 0 does not work */
+ RNA_def_property_ui_text(prop, "", "An array of filter flags, one for each item in the collection (NOTE: "
+ "FILTER_ITEM bit is reserved, it defines whether the item is shown or not)");
+ RNA_def_function_output(func, prop);
+ prop = RNA_def_property(func, "filter_neworder", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_flag(prop, PROP_REQUIRED | PROP_DYNAMIC);
+ RNA_def_property_array(prop, 1); /* XXX Dummy value, default 0 does not work */
+ RNA_def_property_ui_text(prop, "", "An array of indices, one for each item in the collection, mapping the org "
+ "index to the new one");
+ RNA_def_function_output(func, prop);
+
+ /* "Constants"! */
+ RNA_define_verify_sdna(0); /* not in sdna */
- /* registration */
- prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "type->idname");
- RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
- RNA_def_property_ui_text(prop, "ID Name",
- "If this is set, the uilist gets a custom ID, otherwise it takes the "
- "name of the class used to define the uilist (for example, if the "
- "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
- "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+ prop = RNA_def_property(srna, "bitflag_filter_item", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(prop, "FILTER_ITEM",
+ "The value of the reserved bitflag 'FILTER_ITEM' (in filter_flags values)");
+ RNA_def_property_int_funcs(prop, "rna_UIList_filter_const_FILTER_ITEM_get", NULL, NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
static void rna_def_header(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 2d89317b4ae..d79a40aa615 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -428,7 +428,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func,
"Sub-layout. Items placed in this sublayout are placed next to each other "
"in a row");
- RNA_def_boolean(func, "align", 0, "", "Align buttons to each other");
+ RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
func = RNA_def_function(srna, "column", "uiLayoutColumn");
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
@@ -436,13 +436,13 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func,
"Sub-layout. Items placed in this sublayout are placed under each other "
"in a column");
- RNA_def_boolean(func, "align", 0, "", "Align buttons to each other");
+ RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
func = RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow");
RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic", 0, INT_MAX);
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
RNA_def_function_return(func, parm);
- RNA_def_boolean(func, "align", 0, "", "Align buttons to each other");
+ RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
/* box layout */
func = RNA_def_function(srna, "box", "uiLayoutBox");
@@ -456,7 +456,7 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
RNA_def_function_return(func, parm);
RNA_def_float(func, "percentage", 0.0f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at", 0.0f, 1.0f);
- RNA_def_boolean(func, "align", 0, "", "Align buttons to each other");
+ RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
/* Icon of a rna pointer */
func = RNA_def_function(srna, "icon", "rna_ui_get_rnaptr_icon");
@@ -501,13 +501,13 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Item. Exposes an RNA item and places it into the layout");
api_ui_item_rna_common(func);
api_ui_item_common(func);
- RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail");
- RNA_def_boolean(func, "slider", 0, "", "Use slider widget for numeric values");
- RNA_def_boolean(func, "toggle", 0, "", "Use toggle widget for boolean values");
- RNA_def_boolean(func, "icon_only", 0, "", "Draw only icons in buttons, no text");
- RNA_def_boolean(func, "event", 0, "", "Use button to input key events");
- RNA_def_boolean(func, "full_event", 0, "", "Use button to input full events including modifiers");
- RNA_def_boolean(func, "emboss", 1, "", "Draw the button itself, just the icon/text");
+ RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail");
+ RNA_def_boolean(func, "slider", false, "", "Use slider widget for numeric values");
+ RNA_def_boolean(func, "toggle", false, "", "Use toggle widget for boolean values");
+ RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in buttons, no text");
+ RNA_def_boolean(func, "event", false, "", "Use button to input key events");
+ RNA_def_boolean(func, "full_event", false, "", "Use button to input full events including modifiers");
+ RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
RNA_def_int(func, "index", -1, -2, INT_MAX, "",
"The index of this button, when set a single member of an array can be accessed, "
"when set to -1 all array members are used", -2, INT_MAX); /* RNA_NO_INDEX == -1 */
@@ -535,7 +535,7 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "operator", "rna_uiItemO");
api_ui_item_op_common(func);
- RNA_def_boolean(func, "emboss", 1, "", "Draw the button itself, just the icon/text");
+ RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
parm = RNA_def_pointer(func, "properties", "OperatorProperties", "",
"Operator properties to fill in, return when 'properties' is set to true");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
@@ -569,7 +569,7 @@ void RNA_api_ui_layout(StructRNA *srna)
api_ui_item_op_common(func);
parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_boolean(func, "value", 0, "", "Value of the property to call the operator with");
+ parm = RNA_def_boolean(func, "value", false, "", "Value of the property to call the operator with");
RNA_def_property_flag(parm, PROP_REQUIRED); */
func = RNA_def_function(srna, "operator_int", "uiItemIntO");
@@ -623,7 +623,7 @@ void RNA_api_ui_layout(StructRNA *srna)
/* templates */
func = RNA_def_function(srna, "template_header", "uiTemplateHeader");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- RNA_def_boolean(func, "menus", 1, "", "The header has menus, and should show menu expander");
+ RNA_def_boolean(func, "menus", true, "", "The header has menus, and should show menu expander");
func = RNA_def_function(srna, "template_ID", "uiTemplateID");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -679,7 +679,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Item. A preview window for materials, textures, lamps, etc");
parm = RNA_def_pointer(func, "id", "ID", "", "ID datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_boolean(func, "show_buttons", 1, "", "Show preview buttons?");
+ RNA_def_boolean(func, "show_buttons", true, "", "Show preview buttons?");
RNA_def_pointer(func, "parent", "ID", "", "ID datablock");
RNA_def_pointer(func, "slot", "TextureSlot", "", "Texture slot");
@@ -687,13 +687,13 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Item. A curve mapping widget used for e.g falloff curves for lamps");
api_ui_item_rna_common(func);
RNA_def_enum(func, "type", curve_type_items, 0, "Type", "Type of curves to display");
- RNA_def_boolean(func, "levels", 0, "", "Show black/white levels");
- RNA_def_boolean(func, "brush", 0, "", "Show brush options");
+ RNA_def_boolean(func, "levels", false, "", "Show black/white levels");
+ RNA_def_boolean(func, "brush", false, "", "Show brush options");
func = RNA_def_function(srna, "template_color_ramp", "uiTemplateColorRamp");
RNA_def_function_ui_description(func, "Item. A color ramp widget");
api_ui_item_rna_common(func);
- RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail");
+ RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail");
func = RNA_def_function(srna, "template_icon_view", "uiTemplateIconView");
RNA_def_function_ui_description(func, "Enum. Large widget showing Icon previews");
@@ -723,10 +723,10 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "template_color_picker", "uiTemplateColorPicker");
RNA_def_function_ui_description(func, "Item. A color wheel widget to pick colors");
api_ui_item_rna_common(func);
- RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel");
- RNA_def_boolean(func, "lock", 0, "", "Lock the color wheel display to value 1.0 regardless of actual color");
- RNA_def_boolean(func, "lock_luminosity", 0, "", "Keep the color at its original vector length");
- RNA_def_boolean(func, "cubic", 1, "", "Cubic saturation for picking values close to white");
+ RNA_def_boolean(func, "value_slider", false, "", "Display the value slider to the right of the color wheel");
+ RNA_def_boolean(func, "lock", false, "", "Lock the color wheel display to value 1.0 regardless of actual color");
+ RNA_def_boolean(func, "lock_luminosity", false, "", "Keep the color at its original vector length");
+ RNA_def_boolean(func, "cubic", true, "", "Cubic saturation for picking values close to white");
func = RNA_def_function(srna, "template_image_layers", "uiTemplateImageLayers");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -741,19 +741,19 @@ void RNA_api_ui_layout(StructRNA *srna)
api_ui_item_rna_common(func);
parm = RNA_def_pointer(func, "image_user", "ImageUser", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
- RNA_def_boolean(func, "compact", 0, "", "Use more compact layout");
+ RNA_def_boolean(func, "compact", false, "", "Use more compact layout");
func = RNA_def_function(srna, "template_image_settings", "uiTemplateImageSettings");
RNA_def_function_ui_description(func, "User interface for setting image format options");
parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
- RNA_def_boolean(func, "color_management", 0, "", "Show color management settings");
+ RNA_def_boolean(func, "color_management", false, "", "Show color management settings");
func = RNA_def_function(srna, "template_movieclip", "uiTemplateMovieClip");
RNA_def_function_ui_description(func, "Item(s). User interface for selecting movie clips and their source paths");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
- RNA_def_boolean(func, "compact", 0, "", "Use more compact layout");
+ RNA_def_boolean(func, "compact", false, "", "Use more compact layout");
func = RNA_def_function(srna, "template_track", "uiTemplateTrack");
RNA_def_function_ui_description(func, "Item. A movie-track widget to preview tracking image.");
@@ -766,7 +766,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
parm = RNA_def_pointer(func, "track", "MovieTrackingTrack", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
- RNA_def_boolean(func, "compact", 0, "", "Use more compact layout");
+ RNA_def_boolean(func, "compact", false, "", "Use more compact layout");
func = RNA_def_function(srna, "template_movieclip_information", "uiTemplateMovieclipInformation");
RNA_def_function_ui_description(func, "Item. Movie clip information data.");
@@ -796,9 +796,10 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_string(func, "active_propname", "", 0, "",
"Identifier of the integer property in active_data, index of the active item");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display", 0, INT_MAX);
- RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Maximum number of rows to display", 0, INT_MAX);
+ RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Default and minimum number of rows to display", 0, INT_MAX);
+ RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Default maximum number of rows to display", 0, INT_MAX);
RNA_def_enum(func, "type", uilist_layout_type_items, UILST_LAYOUT_DEFAULT, "Type", "Type of layout to use");
+ RNA_def_int(func, "columns", 9, 0, INT_MAX, "", "Number of items to display per row, for GRID layout", 0, INT_MAX);
func = RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -859,7 +860,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Item. A widget to control color managed view settings settings.");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
- /* RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); */
+ /* RNA_def_boolean(func, "show_global_settings", false, "", "Show widgets to control global color management settings"); */
/* node socket icon */
func = RNA_def_function(srna, "template_node_socket", "uiTemplateNodeSocket");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index f34366a23c7..20e5083b1c4 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -505,6 +505,7 @@ static EnumPropertyItem *rna_userdef_audio_device_itemf(bContext *UNUSED(C), Poi
return item;
}
#else
+ (void)free;
return audio_device_items;
#endif
}
@@ -2134,6 +2135,18 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Stitch preview active island", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "uv_shadow", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "uv_shadow");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Texture paint/Modifier UVs", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "uv_others", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "uv_others");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Other Object UVs", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 0d1c684e6a1..c6366745c55 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -43,7 +43,8 @@
#include "WM_types.h"
-EnumPropertyItem event_keymouse_value_items[] = {
+#ifdef RNA_RUNTIME
+static EnumPropertyItem event_keymouse_value_items[] = {
{KM_ANY, "ANY", 0, "Any", ""},
{KM_PRESS, "PRESS", 0, "Press", ""},
{KM_RELEASE, "RELEASE", 0, "Release", ""},
@@ -52,7 +53,7 @@ EnumPropertyItem event_keymouse_value_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem event_tweak_value_items[] = {
+static EnumPropertyItem event_tweak_value_items[] = {
{KM_ANY, "ANY", 0, "Any", ""},
{EVT_GESTURE_N, "NORTH", 0, "North", ""},
{EVT_GESTURE_NE, "NORTH_EAST", 0, "North-East", ""},
@@ -65,25 +66,7 @@ EnumPropertyItem event_tweak_value_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem event_value_items[] = {
- {KM_ANY, "ANY", 0, "Any", ""},
- {KM_NOTHING, "NOTHING", 0, "Nothing", ""},
- {KM_PRESS, "PRESS", 0, "Press", ""},
- {KM_RELEASE, "RELEASE", 0, "Release", ""},
- {KM_CLICK, "CLICK", 0, "Click", ""},
- {KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""},
- {EVT_GESTURE_N, "NORTH", 0, "North", ""},
- {EVT_GESTURE_NE, "NORTH_EAST", 0, "North-East", ""},
- {EVT_GESTURE_E, "EAST", 0, "East", ""},
- {EVT_GESTURE_SE, "SOUTH_EAST", 0, "South-East", ""},
- {EVT_GESTURE_S, "SOUTH", 0, "South", ""},
- {EVT_GESTURE_SW, "SOUTH_WEST", 0, "South-West", ""},
- {EVT_GESTURE_W, "WEST", 0, "West", ""},
- {EVT_GESTURE_NW, "NORTH_WEST", 0, "North-West", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-EnumPropertyItem event_tweak_type_items[] = {
+static EnumPropertyItem event_tweak_type_items[] = {
{EVT_TWEAK_L, "EVT_TWEAK_L", 0, "Left", ""},
{EVT_TWEAK_M, "EVT_TWEAK_M", 0, "Middle", ""},
{EVT_TWEAK_R, "EVT_TWEAK_R", 0, "Right", ""},
@@ -92,7 +75,7 @@ EnumPropertyItem event_tweak_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem event_mouse_type_items[] = {
+static EnumPropertyItem event_mouse_type_items[] = {
{LEFTMOUSE, "LEFTMOUSE", 0, "Left", ""},
{MIDDLEMOUSE, "MIDDLEMOUSE", 0, "Middle", ""},
{RIGHTMOUSE, "RIGHTMOUSE", 0, "Right", ""},
@@ -113,7 +96,7 @@ EnumPropertyItem event_mouse_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem event_timer_type_items[] = {
+static EnumPropertyItem event_timer_type_items[] = {
{TIMER, "TIMER", 0, "Timer", ""},
{TIMER0, "TIMER0", 0, "Timer 0", ""},
{TIMER1, "TIMER1", 0, "Timer 1", ""},
@@ -125,12 +108,12 @@ EnumPropertyItem event_timer_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem event_textinput_type_items[] = {
+static EnumPropertyItem event_textinput_type_items[] = {
{KM_TEXTINPUT, "TEXTINPUT", 0, "Text Input", ""},
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem event_ndof_type_items[] = {
+static EnumPropertyItem event_ndof_type_items[] = {
{NDOF_MOTION, "NDOF_MOTION", 0, "Motion", ""},
/* buttons on all 3dconnexion devices */
{NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "Menu", ""},
@@ -179,6 +162,7 @@ EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""},
{0, NULL, 0, NULL, NULL}
};
+#endif
/* not returned: CAPSLOCKKEY, UNKNOWNKEY */
EnumPropertyItem event_type_items[] = {
@@ -386,6 +370,24 @@ EnumPropertyItem event_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem event_value_items[] = {
+ {KM_ANY, "ANY", 0, "Any", ""},
+ {KM_NOTHING, "NOTHING", 0, "Nothing", ""},
+ {KM_PRESS, "PRESS", 0, "Press", ""},
+ {KM_RELEASE, "RELEASE", 0, "Release", ""},
+ {KM_CLICK, "CLICK", 0, "Click", ""},
+ {KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""},
+ {EVT_GESTURE_N, "NORTH", 0, "North", ""},
+ {EVT_GESTURE_NE, "NORTH_EAST", 0, "North-East", ""},
+ {EVT_GESTURE_E, "EAST", 0, "East", ""},
+ {EVT_GESTURE_SE, "SOUTH_EAST", 0, "South-East", ""},
+ {EVT_GESTURE_S, "SOUTH", 0, "South", ""},
+ {EVT_GESTURE_SW, "SOUTH_WEST", 0, "South-West", ""},
+ {EVT_GESTURE_W, "WEST", 0, "West", ""},
+ {EVT_GESTURE_NW, "NORTH_WEST", 0, "North-West", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
EnumPropertyItem keymap_propvalue_items[] = {
{0, "NONE", 0, "", ""},
{0, NULL, 0, NULL, NULL}
@@ -401,7 +403,9 @@ static EnumPropertyItem keymap_modifiers_items[] = {
};
#endif
-EnumPropertyItem operator_flag_items[] = {
+
+#ifndef RNA_RUNTIME
+static EnumPropertyItem operator_flag_items[] = {
{OPTYPE_REGISTER, "REGISTER", 0, "Register", "Display in the info window and support the redo toolbar panel"},
{OPTYPE_UNDO, "UNDO", 0, "Undo", "Push an undo event (needed for operator redo)"},
{OPTYPE_BLOCKING, "BLOCKING", 0, "Blocking", "Block anything else from using the cursor"},
@@ -413,6 +417,7 @@ EnumPropertyItem operator_flag_items[] = {
{OPTYPE_INTERNAL, "INTERNAL", 0, "Internal", "Removes the operator from search results"},
{0, NULL, 0, NULL, NULL}
};
+#endif
EnumPropertyItem operator_return_items[] = {
{OPERATOR_RUNNING_MODAL, "RUNNING_MODAL", 0, "Running Modal", "Keep the operator running with blender"},
@@ -585,7 +590,7 @@ static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
win->newscreen = value.data;
}
-int rna_Window_screen_assign_poll(PointerRNA *ptr, PointerRNA value)
+int rna_Window_screen_assign_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
bScreen *screen = (bScreen *)value.id.data;
@@ -1735,6 +1740,8 @@ static void rna_def_window(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "sizey");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Height", "Window height");
+
+ RNA_api_window(srna);
}
/* curve.splines */
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index c822378e76e..eb84bb61e1f 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -41,8 +41,31 @@
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
+#include "wm_cursors.h"
+
#include "rna_internal.h" /* own include */
+/* confusingm 2 enums mixed up here */
+EnumPropertyItem window_cursor_items[] = {
+ {CURSOR_STD, "DEFAULT", 0, "Default", ""},
+ {CURSOR_NONE, "NONE", 0, "None", ""},
+ {CURSOR_WAIT, "WAIT", 0, "Wait", ""},
+ {CURSOR_EDIT, "CROSSHAIR", 0, "Crosshair", ""},
+ {CURSOR_X_MOVE, "MOVE_X", 0, "Move-X", ""},
+ {CURSOR_Y_MOVE, "MOVE_Y", 0, "Move-Y", ""},
+
+ /* new */
+ {BC_KNIFECURSOR, "KNIFE", 0, "Knife", ""},
+ {BC_TEXTEDITCURSOR, "TEXT", 0, "Text", ""},
+ {BC_PAINTBRUSHCURSOR, "PAINT_BRUSH", 0, "Paint Brush", ""},
+ {BC_HANDCURSOR, "HAND", 0, "Hand", ""},
+ {BC_EW_SCROLLCURSOR, "SCROLL_X", 0, "Scroll-X", ""},
+ {BC_NS_SCROLLCURSOR, "SCROLL_Y", 0, "Scroll-Y", ""},
+ {BC_NSEW_SCROLLCURSOR, "SCROLL_XY", 0, "Scroll-XY", ""},
+ {BC_EYEDROPPER_CURSOR, "EYEDROPPER", 0, "Eyedropper", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "UI_interface.h"
@@ -95,7 +118,7 @@ struct wmStaticProgress {
} wm_progress_state = {0, 0, false};
-static void rna_progress_begin(struct wmWindowManager *wm, float min, float max)
+static void rna_progress_begin(struct wmWindowManager *UNUSED(wm), float min, float max)
{
float range = max - min;
if (range != 0) {
@@ -120,7 +143,7 @@ static void rna_progress_update(struct wmWindowManager *wm, float value)
static void rna_progress_end(struct wmWindowManager *wm)
{
if (wm_progress_state.is_valid) {
- WM_cursor_restore(wm->winactive);
+ WM_cursor_modal_restore(wm->winactive);
wm_progress_state.is_valid = false;
}
}
@@ -239,6 +262,18 @@ static wmKeyMap *rna_keymap_find_modal(wmKeyConfig *UNUSED(keyconf), const char
return ot->modalkeymap;
}
+static void rna_KeyMap_remove(wmKeyConfig *keyconfig, ReportList *reports, PointerRNA *keymap_ptr)
+{
+ wmKeyMap *keymap = keymap_ptr->data;
+
+ if (WM_keymap_remove(keyconfig, keymap) == FALSE) {
+ BKE_reportf(reports, RPT_ERROR, "KeyConfig '%s' cannot be removed", keymap->idname);
+ return;
+ }
+
+ RNA_POINTER_INVALIDATE(keymap_ptr);
+}
+
static void rna_KeyConfig_remove(wmWindowManager *wm, ReportList *reports, PointerRNA *keyconf_ptr)
{
wmKeyConfig *keyconf = keyconf_ptr->data;
@@ -299,6 +334,34 @@ static void rna_generic_op_invoke(FunctionRNA *func, int flag)
}
}
+void RNA_api_window(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "cursor_warp", "WM_cursor_warp");
+ parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "y", 0, INT_MIN, INT_MAX, "", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Set the cursor position");
+
+ func = RNA_def_function(srna, "cursor_set", "WM_cursor_set");
+ parm = RNA_def_property(func, "cursor", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(parm, window_cursor_items);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Set the cursor");
+
+ func = RNA_def_function(srna, "cursor_modal_set", "WM_cursor_modal_set");
+ parm = RNA_def_property(func, "cursor", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(parm, window_cursor_items);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Set the cursor, so the previous cursor can be restored");
+
+ RNA_def_function(srna, "cursor_modal_restore", "WM_cursor_modal_restore");
+ RNA_def_function_ui_description(func, "Restore the previous cursor after calling ``cursor_modal_set``");
+}
+
void RNA_api_wm(StructRNA *srna)
{
FunctionRNA *func;
@@ -620,6 +683,12 @@ void RNA_api_keymaps(StructRNA *srna)
parm = RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Added key map");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "remove", "rna_KeyMap_remove"); /* remove_keymap */
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Removed key map");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
func = RNA_def_function(srna, "find", "rna_keymap_find"); /* find_keymap */
parm = RNA_def_string(func, "name", "", 0, "Name", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index e09fa18ffc5..7c47fd5862e 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -50,6 +50,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
+#include "BKE_curve.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -198,7 +199,7 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op,
/*element type argument doesn't do anything here*/
BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) {
- v2 = BMO_iter_map_value_p(&oiter);
+ v2 = BMO_iter_map_value_ptr(&oiter);
index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1;
}
@@ -271,7 +272,7 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4],
/* add new merge targets to weld operator */
BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) {
- v2 = BMO_iter_map_value_p(&oiter);
+ v2 = BMO_iter_map_value_ptr(&oiter);
/* check in case the target vertex (v2) is already marked
* for merging */
while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) {
@@ -318,8 +319,10 @@ static void merge_first_last(BMesh *bm,
/* add new merge targets to weld operator */
slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap");
BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) {
- v2 = BMO_iter_map_value_p(&oiter);
- BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2);
+ if (!BMO_slot_map_contains(slot_targetmap, v)) {
+ v2 = BMO_iter_map_value_ptr(&oiter);
+ BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2);
+ }
}
BMO_op_finish(bm, &find_op);
@@ -343,7 +346,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
int *indexMap = NULL;
DerivedMesh *start_cap = NULL, *end_cap = NULL;
MVert *src_mvert;
- BMOpSlot *slot_targetmap = NULL; /* for weldop */
+ BMOpSlot *slot_targetmap = NULL; /* for weld_op */
/* need to avoid infinite recursion here */
if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH)
@@ -387,19 +390,19 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
BKE_object_to_mat3(amd->curve_ob, tmp_mat);
scale = mat3_to_scale(tmp_mat);
- if (!cu->path) {
+ if (!amd->curve_ob->curve_cache || !amd->curve_ob->curve_cache->path) {
cu->flag |= CU_PATH; // needed for path & bevlist
BKE_displist_make_curveTypes(scene, amd->curve_ob, 0);
}
- if (cu->path)
- length = scale * cu->path->totdist;
+ if (amd->curve_ob->curve_cache->path)
+ length = scale * amd->curve_ob->curve_cache->path->totdist;
}
}
/* calculate the maximum number of copies which will fit within the
* prescribed length */
if (amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) {
- float dist = sqrt(dot_v3v3(offset[3], offset[3]));
+ float dist = len_v3(offset[3]);
if (dist > 1e-6f)
/* this gives length = first copy start to last copy end
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index b48f434abe9..326ffba3e2e 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -46,6 +46,7 @@
#include "MOD_util.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "MEM_guardedalloc.h"
@@ -116,7 +117,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
if ((bmd->lim_flags & MOD_BEVEL_VGROUP) && bmd->defgrp_name[0]) {
modifier_get_vgroup(ob, dm, bmd->defgrp_name, &dvert, &vgroup);
}
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_vert_is_manifold(v))
continue;
if (vgroup != -1) {
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
index 98fab9c06ff..9c8109c7856 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ b/source/blender/modifiers/intern/MOD_boolean_util.c
@@ -266,44 +266,6 @@ static void FaceIt_Construct(
output->it = it;
}
-static Object *AddNewBlenderMesh(Scene *scene, Base *base)
-{
- /* This little function adds a new mesh object to the blender object list
- * It uses ob to duplicate data as this seems to be easier than creating
- * a new one. This new oject contains no faces nor vertices. */
- Mesh *old_me;
- Base *basen;
- Object *ob_new;
-
- /* now create a new blender object.
- * duplicating all the settings from the previous object
- * to the new one. */
- ob_new = BKE_object_copy(base->object);
-
- /* Ok we don't want to use the actual data from the
- * last object, the above function incremented the
- * number of users, so decrement it here. */
- old_me = ob_new->data;
- old_me->id.us--;
-
- /* Now create a new base to add into the linked list of
- * vase objects. */
-
- basen = MEM_mallocN(sizeof(Base), "duplibase");
- *basen = *base;
- BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */
- basen->object = ob_new;
- basen->flag &= ~SELECT;
-
- /* Initialize the mesh data associated with this object. */
- ob_new->data = BKE_mesh_add(G.main, "Mesh");
-
- /* Finally assign the object type. */
- ob_new->type = OB_MESH;
-
- return ob_new;
-}
-
static void InterpCSGFace(
DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr,
float mapmat[4][4])
@@ -509,9 +471,9 @@ static void FreeMeshDescriptors(
FaceIt_Destruct(face_it);
}
-static DerivedMesh *NewBooleanDerivedMesh_intern(
+DerivedMesh *NewBooleanDerivedMesh(
DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
- int int_op_type, Material **mat, int *totmat)
+ int int_op_type)
{
float inv_mat[4][4];
@@ -567,7 +529,7 @@ static DerivedMesh *NewBooleanDerivedMesh_intern(
/* iterate through results of operation and insert
* into new object */
result = ConvertCSGDescriptorsToDerivedMesh(
- &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob);
+ &fd_o, &vd_o, inv_mat, map_mat, NULL, NULL, dm_select, ob_select, dm, ob);
/* free up the memory */
CSG_FreeVertexDescriptor(&vd_o);
@@ -584,67 +546,3 @@ static DerivedMesh *NewBooleanDerivedMesh_intern(
return result;
}
-
-int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
-{
- Mesh *me_new;
- int a, maxmat, totmat = 0;
- Object *ob_new, *ob, *ob_select;
- Material **mat;
- DerivedMesh *result;
- DerivedMesh *dm_select;
- DerivedMesh *dm;
-
- ob = base->object;
- ob_select = base_select->object;
-
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ??
-
- maxmat = ob->totcol + ob_select->totcol;
- mat = (Material **)MEM_mallocN(sizeof(Material *) * maxmat, "NewBooleanMeshMat");
-
- /* put some checks in for nice user feedback */
- if (dm == NULL || dm_select == NULL) {
- return 0;
- }
-
- if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) {
- MEM_freeN(mat);
- return -1;
- }
-
- result = NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat);
-
- if (result == NULL) {
- MEM_freeN(mat);
- return 0;
- }
-
- /* create a new blender mesh object - using 'base' as a template */
- ob_new = AddNewBlenderMesh(scene, base_select);
- me_new = ob_new->data;
-
- DM_to_mesh(result, me_new, ob_new, CD_MASK_MESH);
- result->release(result);
-
- dm->release(dm);
- dm_select->release(dm_select);
-
- /* add materials to object */
- for (a = 0; a < totmat; a++)
- assign_material(ob_new, mat[a], a + 1, BKE_MAT_ASSIGN_USERPREF);
-
- MEM_freeN(mat);
-
- /* update dag */
- DAG_id_tag_update(&ob_new->id, OB_RECALC_DATA);
-
- return 1;
-}
-
-DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
- int int_op_type)
-{
- return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL);
-}
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/modifiers/intern/MOD_boolean_util.h
index 209db60f0c9..04d76d45652 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.h
+++ b/source/blender/modifiers/intern/MOD_boolean_util.h
@@ -39,12 +39,6 @@ struct Base;
struct DerivedMesh;
/* Performs a boolean between two mesh objects, it is assumed that both objects
- * are in fact a mesh object. On success returns 1 and creates a new mesh object
- * into blender data structures. On failure returns 0 and reports an error. */
-int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_select, int op);
-
-
-/* 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. */
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 9e375b07972..a54cc80839b 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -109,7 +109,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
edgeMap = MEM_mallocN(sizeof(*edgeMap) * numEdge_src, "build modifier edgeMap");
faceMap = MEM_mallocN(sizeof(*faceMap) * numPoly_src, "build modifier faceMap");
-#pragma omp parallel sections if (numVert_src + numEdge_src + numPoly_src >= DM_OMP_LIMIT)
+#pragma omp parallel sections if (numVert_src + numEdge_src + numPoly_src >= BKE_MESH_OMP_LIMIT)
{
#pragma omp section
{ range_vn_i(vertMap, numVert_src, 0); }
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index 9fdb40e71dc..a3569cbde68 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -49,11 +49,13 @@
#include "BKE_cdderivedmesh.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
// #define USE_TIMEIT
#ifdef USE_TIMEIT
# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
#endif
#include "MOD_util.h"
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index b3d3e65e120..d55ebdad939 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -44,6 +44,7 @@
#include "BKE_modifier.h"
#include "bmesh.h"
+#include "bmesh_tools.h"
#include "DNA_object_types.h"
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index fe680041197..9fd11f78ea0 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -568,7 +568,7 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
int numlayer;
unsigned int ed_v1, ed_v2;
- edgehash = BLI_edgehash_new();
+ edgehash = BLI_edgehash_new(__func__);
/* recreate vertpa from facepa calculation */
for (i = 0, mf = mface; i < totface; i++, mf++) {
@@ -586,12 +586,12 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
v3 = vertpa[mf->v3];
if (v1 != v2) {
- BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL);
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v2, NULL);
(*fs) |= 1;
}
if (v2 != v3) {
- BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL);
+ BLI_edgehash_reinsert(edgehash, mf->v2, mf->v3, NULL);
(*fs) |= 2;
}
@@ -599,24 +599,24 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
v4 = vertpa[mf->v4];
if (v3 != v4) {
- BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL);
+ BLI_edgehash_reinsert(edgehash, mf->v3, mf->v4, NULL);
(*fs) |= 4;
}
if (v1 != v4) {
- BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL);
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v4, NULL);
(*fs) |= 8;
}
/* mark center vertex as a fake edge split */
if (*fs == 15)
- BLI_edgehash_insert(edgehash, mf->v1, mf->v3, NULL);
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
}
else {
(*fs) |= 16; /* mark face as tri */
if (v1 != v3) {
- BLI_edgehash_insert(edgehash, mf->v1, mf->v3, NULL);
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
(*fs) |= 4;
}
}
@@ -821,7 +821,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
cfra = BKE_scene_frame_get(scene);
/* hash table for vertice <-> particle relations */
- vertpahash = BLI_edgehash_new();
+ vertpahash = BLI_edgehash_new(__func__);
for (i = 0; i < totface; i++) {
if (facepa[i] != totpart) {
@@ -846,11 +846,11 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
mf = &mface[i];
/* set face vertices to exist in particle group */
- BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL);
- BLI_edgehash_insert(vertpahash, mf->v2, mindex, NULL);
- BLI_edgehash_insert(vertpahash, mf->v3, mindex, NULL);
+ BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, NULL);
+ BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL);
+ BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL);
if (mf->v4)
- BLI_edgehash_insert(vertpahash, mf->v4, mindex, NULL);
+ BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, NULL);
}
/* make new vertice indexes & count total vertices after duplication */
@@ -869,7 +869,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
/* getting back to object space */
invert_m4_m4(imat, ob->obmat);
- psmd->psys->lattice = psys_get_lattice(&sim);
+ psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
/* duplicate & displace vertices */
ehi = BLI_edgehashIterator_new(vertpahash);
@@ -973,9 +973,9 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
CDDM_tessfaces_to_faces(explode);
explode->dirty |= DM_DIRTY_NORMALS;
- if (psmd->psys->lattice) {
- end_latt_deform(psmd->psys->lattice);
- psmd->psys->lattice = NULL;
+ if (psmd->psys->lattice_deform_data) {
+ end_latt_deform(psmd->psys->lattice_deform_data);
+ psmd->psys->lattice_deform_data = NULL;
}
return explode;
diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.c b/source/blender/modifiers/intern/MOD_meshcache_util.c
index 679a79322c3..404d0538a29 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_util.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_util.c
@@ -20,6 +20,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/modifiers/intern/MOD_meshcache_util.c
+ * \ingroup modifiers
+ */
+
#include "BLI_utildefines.h"
#include "BLI_math.h"
diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.h b/source/blender/modifiers/intern/MOD_meshcache_util.h
index d7e71518f77..f3b5f43009d 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_util.h
+++ b/source/blender/modifiers/intern/MOD_meshcache_util.h
@@ -25,6 +25,7 @@
*/
#ifndef __MOD_MESHCACHE_UTIL_H__
+#define __MOD_MESHCACHE_UTIL_H__
struct MPoly;
struct MLoop;
@@ -64,4 +65,4 @@ void MOD_meshcache_calc_range(const float frame, const char interp,
#define FRAME_SNAP_EPS 0.0001f
-#endif /* __MOD_MESHCACHE_UTIL_H__ */
+#endif /* __MOD_MESHCACHE_UTIL_H__ */
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index e846ce11262..c51fa329df2 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -261,7 +261,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
maxloop += totloop;
}
- psys->lattice = psys_get_lattice(&sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
float min_r[3], max_r[3];
@@ -378,9 +378,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
CDDM_calc_edges(result);
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice = NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
if (size)
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 83ac9f34df3..09e0ac966d0 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -933,7 +933,6 @@ static void add_poly(SkinOutput *so,
BMVert *v4)
{
BMVert *verts[4] = {v1, v2, v3, v4};
- BMEdge *edges[4];
BMFace *f;
BLI_assert(v1 != v2 && v1 != v3 && v1 != v4);
@@ -941,18 +940,7 @@ static void add_poly(SkinOutput *so,
BLI_assert(v3 != v4);
BLI_assert(v1 && v2 && v3);
- edges[0] = BM_edge_create(so->bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE);
- edges[1] = BM_edge_create(so->bm, v2, v3, NULL, BM_CREATE_NO_DOUBLE);
- if (v4) {
- edges[2] = BM_edge_create(so->bm, v3, v4, NULL, BM_CREATE_NO_DOUBLE);
- edges[3] = BM_edge_create(so->bm, v4, v1, NULL, BM_CREATE_NO_DOUBLE);
- }
- else {
- edges[2] = BM_edge_create(so->bm, v3, v1, NULL, BM_CREATE_NO_DOUBLE);
- edges[3] = NULL;
- }
-
- f = BM_face_create(so->bm, verts, edges, v4 ? 4 : 3, BM_CREATE_NO_DOUBLE);
+ f = BM_face_create_verts(so->bm, verts, v4 ? 4 : 3, NULL, BM_CREATE_NO_DOUBLE, true);
if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING)
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
f->mat_nr = so->mat_nr;
@@ -996,7 +984,7 @@ static void output_frames(BMesh *bm,
f = &sn->frames[i];
for (j = 0; j < 4; j++) {
if (!f->merge[j].frame) {
- BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL, 0);
+ BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL, BM_CREATE_NOP);
if (input_dvert) {
MDeformVert *dv;
@@ -1310,7 +1298,7 @@ static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame)
/* Detach everything */
for (i = 0; i < totattached; i++) {
BMVert **av = &frame->verts[attached[i]];
- (*av) = BM_vert_create(bm, (*av)->co, *av, 0);
+ (*av) = BM_vert_create(bm, (*av)->co, *av, BM_CREATE_NOP);
}
}
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 98cea62a2ff..4e2656bbf00 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -121,14 +121,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob),
struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
+ ModifierApplyFlag flag)
{
SubsurfModifierData *smd = (SubsurfModifierData *) md;
DerivedMesh *result;
+ /* 'orco' using editmode flags would cause cache to be used twice in editbmesh_calc_modifiers */
+ SubsurfFlags ss_flags = (flag & MOD_APPLY_ORCO) ? 0 : (SUBSURF_FOR_EDIT_MODE | SUBSURF_IN_EDIT_MODE);
- result = subsurf_make_derived_from_derived(derivedData, smd,
- NULL, (SUBSURF_FOR_EDIT_MODE |
- SUBSURF_IN_EDIT_MODE));
+ result = subsurf_make_derived_from_derived(derivedData, smd, NULL, ss_flags);
return result;
}
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index 9155aa0044b..ffc813068b8 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -33,6 +33,9 @@
#include "BKE_modifier.h"
#include "BKE_editmesh.h"
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int flag)
{
DerivedMesh *result;
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index b6539f4b028..ad1e2a464a8 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -93,7 +93,7 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(
CustomDataMask dataMask = 0;
/* ask for UV coordinates */
- dataMask |= CD_MASK_MTFACE;
+ dataMask |= CD_MLOOPUV | CD_MTEXPOLY;
return dataMask;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 63267538528..67168e52949 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -28,18 +28,12 @@
* \ingroup modifiers
*/
-#define DO_PROFILE 0
-
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_rand.h"
-#if DO_PROFILE
- #include "PIL_time.h"
-#endif
-
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -58,6 +52,13 @@
#include "MOD_util.h"
#include "MOD_weightvg_util.h"
+// #define USE_TIMEIT
+
+#ifdef USE_TIMEIT
+# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
+#endif
+
/**************************************
* Util functions. *
**************************************/
@@ -382,8 +383,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
#endif
-#if DO_PROFILE
- TIMEIT_START(perf)
+#ifdef USE_TIMEIT
+ TIMEIT_START(perf);
#endif
/* Get number of verts. */
@@ -548,8 +549,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
MEM_freeN(indices);
MEM_freeN(v_cos);
-#if DO_PROFILE
- TIMEIT_END(perf)
+#ifdef USE_TIMEIT
+ TIMEIT_END(perf);
#endif
/* Return the vgroup-modified mesh. */
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 64261246e3d..61c8cb5655d 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -92,6 +92,7 @@ set(SRC
composite/nodes/node_composite_normal.c
composite/nodes/node_composite_normalize.c
composite/nodes/node_composite_outputFile.c
+ composite/nodes/node_composite_planetrackdeform.c
composite/nodes/node_composite_premulkey.c
composite/nodes/node_composite_rgb.c
composite/nodes/node_composite_rotate.c
@@ -163,6 +164,7 @@ set(SRC
shader/nodes/node_shader_bsdf_translucent.c
shader/nodes/node_shader_bsdf_transparent.c
shader/nodes/node_shader_bsdf_velvet.c
+ shader/nodes/node_shader_bsdf_hair.c
shader/nodes/node_shader_bump.c
shader/nodes/node_shader_emission.c
shader/nodes/node_shader_fresnel.c
diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h
index ac0ceab36d4..a8279b4c66a 100644
--- a/source/blender/nodes/NOD_common.h
+++ b/source/blender/nodes/NOD_common.h
@@ -29,8 +29,8 @@
* \ingroup nodes
*/
-#ifndef NOD_COMMON_H
-#define NOD_COMMON_H
+#ifndef __NOD_COMMON_H__
+#define __NOD_COMMON_H__
#include "BKE_node.h"
@@ -51,4 +51,4 @@ struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char
void node_group_input_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
void node_group_output_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
-#endif
+#endif /* __NOD_COMMON_H__ */
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 626e7955b08..78265154125 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -42,8 +42,6 @@ extern struct bNodeTreeType *ntreeType_Composite;
void register_node_tree_type_cmp(void);
void register_node_type_cmp_group(void);
-void register_node_type_cmp_forloop(void);
-void register_node_type_cmp_whileloop(void);
void register_node_type_cmp_rlayers(void);
void register_node_type_cmp_image(void);
@@ -137,6 +135,7 @@ void register_node_type_cmp_bokehblur(void);
void register_node_type_cmp_switch(void);
void register_node_type_cmp_pixelate(void);
void register_node_type_cmp_trackpos(void);
+void register_node_type_cmp_planetrackdeform(void);
void node_cmp_rlayers_force_hidden_passes(struct bNode *node);
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index ec39d81618d..853046a2a23 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -43,8 +43,6 @@ extern struct bNodeTreeType *ntreeType_Shader;
void register_node_tree_type_sh(void);
void register_node_type_sh_group(void);
-void register_node_type_sh_forloop(void);
-void register_node_type_sh_whileloop(void);
void register_node_type_sh_output(void);
void register_node_type_sh_material(void);
@@ -108,6 +106,7 @@ void register_node_type_sh_emission(void);
void register_node_type_sh_holdout(void);
void register_node_type_sh_volume_transparent(void);
void register_node_type_sh_volume_isotropic(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);
void register_node_type_sh_add_shader(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 0b526fcde0e..db9f710b6cf 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -85,7 +85,8 @@ DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BS
DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TOON, def_toon, "BSDF_TOON", BsdfToon, "Toon BSDF", "" )
-DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, 0, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
+DefNode( ShaderNode, SH_NODE_BSDF_HAIR, def_hair, "BSDF_HAIR", BsdfHair, "Hair BSDF", "" )
+DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
DefNode( ShaderNode, SH_NODE_VOLUME_TRANSPARENT, 0, "VOLUME_TRANSPARENT", VolumeTransparent,"Transparent Volume","" )
DefNode( ShaderNode, SH_NODE_VOLUME_ISOTROPIC, 0, "VOLUME_ISOTROPIC", VolumeIsotropic, "Isotropic Volume", "" )
DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" )
@@ -141,7 +142,8 @@ DefNode( CompositorNode, CMP_NODE_HUE_SAT, def_cmp_hue_saturation, "HUE_S
DefNode( CompositorNode, CMP_NODE_IMAGE, def_cmp_image, "IMAGE", Image, "Image", "" )
DefNode( CompositorNode, CMP_NODE_R_LAYERS, def_cmp_render_layers, "R_LAYERS", RLayers, "Render Layers", "" )
DefNode( CompositorNode, CMP_NODE_COMPOSITE, def_cmp_composite, "COMPOSITE", Composite, "Composite", "" )
-DefNode( CompositorNode, CMP_NODE_OUTPUT_FILE, def_cmp_output_file, "OUTPUT_FILE", OutputFile, "File Output", "" )
+/* NB: OutputFile node has special rna setup function called in rna_nodetree.c */
+DefNode( CompositorNode, CMP_NODE_OUTPUT_FILE, 0, "OUTPUT_FILE", OutputFile, "File Output", "" )
DefNode( CompositorNode, CMP_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" )
DefNode( CompositorNode, CMP_NODE_TRANSLATE, def_cmp_translate, "TRANSLATE", Translate, "Translate", "" )
DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" )
@@ -200,6 +202,7 @@ DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYIN
DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" )
DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" )
DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" )
+DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" )
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h
index ea003f23960..378c96d5882 100644
--- a/source/blender/nodes/NOD_texture.h
+++ b/source/blender/nodes/NOD_texture.h
@@ -42,8 +42,6 @@ extern struct bNodeTreeType *ntreeType_Texture;
void register_node_tree_type_tex(void);
void register_node_type_tex_group(void);
-void register_node_type_tex_forloop(void);
-void register_node_type_tex_whileloop(void);
void register_node_type_tex_math(void);
void register_node_type_tex_mix_rgb(void);
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 0b62481b2f7..31ae46468c3 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -318,38 +318,22 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node)
lb = RNA_struct_type_properties(ptr.type);
for (link = lb->first; link; link = link->next) {
- int len = 1, index;
- bool driven;
prop = (PropertyRNA *)link;
- if (RNA_property_array_check(prop))
- len = RNA_property_array_length(&ptr, prop);
-
- for (index = 0; index < len; index++) {
- if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
- nodeUpdate(ntree, node);
- return 1;
- }
+ if (RNA_property_animated(&ptr, prop)) {
+ nodeUpdate(ntree, node);
+ return 1;
}
}
/* now check node sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
- int len = 1, index;
- bool driven;
-
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
prop = RNA_struct_find_property(&ptr, "default_value");
- if (prop) {
- if (RNA_property_array_check(prop))
- len = RNA_property_array_length(&ptr, prop);
-
- for (index = 0; index < len; index++) {
- if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
- nodeUpdate(ntree, node);
- return 1;
- }
- }
+
+ if (RNA_property_animated(&ptr, prop)) {
+ nodeUpdate(ntree, node);
+ return 1;
}
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
index 316e5b344ce..22d16e93879 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_map_value_out[] = {
static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage = add_tex_mapping();
+ node->storage = add_tex_mapping(TEXMAP_TYPE_POINT);
}
void register_node_type_cmp_map_value(void)
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 90b21f1bab0..89c6fbe4590 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -225,9 +225,24 @@ static void copy_output_file(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bN
static void update_output_file(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *sock;
+ bNodeSocket *sock, *sock_next;
PointerRNA ptr;
+ /* XXX fix for #36706: remove invalid sockets added with bpy API.
+ * This is not ideal, but prevents crashes from missing storage.
+ * FileOutput node needs a redesign to support this properly.
+ */
+ for (sock = node->inputs.first; sock; sock = sock_next) {
+ sock_next = sock->next;
+ if (sock->storage == NULL) {
+ nodeRemoveSocket(ntree, node, sock);
+ }
+ }
+ for (sock = node->outputs.first; sock; sock = sock_next) {
+ sock_next = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
cmp_node_update_default(ntree, node);
/* automatically update the socket type based on linked input */
diff --git a/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c b/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
new file mode 100644
index 00000000000..7a15d6364dc
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_planetrackdeform.c
+ * \ingroup cmpnodes
+ */
+
+
+#include "node_composite_util.h"
+
+static bNodeSocketTemplate cmp_node_planetrackdeform_in[] = {
+ { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate cmp_node_planetrackdeform_out[] = {
+ { SOCK_RGBA, 0, N_("Image")},
+ { SOCK_FLOAT, 0, N_("Plane")},
+ { -1, 0, "" }
+};
+
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodePlaneTrackDeformData *data = MEM_callocN(sizeof(NodePlaneTrackDeformData), "node plane track deform data");
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_planetrackdeform(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_PLANETRACKDEFORM, "Plane Track Deform", NODE_CLASS_DISTORT, 0);
+ node_type_socket_templates(&ntype, cmp_node_planetrackdeform_in, cmp_node_planetrackdeform_out);
+ node_type_init(&ntype, init);
+ node_type_storage(&ntype, "NodePlaneTrackDeformData", node_free_standard_storage, node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.c b/source/blender/nodes/composite/nodes/node_composite_scale.c
index 134402c00e1..8041a2e56e9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_scale.c
+++ b/source/blender/nodes/composite/nodes/node_composite_scale.c
@@ -45,12 +45,31 @@ static bNodeSocketTemplate cmp_node_scale_out[] = {
{ -1, 0, "" }
};
+static void node_composite_update_scale(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock;
+ bool use_xy_scale = ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_ABSOLUTE);
+
+ /* Only show X/Y scale factor inputs for modes using them! */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "X") || STREQ(sock->name, "Y")) {
+ if (use_xy_scale) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ }
+}
+
void register_node_type_cmp_scale(void)
{
static bNodeType ntype;
cmp_node_type_base(&ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, 0);
node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out);
+ node_type_update(&ntype, node_composite_update_scale, NULL);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 2b6318679e0..812fe5b4ae7 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -287,8 +287,8 @@ void ntreeReleaseThreadStack(bNodeThreadStack *nts)
bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
{
- bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
+ bNodeStack *nsin[MAX_SOCKET] = {NULL}; /* arbitrary... watch this */
+ bNodeStack *nsout[MAX_SOCKET] = {NULL}; /* arbitrary... watch this */
bNodeExec *nodeexec;
bNode *node;
int n;
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index f9a450174a3..e77f0a08331 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -112,86 +112,54 @@ const char *node_filter_label(bNode *node)
void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *fromsock_first = NULL, *tosock_first = NULL; /* used for fallback link if no other reconnections are found */
- int datatype;
- int num_links_in = 0, num_links_out = 0, num_reconnect = 0;
+ bNodeLink *link;
+ bNodeSocket *output, *input, *selected;
- /* Security check! */
+ /* sanity check */
if (!ntree)
return;
- for (datatype = 0; datatype < NUM_SOCKET_TYPES; ++datatype) {
- bNodeSocket *fromsock, *tosock;
- int fromindex, toindex;
- bNodeLink *link;
-
- /* Connect the first input of each type with outputs of the same type. */
+ /* use link pointer as a tag for handled sockets (for outputs is unused anyway) */
+ for (output = node->outputs.first; output; output = output->next)
+ output->link = NULL;
+
+ for (link = ntree->links.first; link; link = link->next) {
+ output = link->fromsock;
+ if (link->fromnode != node || output->link)
+ continue;
+ output->link = link; /* not really used, just for tagging handled sockets */
- fromindex = INT_MAX;
- fromsock = NULL;
- for (link = ntree->links.first; link; link = link->next) {
- if (nodeLinkIsHidden(link))
- continue;
- if (link->tonode == node && link->tosock->type == datatype) {
- int index = BLI_findindex(&node->inputs, link->tosock);
- if (index < fromindex) {
- fromindex = index;
- fromsock = link->tosock;
+ /* look for suitable input */
+ selected = NULL;
+ for (input = node->inputs.first; input; input = input->next) {
+ /* only use if same type */
+ if (input->type == output->type) {
+ if (!selected) {
+ selected = input;
}
- }
- }
- if (fromsock) {
- ++num_links_in;
- if (!fromsock_first)
- fromsock_first = fromsock;
- }
-
- toindex = INT_MAX;
- tosock = NULL;
- for (link = ntree->links.first; link; link = link->next) {
- if (nodeLinkIsHidden(link))
- continue;
- if (link->fromnode == node && link->fromsock->type == datatype) {
- int index = BLI_findindex(&node->outputs, link->fromsock);
- if (index < toindex) {
- toindex = index;
- tosock = link->fromsock;
+ else {
+ /* linked inputs preferred */
+ if (input->link && !selected->link)
+ selected = input;
}
}
}
- if (tosock) {
- ++num_links_out;
- if (!tosock_first)
- tosock_first = tosock;
-
- if (fromsock) {
- bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link");
- ilink->fromnode = node;
- ilink->fromsock = fromsock;
- ilink->tonode = node;
- ilink->tosock = tosock;
- /* internal link is always valid */
- ilink->flag |= NODE_LINK_VALID;
- BLI_addtail(&node->internal_links, ilink);
-
- ++num_reconnect;
- }
+
+ if (selected) {
+ bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link");
+ ilink->fromnode = node;
+ ilink->fromsock = selected;
+ ilink->tonode = node;
+ ilink->tosock = output;
+ /* internal link is always valid */
+ ilink->flag |= NODE_LINK_VALID;
+ BLI_addtail(&node->internal_links, ilink);
}
}
- /* if there is one input and one output link, but no reconnections by type,
- * simply connect those two sockets.
- */
- if ((num_reconnect == 0) && (num_links_in == 1) && (num_links_out == 1)) {
- bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link");
- ilink->fromnode = node;
- ilink->fromsock = fromsock_first;
- ilink->tonode = node;
- ilink->tosock = tosock_first;
- /* internal link is always valid */
- ilink->flag |= NODE_LINK_VALID;
- BLI_addtail(&node->internal_links, ilink);
- }
+ /* clean up */
+ for (output = node->outputs.first; output; output = output->next)
+ output->link = NULL;
}
float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 134a5c9575f..1e828ea321c 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -189,13 +189,16 @@ void register_node_tree_type_sh(void)
void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
{
+ /* localize tree to create links for reroute and mute */
+ bNodeTree *localtree = ntreeLocalize(ntree);
bNodeTreeExec *exec;
- exec = ntreeShaderBeginExecTree(ntree);
-
+ exec = ntreeShaderBeginExecTree(localtree);
ntreeExecGPUNodes(exec, mat, 1);
-
ntreeShaderEndExecTree(exec);
+
+ ntreeFreeTree_ex(localtree, false);
+ MEM_freeN(localtree);
}
/* **************** call to switch lamploop for material node ************ */
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index f6ecb3e0b72..86e59cd779a 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -195,25 +195,28 @@ static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNode
bNode *nodeGetActiveTexture(bNodeTree *ntree)
{
/* this is the node we texture paint and draw in textured draw */
- bNode *node, *tnode;
+ bNode *node, *tnode, *inactivenode = NULL;
if (!ntree)
return NULL;
- for (node = ntree->nodes.first; node; node = node->next)
+ for (node = ntree->nodes.first; node; node = node->next) {
if (node->flag & NODE_ACTIVE_TEXTURE)
return node;
+ else if (!inactivenode && node->typeinfo->nclass == NODE_CLASS_TEXTURE)
+ inactivenode = node;
+ }
/* node active texture node in this tree, look inside groups */
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP) {
tnode = nodeGetActiveTexture((bNodeTree *)node->id);
- if (tnode)
+ if (tnode && ((tnode->flag & NODE_ACTIVE_TEXTURE) || !inactivenode))
return tnode;
}
}
- return NULL;
+ return inactivenode;
}
void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs)
@@ -268,6 +271,9 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in
GPUNodeLink *tdomax = GPU_uniform(&domax);
GPU_link(mat, "mapping", in[0].link, tmat, tmin, tmax, tdomin, tdomax, &in[0].link);
+
+ if (texmap->type == TEXMAP_TYPE_NORMAL)
+ GPU_link(mat, "texco_norm", in[0].link, &in[0].link);
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
new file mode 100644
index 00000000000..ba33a262548
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
@@ -0,0 +1,66 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 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_bsdf_hair_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -M_PI_2, M_PI_2, PROP_ANGLE},
+ { SOCK_FLOAT, 1, N_("RoughnessU"), 0.1f, 0.1f, 0.1f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("RoughnessV"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_bsdf_hair_out[] = {
+ { SOCK_SHADER, 0, N_("BSDF")},
+ { -1, 0, "" }
+};
+
+static int node_shader_gpu_bsdf_hair(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ if (!in[2].link)
+ in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
+
+ return GPU_stack_link(mat, "node_bsdf_hair", in, out);
+}
+
+/* node type definition */
+void register_node_type_sh_bsdf_hair(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_BSDF_HAIR, "Hair BSDF", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_bsdf_hair_in, sh_node_bsdf_hair_out);
+ node_type_size(&ntype, 150, 60, 200);
+ node_type_init(&ntype, NULL);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_bsdf_hair);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index fad1a69d364..9956fd712c8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -41,6 +41,11 @@ static bNodeSocketTemplate sh_node_gamma_out[] = {
{ -1, 0, "" }
};
+static int node_shader_gpu_gamma(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "node_gamma", in, out);
+}
+
void register_node_type_sh_gamma(void)
{
static bNodeType ntype;
@@ -50,6 +55,7 @@ void register_node_type_sh_gamma(void)
node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_gamma);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index 05936e22775..cff4a039602 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -29,7 +29,6 @@
* \ingroup shdnodes
*/
-
#include "node_shader_util.h"
/* **************** MAPPING ******************** */
@@ -53,7 +52,7 @@ static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNo
/* stack order output: vector */
nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
mul_m4_v3(texmap->mat, vec);
-
+
if (texmap->flag & TEXMAP_CLIP_MIN) {
if (vec[0] < texmap->min[0]) vec[0] = texmap->min[0];
if (vec[1] < texmap->min[1]) vec[1] = texmap->min[1];
@@ -64,12 +63,15 @@ static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNo
if (vec[1] > texmap->max[1]) vec[1] = texmap->max[1];
if (vec[2] > texmap->max[2]) vec[2] = texmap->max[2];
}
+
+ if (texmap->type == TEXMAP_TYPE_NORMAL)
+ normalize_v3(vec);
}
static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage = add_tex_mapping();
+ node->storage = add_tex_mapping(TEXMAP_TYPE_POINT);
}
static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
@@ -83,7 +85,12 @@ static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUS
GPUNodeLink *tdomin = GPU_uniform(&domin);
GPUNodeLink *tdomax = GPU_uniform(&domax);
- return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax);
+ int result = GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax);
+
+ if (result && texmap->type == TEXMAP_TYPE_NORMAL)
+ GPU_link(mat, "texco_norm", out[0].link, &out[0].link);
+
+ return result;
}
void register_node_type_sh_mapping(void)
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 3bdc3813fd7..fd864f1c7c6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
+++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
@@ -30,11 +30,12 @@
/* **************** OUTPUT ******************** */
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_FLOAT, 1, N_("IOR"), 1.3f, 0.0f, 0.0f, 0.0f, 1.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},
+ { 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_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},
{ -1, 0, "" }
};
@@ -43,6 +44,20 @@ static bNodeSocketTemplate sh_node_subsurface_scattering_out[] = {
{ -1, 0, "" }
};
+static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ /*bNodeSocket *sock;*/
+
+ node->custom1 = SHD_SUBSURFACE_CUBIC;
+
+ /*for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (strcmp(sock->name, "Sharpness") == 0) {
+ bNodeSocketValueFloat *dval = sock->default_value;
+ dval->value = 0.0f;
+ }
+ }*/
+}
+
static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[1].link)
@@ -51,6 +66,22 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED
return GPU_stack_link(mat, "node_subsurface_scattering", in, out);
}
+static void node_shader_update_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock;
+ int falloff = node->custom1;
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (strcmp(sock->name, "Sharpness") == 0) {
+ if (falloff == SHD_SUBSURFACE_CUBIC)
+ sock->flag &= ~SOCK_UNAVAIL;
+ else
+ sock->flag |= SOCK_UNAVAIL;
+
+ }
+ }
+}
+
/* node type definition */
void register_node_type_sh_subsurface_scattering(void)
{
@@ -60,9 +91,10 @@ void register_node_type_sh_subsurface_scattering(void)
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_subsurface_scattering_in, sh_node_subsurface_scattering_out);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
- node_type_init(&ntype, NULL);
+ node_type_init(&ntype, node_shader_init_subsurface_scattering);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering);
+ node_type_update(&ntype, node_shader_update_subsurface_scattering, NULL);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index 826b7d9337d..12da301d090 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -51,7 +51,7 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = {
static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->offset = 0.5f;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
index ceb3911f429..725b5654523 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = {
static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
node->storage = tex;
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 2fbf5b6faf9..5e6471eab77 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = {
static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->color_space = SHD_COLORSPACE_COLOR;
tex->projection = SHD_PROJ_EQUIRECTANGULAR;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
index 5ee3b1f6176..c3ef897b1ad 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = {
static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexGradient *tex = MEM_callocN(sizeof(NodeTexGradient), "NodeTexGradient");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->gradient_type = SHD_BLEND_LINEAR;
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 53c44ebd715..1b705e12daf 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = {
static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->color_space = SHD_COLORSPACE_COLOR;
tex->iuser.frames = 1;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
index 38292939a3c..b9339bc483f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = {
static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->depth = 2;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index b41cc7d8812..2b5d5e12420 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -49,7 +49,7 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexMusgrave *tex = MEM_callocN(sizeof(NodeTexMusgrave), "NodeTexMusgrave");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->musgrave_type = SHD_MUSGRAVE_FBM;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index a7009b81e9a..36e26925501 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = {
static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
node->storage = tex;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
index f9cd4b72912..22061979b12 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -42,12 +42,14 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = {
static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->sun_direction[0] = 0.0f;
tex->sun_direction[1] = 0.0f;
tex->sun_direction[2] = 1.0f;
tex->turbidity = 2.2f;
+ tex->ground_albedo = 0.3f;
+ tex->sky_model = SHD_SKY_NEW;
node->storage = tex;
}
@@ -70,6 +72,7 @@ void register_node_type_sh_tex_sky(void)
sh_node_type_base(&ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_sky_in, sh_node_tex_sky_out);
+ node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, node_shader_init_tex_sky);
node_type_storage(&ntype, "NodeTexSky", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_sky);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
index 3f1b0638b99..f75c05601aa 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->coloring = SHD_VORONOI_INTENSITY;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
index a424265c94a..be7df85fbee 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
@@ -47,7 +47,7 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = {
static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave");
- default_tex_mapping(&tex->base.tex_mapping);
+ default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
default_color_mapping(&tex->base.color_mapping);
tex->wave_type = SHD_WAVE_BANDS;
diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c
index 6ab8d27f6e6..fec6abbf062 100644
--- a/source/blender/nodes/texture/nodes/node_texture_common.c
+++ b/source/blender/nodes/texture/nodes/node_texture_common.c
@@ -93,9 +93,12 @@ static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
for (node = ngroup->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP_INPUT) {
for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
- ns = node_get_socket_stack(gstack, sock);
- if (ns)
- copy_stack(ns, in[a]);
+ if (in[a]) { /* shouldn't need to check this [#36694] */
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns) {
+ copy_stack(ns, in[a]);
+ }
+ }
}
}
}
@@ -114,9 +117,12 @@ static void group_copy_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstac
for (node = ngroup->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
- ns = node_get_socket_stack(gstack, sock);
- if (ns)
- copy_stack(out[a], ns);
+ if (out[a]) { /* shouldn't need to check this [#36694] */
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns) {
+ copy_stack(out[a], ns);
+ }
+ }
}
break; /* only one active output node */
}
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 6c7fc686cc0..ec9f2865582 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -581,11 +581,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
item = PyDict_New();
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
- BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
- BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter);
+ BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
+ void *ele_val = BLI_ghashIterator_getValue(&hash_iter);
- PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key);
- PyObject *py_val = BPy_BMElem_CreatePyObject(bm, *(void **)BMO_OP_SLOT_MAPPING_DATA(ele_val));
+ PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key);
+ PyObject *py_val = BPy_BMElem_CreatePyObject(bm, ele_val);
PyDict_SetItem(item, py_key, py_val);
Py_DECREF(py_key);
@@ -599,11 +599,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
item = PyDict_New();
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
- BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
- BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter);
+ BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
+ void *ele_val = BLI_ghashIterator_getValue(&hash_iter);
PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key);
- PyObject *py_val = PyFloat_FromDouble(*(float *)BMO_OP_SLOT_MAPPING_DATA(ele_val));
+ PyObject *py_val = PyFloat_FromDouble(*(float *)&ele_val);
PyDict_SetItem(item, py_key, py_val);
Py_DECREF(py_key);
@@ -617,11 +617,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
item = PyDict_New();
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
- BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
- BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter);
+ BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
+ void *ele_val = BLI_ghashIterator_getValue(&hash_iter);
PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key);
- PyObject *py_val = PyLong_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val));
+ PyObject *py_val = PyLong_FromLong(*(int *)&ele_val);
PyDict_SetItem(item, py_key, py_val);
Py_DECREF(py_key);
@@ -635,11 +635,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
item = PyDict_New();
if (slot_hash) {
GHASH_ITER (hash_iter, slot_hash) {
- BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
- BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter);
+ BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter);
+ void *ele_val = BLI_ghashIterator_getValue(&hash_iter);
PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key);
- PyObject *py_val = PyBool_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val));
+ PyObject *py_val = PyBool_FromLong(*(int *)&ele_val);
PyDict_SetItem(item, py_key, py_val);
Py_DECREF(py_key);
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 0e2fbe8a526..92fb506497f 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -122,12 +122,12 @@ static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
param = PyLong_AsLong(value);
- if (param == true) {
- BM_elem_flag_enable(self->ele, hflag);
- return 0;
- }
- else if (param == false) {
- BM_elem_flag_disable(self->ele, hflag);
+ if ((unsigned int)param <= 1) {
+ if (hflag == BM_ELEM_SELECT)
+ BM_elem_select_set(self->bm, self->ele, param);
+ else
+ BM_elem_flag_set(self->ele, hflag, param);
+
return 0;
}
else {
@@ -1047,6 +1047,8 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *
int use_shape_key = false;
int shape_key_index = 0;
+ BPY_BM_CHECK_OBJ(self);
+
if (!PyArg_ParseTupleAndKeywords(args, kw, "O|iii:from_mesh", (char **)kwlist,
&py_mesh, &use_fnorm, &use_shape_key, &shape_key_index) ||
!(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
@@ -1871,7 +1873,7 @@ static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
return NULL;
}
- v = BM_vert_create(bm, co, NULL, 0);
+ v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
if (v == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1940,7 +1942,7 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
goto cleanup;
}
- e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, 0);
+ e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, BM_CREATE_NOP);
if (e == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -2020,7 +2022,8 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
/* Go ahead and make the face!
* --------------------------- */
- f_new = BM_face_create_ngon_verts(bm, vert_array, vert_seq_len, 0, false, true);
+ f_new = BM_face_create_verts(bm, vert_array, vert_seq_len,
+ py_face_example ? py_face_example->f : NULL, BM_CREATE_NOP, true);
if (UNLIKELY(f_new == NULL)) {
PyErr_SetString(PyExc_ValueError,
@@ -2028,10 +2031,6 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
goto cleanup;
}
- if (py_face_example) {
- BM_elem_attrs_copy(py_face_example->bm, bm, py_face_example->f, f_new);
- }
-
ret = BPy_BMFace_CreatePyObject(bm, f_new);
/* pass through */
@@ -2921,7 +2920,8 @@ static void bpy_bmvert_dealloc(BPy_BMElem *self)
BMesh *bm = self->bm;
if (bm) {
void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
- *ptr = NULL;
+ if (ptr)
+ *ptr = NULL;
}
PyObject_DEL(self);
}
@@ -2931,7 +2931,8 @@ static void bpy_bmedge_dealloc(BPy_BMElem *self)
BMesh *bm = self->bm;
if (bm) {
void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->head.data, CD_BM_ELEM_PYPTR);
- *ptr = NULL;
+ if (ptr)
+ *ptr = NULL;
}
PyObject_DEL(self);
}
@@ -2941,7 +2942,8 @@ static void bpy_bmface_dealloc(BPy_BMElem *self)
BMesh *bm = self->bm;
if (bm) {
void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
- *ptr = NULL;
+ if (ptr)
+ *ptr = NULL;
}
PyObject_DEL(self);
}
@@ -2951,7 +2953,8 @@ static void bpy_bmloop_dealloc(BPy_BMElem *self)
BMesh *bm = self->bm;
if (bm) {
void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->head.data, CD_BM_ELEM_PYPTR);
- *ptr = NULL;
+ if (ptr)
+ *ptr = NULL;
}
PyObject_DEL(self);
}
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index f02b94be526..0909ce0d26a 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -27,8 +27,8 @@
* \ingroup pybmesh
*/
-#ifndef __BMESH_TYPES_H__
-#define __BMESH_TYPES_H__
+#ifndef __BMESH_PY_TYPES_H__
+#define __BMESH_PY_TYPES_H__
extern PyTypeObject BPy_BMesh_Type;
extern PyTypeObject BPy_BMVert_Type;
@@ -205,4 +205,4 @@ extern struct PyC_FlagSet bpy_bm_htype_all_flags[];
extern struct PyC_FlagSet bpy_bm_hflag_all_flags[];
#endif
-#endif /* __BMESH_TYPES_H__ */
+#endif /* __BMESH_PY_TYPES_H__ */
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index b0604fa2dbc..30902c615a1 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -32,6 +32,7 @@
#include <Python.h>
+#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_math_vector.h"
diff --git a/source/blender/python/generic/blf_py_api.h b/source/blender/python/generic/blf_py_api.h
index 12bd9bcf019..d856e68faee 100644
--- a/source/blender/python/generic/blf_py_api.h
+++ b/source/blender/python/generic/blf_py_api.h
@@ -20,9 +20,13 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef __BLF_PY_API_H__
+#define __BLF_PY_API_H__
+
/** \file blender/python/generic/blf_py_api.h
* \ingroup pygen
*/
-
PyObject *BPyInit_blf(void);
+
+#endif /* __BLF_PY_API_H__ */
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index fc4b78b5c05..f7ed5fec891 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -1518,7 +1518,7 @@ void IDP_spit(IDProperty *prop)
{
if (prop) {
PyGILState_STATE gilstate;
- int use_gil = TRUE; /* !PYC_INTERPRETER_ACTIVE; */
+ int use_gil = TRUE; /* !PyC_IsInterpreterActive(); */
PyObject *ret_dict;
PyObject *ret_str;
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 2876d7666f4..63f66afd8a8 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -191,7 +191,7 @@ void PyC_LineSpit(void)
int lineno;
/* Note, allow calling from outside python (RNA) */
- if (!PYC_INTERPRETER_ACTIVE) {
+ if (!PyC_IsInterpreterActive()) {
fprintf(stderr, "python line lookup failed, interpreter inactive\n");
return;
}
@@ -205,7 +205,7 @@ void PyC_LineSpit(void)
void PyC_StackSpit(void)
{
/* Note, allow calling from outside python (RNA) */
- if (!PYC_INTERPRETER_ACTIVE) {
+ if (!PyC_IsInterpreterActive()) {
fprintf(stderr, "python line lookup failed, interpreter inactive\n");
return;
}
@@ -258,7 +258,7 @@ void PyC_FileAndNum(const char **filename, int *lineno)
void PyC_FileAndNum_Safe(const char **filename, int *lineno)
{
- if (!PYC_INTERPRETER_ACTIVE) {
+ if (!PyC_IsInterpreterActive()) {
return;
}
@@ -599,6 +599,11 @@ void PyC_SetHomePath(const char *py_path_bundle)
}
}
+bool PyC_IsInterpreterActive(void)
+{
+ return (((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL);
+}
+
/* Would be nice if python had this built in
* See: http://wiki.blender.org/index.php/Dev:Doc/Tools/Debugging/PyFromC
*/
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 239858032de..8928642bc3e 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -56,7 +56,7 @@ void PyC_MainModule_Restore(PyObject *main_mod);
void PyC_SetHomePath(const char *py_path_bundle);
-#define PYC_INTERPRETER_ACTIVE (((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL)
+bool PyC_IsInterpreterActive(void);
void *PyC_RNA_AsPointer(PyObject *value, const char *type_name);
diff --git a/source/blender/python/intern/bpy.h b/source/blender/python/intern/bpy.h
index fe877d161ff..b647d0d450c 100644
--- a/source/blender/python/intern/bpy.h
+++ b/source/blender/python/intern/bpy.h
@@ -24,6 +24,7 @@
*/
#ifndef __BPY_H__
+#define __BPY_H__
void BPy_init_modules(void);
extern PyObject *bpy_package_py;
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 90a0444ceae..959e4a788dd 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -57,6 +57,8 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{(char *)"save_post", (char *)"Callback list - on saving a blend file (after)"},
{(char *)"scene_update_pre", (char *)"Callback list - on updating the scenes data (before)"},
{(char *)"scene_update_post", (char *)"Callback list - on updating the scenes data (after)"},
+ {(char *)"game_pre", (char *)"Callback list - on starting the game engine"},
+ {(char *)"game_post", (char *)"Callback list - on ending the game engine"},
/* sets the permanent tag */
# define APP_CB_OTHER_FIELDS 1
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index 481758db252..7141db7352a 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -123,7 +123,7 @@ static void bpy_pydriver_update_dict(const float evaltime)
void BPY_driver_reset(void)
{
PyGILState_STATE gilstate;
- bool use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ bool use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -162,7 +162,7 @@ static void pydriver_error(ChannelDriver *driver)
*
* (old)note: PyGILState_Ensure() isn't always called because python can call
* the bake operator which intern starts a thread which calls scene update
- * which does a driver update. to avoid a deadlock check PYC_INTERPRETER_ACTIVE
+ * which does a driver update. to avoid a deadlock check PyC_IsInterpreterActive()
* if PyGILState_Ensure() is needed - see [#27683]
*
* (new)note: checking if python is running is not threadsafe [#28114]
@@ -199,7 +199,7 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
return 0.0f;
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index feffea20553..cc1dd369f8b 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -166,7 +166,7 @@ void BPY_text_free_code(Text *text)
{
if (text->compiled) {
PyGILState_STATE gilstate;
- bool use_gil = !PYC_INTERPRETER_ACTIVE;
+ bool use_gil = !PyC_IsInterpreterActive();
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -760,7 +760,7 @@ void BPY_modules_load_user(bContext *C)
int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result)
{
PyGILState_STATE gilstate;
- bool use_gil = !PYC_INTERPRETER_ACTIVE;
+ bool use_gil = !PyC_IsInterpreterActive();
PyObject *pyctx;
PyObject *item;
@@ -821,8 +821,12 @@ 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);
- else printf("PyContext '%s' not found\n", member);
+ if (item) {
+ printf("PyContext '%s' not a valid type\n", member);
+ }
+ else {
+ printf("PyContext '%s' not found\n", member);
+ }
}
else {
if (G.debug & G_DEBUG_PYTHON) {
diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h
index 2e0d18d8b7f..41b7303bf8d 100644
--- a/source/blender/python/intern/bpy_intern_string.h
+++ b/source/blender/python/intern/bpy_intern_string.h
@@ -20,6 +20,9 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef __BPY_INTERN_STRING_H__
+#define __BPY_INTERN_STRING_H__
+
/** \file blender/python/intern/bpy_intern_string.h
* \ingroup pythonintern
*/
@@ -36,3 +39,5 @@ extern PyObject *bpy_intern_str_attr;
extern PyObject *bpy_intern_str___slots__;
extern PyObject *bpy_intern_str___name__;
extern PyObject *bpy_intern_str___doc__;
+
+#endif /* __BPY_INTERN_STRING_H__ */
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index 65b7bf62032..efee9b13d58 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -177,14 +177,17 @@ PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args)
}
/* identifiers */
- srna = srna_from_self(macro, "Macro Define:");
- macroname = RNA_struct_identifier(srna);
+ srna = pyrna_struct_as_srna((PyObject *)macro, false, "Macro Define:");
+ if (srna == NULL) {
+ return NULL;
+ }
+ macroname = RNA_struct_identifier(srna);
ot = WM_operatortype_find(macroname, true);
if (!ot) {
PyErr_Format(PyExc_ValueError,
- "Macro Define: '%s' is not a valid macro or hasn't been registered yet",
+ "Macro Define: '%s' is not a valid macro",
macroname);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 9bd9d33a36c..bfa4954d4bc 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -256,7 +256,7 @@ static int bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -313,7 +313,7 @@ static void bpy_prop_boolean_set_cb(struct PointerRNA *ptr, struct PropertyRNA *
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -368,7 +368,7 @@ static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, struct Propert
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -430,7 +430,7 @@ static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct Propert
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -490,7 +490,7 @@ static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -547,7 +547,7 @@ static void bpy_prop_int_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -602,7 +602,7 @@ static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -664,7 +664,7 @@ static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -724,7 +724,7 @@ static float bpy_prop_float_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -781,7 +781,7 @@ static void bpy_prop_float_set_cb(struct PointerRNA *ptr, struct PropertyRNA *pr
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -836,7 +836,7 @@ static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, struct PropertyR
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -898,7 +898,7 @@ static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyR
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -957,7 +957,7 @@ static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -1017,7 +1017,7 @@ static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -1079,7 +1079,7 @@ static void bpy_prop_string_set_cb(struct PointerRNA *ptr, struct PropertyRNA *p
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -1140,7 +1140,7 @@ static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -1197,7 +1197,7 @@ static void bpy_prop_enum_set_cb(struct PointerRNA *ptr, struct PropertyRNA *pro
pyrna_write_set(true);
}
- use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PyC_IsInterpreterActive(); */
if (use_gil)
gilstate = PyGILState_Ensure();
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 3cd030e9b08..4d4d4873390 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1341,7 +1341,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
return pyrna_py_from_array(ptr, prop);
}
- /* see if we can coorce into a python type - PropertyType */
+ /* see if we can coerce into a python type - PropertyType */
switch (type) {
case PROP_BOOLEAN:
ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop));
@@ -1507,7 +1507,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
else {
/* Normal Property (not an array) */
- /* see if we can coorce into a python type - PropertyType */
+ /* see if we can coerce into a python type - PropertyType */
switch (type) {
case PROP_BOOLEAN:
{
@@ -4600,14 +4600,6 @@ PyDoc_STRVAR(pyrna_prop_collection_foreach_get_doc,
".. method:: foreach_get(attr, seq)\n"
"\n"
" This is a function to give fast access to attributes within a collection.\n"
-"\n"
-" .. code-block:: python\n"
-"\n"
-" collection.foreach_get(attr, someseq)\n"
-"\n"
-" # Python equivalent\n"
-" for i in range(len(seq)): someseq[i] = getattr(collection, attr)\n"
-"\n"
);
static PyObject *pyrna_prop_collection_foreach_get(BPy_PropertyRNA *self, PyObject *args)
{
@@ -4620,14 +4612,6 @@ PyDoc_STRVAR(pyrna_prop_collection_foreach_set_doc,
".. method:: foreach_set(attr, seq)\n"
"\n"
" This is a function to give fast access to attributes within a collection.\n"
-"\n"
-" .. code-block:: python\n"
-"\n"
-" collection.foreach_set(attr, seq)\n"
-"\n"
-" # Python equivalent\n"
-" for i in range(len(seq)): setattr(collection[i], attr, seq[i])\n"
-"\n"
);
static PyObject *pyrna_prop_collection_foreach_set(BPy_PropertyRNA *self, PyObject *args)
{
@@ -4887,7 +4871,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
}
}
else {
- /* see if we can coorce into a python type - PropertyType */
+ /* see if we can coerce into a python type - PropertyType */
switch (type) {
case PROP_BOOLEAN:
ret = PyBool_FromLong(*(int *)data);
@@ -5327,7 +5311,7 @@ static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *UNUSED(closure)
PyObject *ret;
char *args;
- args = RNA_function_as_string_keywords(NULL, self->func, NULL, true, true, INT_MAX);
+ args = RNA_function_as_string_keywords(NULL, self->func, true, true, INT_MAX);
ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s",
RNA_struct_identifier(self->ptr.type),
@@ -6875,7 +6859,7 @@ int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class)
/*-------------------- Type Registration ------------------------*/
-static int rna_function_arg_count(FunctionRNA *func)
+static int rna_function_arg_count(FunctionRNA *func, int *min_count)
{
const ListBase *lb = RNA_function_defined_parameters(func);
PropertyRNA *parm;
@@ -6883,13 +6867,23 @@ static int rna_function_arg_count(FunctionRNA *func)
int flag = RNA_function_flag(func);
int is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
int count = is_staticmethod ? 0 : 1;
+ bool done_min_count = false;
for (link = lb->first; link; link = link->next) {
parm = (PropertyRNA *)link;
- if (!(RNA_property_flag(parm) & PROP_OUTPUT))
+ if (!(RNA_property_flag(parm) & PROP_OUTPUT)) {
+ if (!done_min_count && (RNA_property_flag(parm) & PROP_PYFUNC_OPTIONAL)) {
+ /* From now on, following parameters are optional in py func */
+ if (min_count)
+ *min_count = count;
+ done_min_count = true;
+ }
count++;
+ }
}
+ if (!done_min_count && min_count)
+ *min_count = count;
return count;
}
@@ -6904,7 +6898,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
PyObject *py_class = (PyObject *)py_data;
PyObject *base_class = RNA_struct_py_type_get(srna);
PyObject *item;
- int i, flag, is_staticmethod, arg_count, func_arg_count;
+ int i, flag, is_staticmethod, arg_count, func_arg_count, func_arg_min_count = 0;
const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */
if (srna_base) {
@@ -6968,7 +6962,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
}
}
- func_arg_count = rna_function_arg_count(func);
+ func_arg_count = rna_function_arg_count(func, &func_arg_min_count);
if (func_arg_count >= 0) { /* -1 if we don't care*/
arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
@@ -6976,14 +6970,25 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
/* note, the number of args we check for and the number of args we give to
* @staticmethods are different (quirk of python),
* this is why rna_function_arg_count() doesn't return the value -1*/
- if (is_staticmethod)
+ if (is_staticmethod) {
func_arg_count++;
+ func_arg_min_count++;
+ }
- if (arg_count != func_arg_count) {
- PyErr_Format(PyExc_ValueError,
- "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d",
- class_type, py_class_name, RNA_function_identifier(func),
- func_arg_count, arg_count);
+ if (arg_count < func_arg_min_count || arg_count > func_arg_count) {
+ if (func_arg_min_count != func_arg_count) {
+ PyErr_Format(PyExc_ValueError,
+ "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d "
+ "args, found %d",
+ class_type, py_class_name, RNA_function_identifier(func),
+ func_arg_count, func_arg_min_count, arg_count);
+ }
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d",
+ class_type, py_class_name, RNA_function_identifier(func),
+ func_arg_count, arg_count);
+ }
return -1;
}
}
@@ -7063,7 +7068,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PropertyRNA *parm;
ParameterIterator iter;
PointerRNA funcptr;
- int err = 0, i, ret_len = 0;
+ int err = 0, i, ret_len = 0, arg_count;
int flag = RNA_function_flag(func);
const char is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
const char is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE);
@@ -7198,7 +7203,15 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (item) {
RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
- args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
+ if (is_staticmethod) {
+ arg_count = ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount - 1;
+ }
+ else {
+ arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
+ }
+// args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
+ args = PyTuple_New(arg_count); /* first arg is included in 'item' */
+
if (is_staticmethod) {
i = 0;
@@ -7230,9 +7243,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
continue;
}
- parmitem = pyrna_param_to_py(&funcptr, parm, iter.data);
- PyTuple_SET_ITEM(args, i, parmitem);
- i++;
+ if (i < arg_count) {
+ parmitem = pyrna_param_to_py(&funcptr, parm, iter.data);
+ PyTuple_SET_ITEM(args, i, parmitem);
+ i++;
+ }
}
#ifdef USE_PEDANTIC_WRITE
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index 6e78a543481..e473af9fac8 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -312,7 +312,8 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
BKE_reports_init(&reports, RPT_STORE);
- result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON);
+ result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index,
+ CREATEDRIVER_WITH_FMODIFIER, DRIVER_TYPE_PYTHON);
if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
return NULL;
diff --git a/source/blender/python/intern/bpy_rna_anim.h b/source/blender/python/intern/bpy_rna_anim.h
index 005e8f3e1a4..8ef976b8cb4 100644
--- a/source/blender/python/intern/bpy_rna_anim.h
+++ b/source/blender/python/intern/bpy_rna_anim.h
@@ -20,6 +20,9 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef __BPY_RNA_ANIM_H__
+#define __BPY_RNA_ANIM_H__
+
/** \file blender/python/intern/bpy_rna_anim.h
* \ingroup pythonintern
*/
@@ -33,3 +36,5 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw);
PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args);
PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args);
+
+#endif /* __BPY_RNA_ANIM_H__ */
diff --git a/source/blender/python/intern/bpy_rna_callback.h b/source/blender/python/intern/bpy_rna_callback.h
index 4b801f35654..6ef98790b4e 100644
--- a/source/blender/python/intern/bpy_rna_callback.h
+++ b/source/blender/python/intern/bpy_rna_callback.h
@@ -20,11 +20,13 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef __BPY_RNA_CALLBACK_H__
+#define __BPY_RNA_CALLBACK_H__
+
/** \file blender/python/intern/bpy_rna_callback.h
* \ingroup pythonintern
*/
-
struct BPy_StructRNA;
struct PyObject;
@@ -35,3 +37,5 @@ PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args);
PyObject *pyrna_callback_classmethod_add(PyObject *cls, PyObject *args);
PyObject *pyrna_callback_classmethod_remove(PyObject *cls, PyObject *args);
+
+#endif /* __BPY_RNA_CALLBACK_H__ */
diff --git a/source/blender/python/intern/gpu.h b/source/blender/python/intern/gpu.h
index f8c751f7f94..82338869b9d 100644
--- a/source/blender/python/intern/gpu.h
+++ b/source/blender/python/intern/gpu.h
@@ -27,10 +27,13 @@
/** \file blender/python/intern/gpu.h
* \ingroup pythonintern
- */
-
-/**
+ *
* Initializes the gpu Python module.
*/
+
+#ifndef __GPU_H__
+#define __GPU_H__
+
PyObject *GPU_initPython(void);
+#endif /* __GPU_H__ */
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 90e9565f05f..8f94fc8b467 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -510,10 +510,12 @@ PyMODINIT_FUNC PyInit_mathutils(void)
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
+#ifndef MATH_STANDALONE
/* Noise submodule */
PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
+#endif
mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb);
mathutils_matrix_col_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_col_cb);
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index d471cd05a2b..3e5dcc28903 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -522,18 +522,12 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
axis_angle_to_mat3((float (*)[3])mat, tvec, angle);
}
else if (matSize == 2) {
- const float angle_cos = cosf(angle);
- const float angle_sin = sinf(angle);
+ angle_to_mat2((float (*)[2])mat, angle);
- /* 2D rotation matrix */
- mat[0] = angle_cos;
- mat[1] = angle_sin;
- mat[2] = -angle_sin;
- mat[3] = angle_cos;
}
else {
/* valid axis checked above */
- single_axis_angle_to_mat3((float (*)[3])mat, axis[0], angle);
+ axis_angle_to_mat3_single((float (*)[3])mat, axis[0], angle);
}
if (matSize == 4) {
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index d44bce502ca..8a5a8446ac6 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1165,7 +1165,7 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
PyDoc_STRVAR(Vector_rotate_doc,
".. function:: rotate(other)\n"
"\n"
-" Return vector by a rotation value.\n"
+" Rotate the vector by a rotation value.\n"
"\n"
" :arg other: rotation component of mathutils value\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
@@ -1286,7 +1286,7 @@ static PyObject *vector_item_internal(VectorObject *self, int i, const int is_at
static PyObject *Vector_item(VectorObject *self, int i)
{
- return vector_item_internal(self, i, FALSE);
+ return vector_item_internal(self, i, false);
}
/* sequence accessor (set): vector[index] = value */
static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, const int is_attr)
@@ -1323,7 +1323,7 @@ static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value,
static int Vector_ass_item(VectorObject *self, int i, PyObject *value)
{
- return vector_ass_item_internal(self, i, value, FALSE);
+ return vector_ass_item_internal(self, i, value, false);
}
/* sequence slice (get): vector[a:b] */
@@ -2086,12 +2086,12 @@ PyDoc_STRVAR(Vector_axis_w_doc, "Vector W axis (4D Vectors only).\n\n:type: floa
static PyObject *Vector_axis_get(VectorObject *self, void *type)
{
- return vector_item_internal(self, GET_INT_FROM_POINTER(type), TRUE);
+ return vector_item_internal(self, GET_INT_FROM_POINTER(type), true);
}
static int Vector_axis_set(VectorObject *self, PyObject *value, void *type)
{
- return vector_ass_item_internal(self, GET_INT_FROM_POINTER(type), value, TRUE);
+ return vector_ass_item_internal(self, GET_INT_FROM_POINTER(type), value, true);
}
/* vector.length */
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 8509c46b395..8b5b74c480a 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -34,6 +34,7 @@
# include "MEM_guardedalloc.h"
# include "BLI_blenlib.h"
# include "BLI_boxpack2d.h"
+# include "BLI_convexhull2d.h"
# include "BKE_displist.h"
# include "BKE_curve.h"
#endif
@@ -568,22 +569,19 @@ PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc,
" :type plane_co: :class:`mathutils.Vector`\n"
" :arg plane_no: The direction the plane is facing\n"
" :type plane_no: :class:`mathutils.Vector`\n"
-" :arg no_flip: Always return an intersection on the directon defined bt line_a -> line_b\n"
-" :type no_flip: :boolean\n"
" :return: The point of intersection or None when not found\n"
" :rtype: :class:`mathutils.Vector` or None\n"
);
static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args)
{
VectorObject *line_a, *line_b, *plane_co, *plane_no;
- int no_flip = 0;
float isect[3];
+
if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane",
&vector_Type, &line_a,
&vector_Type, &line_b,
&vector_Type, &plane_co,
- &vector_Type, &plane_no,
- &no_flip))
+ &vector_Type, &plane_no))
{
return NULL;
}
@@ -603,7 +601,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec
return NULL;
}
- if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec, no_flip) == 1) {
+ if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec) == 1) {
return Vector_CreatePyObject(isect, 3, Py_NEW, NULL);
}
else {
@@ -692,7 +690,7 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
{
VectorObject *line_a, *line_b, *sphere_co;
float sphere_radius;
- int clip = TRUE;
+ int clip = true;
float isect_a[3];
float isect_b[3];
@@ -728,12 +726,12 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
switch (isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
case 1:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = FALSE;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
use_b = false;
break;
case 2:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = FALSE;
- if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = FALSE;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
break;
default:
use_a = false;
@@ -773,7 +771,7 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
{
VectorObject *line_a, *line_b, *sphere_co;
float sphere_radius;
- int clip = TRUE;
+ int clip = true;
float isect_a[2];
float isect_b[2];
@@ -803,7 +801,7 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
switch (isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
case 1:
if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
- use_b = FALSE;
+ use_b = false;
break;
case 2:
if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
@@ -980,24 +978,35 @@ PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
);
static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt, *plene_co, *plane_no;
+ VectorObject *pt, *plane_co, *plane_no;
+ float plane[4];
if (!PyArg_ParseTuple(args, "O!O!O!:distance_point_to_plane",
&vector_Type, &pt,
- &vector_Type, &plene_co,
+ &vector_Type, &plane_co,
&vector_Type, &plane_no))
{
return NULL;
}
+ if (pt->size != 3 ||
+ plane_co->size != 3 ||
+ plane_no->size != 3)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "One of more of the vector arguments wasn't a 3D vector");
+ return NULL;
+ }
+
if (BaseMath_ReadCallback(pt) == -1 ||
- BaseMath_ReadCallback(plene_co) == -1 ||
+ BaseMath_ReadCallback(plane_co) == -1 ||
BaseMath_ReadCallback(plane_no) == -1)
{
return NULL;
}
- return PyFloat_FromDouble(dist_to_plane_v3(pt->vec, plene_co->vec, plane_no->vec));
+ plane_from_point_normal_v3(plane, plane_co->vec, plane_no->vec);
+ return PyFloat_FromDouble(dist_to_plane_v3(pt->vec, plane));
}
PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
@@ -1054,6 +1063,17 @@ static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObje
return NULL;
}
+ if (BaseMath_ReadCallback(vec_pt) == -1 ||
+ BaseMath_ReadCallback(vec_t1_src) == -1 ||
+ BaseMath_ReadCallback(vec_t2_src) == -1 ||
+ BaseMath_ReadCallback(vec_t3_src) == -1 ||
+ BaseMath_ReadCallback(vec_t1_tar) == -1 ||
+ BaseMath_ReadCallback(vec_t2_tar) == -1 ||
+ BaseMath_ReadCallback(vec_t3_tar) == -1)
+ {
+ return NULL;
+ }
+
barycentric_transform(vec, vec_pt->vec,
vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec,
vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec);
@@ -1099,7 +1119,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
/* python */
PyObject *py_verts = PyList_New(0);
- PyObject *py_plene_index = PyList_New(0);
+ PyObject *py_plane_index = PyList_New(0);
memset(planes_used, 0, sizeof(char) * len);
@@ -1135,7 +1155,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
PyList_Append(py_verts, item);
Py_DECREF(item);
- planes_used[i] = planes_used[j] = planes_used[k] = TRUE;
+ planes_used[i] = planes_used[j] = planes_used[k] = true;
}
}
}
@@ -1151,7 +1171,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
for (i = 0; i < len; i++) {
if (planes_used[i]) {
PyObject *item = PyLong_FromLong(i);
- PyList_Append(py_plene_index, item);
+ PyList_Append(py_plane_index, item);
Py_DECREF(item);
}
}
@@ -1160,7 +1180,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
{
PyObject *ret = PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, py_verts);
- PyTuple_SET_ITEM(ret, 1, py_plene_index);
+ PyTuple_SET_ITEM(ret, 1, py_plane_index);
return ret;
}
}
@@ -1473,7 +1493,7 @@ static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlis
}
/* Non Python function */
- BLI_box_pack_2D(boxarray, len, &tot_width, &tot_height);
+ BLI_box_pack_2d(boxarray, len, &tot_width, &tot_height);
boxPack_ToPyObject(boxlist, &boxarray);
}
@@ -1484,6 +1504,87 @@ static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlis
return ret;
}
+PyDoc_STRVAR(M_Geometry_box_fit_2d_doc,
+".. function:: box_fit_2d(points)\n"
+"\n"
+" Returns an angle that best fits the points to an axis aligned rectangle\n"
+"\n"
+" :arg points: list of 2d points.\n"
+" :type points: list\n"
+" :return: angle\n"
+" :rtype: float\n"
+);
+static PyObject *M_Geometry_box_fit_2d(PyObject *UNUSED(self), PyObject *pointlist)
+{
+ float (*points)[2];
+ Py_ssize_t len;
+
+ float angle = 0.0f;
+
+ len = mathutils_array_parse_alloc_v(((float **)&points), 2, pointlist, "box_fit_2d");
+ if (len == -1) {
+ return NULL;
+ }
+
+ if (len) {
+ /* Non Python function */
+ angle = BLI_convexhull_aabb_fit_points_2d((const float (*)[2])points, len);
+
+ PyMem_Free(points);
+ }
+
+
+ return PyFloat_FromDouble(angle);
+}
+
+PyDoc_STRVAR(M_Geometry_convex_hull_2d_doc,
+".. function:: convex_hull_2d(points)\n"
+"\n"
+" Returns a list of indices into the list given\n"
+"\n"
+" :arg points: list of 2d points.\n"
+" :type points: list\n"
+" :return: a list of indices\n"
+" :rtype: list of ints\n"
+);
+static PyObject *M_Geometry_convex_hull_2d(PyObject *UNUSED(self), PyObject *pointlist)
+{
+ float (*points)[2];
+ Py_ssize_t len;
+
+ PyObject *ret;
+
+ len = mathutils_array_parse_alloc_v(((float **)&points), 2, pointlist, "convex_hull_2d");
+ if (len == -1) {
+ return NULL;
+ }
+
+ if (len) {
+ int *index_map;
+ Py_ssize_t len_ret, i;
+
+ index_map = MEM_mallocN(sizeof(*index_map) * len, __func__);
+
+ /* Non Python function */
+ len_ret = BLI_convexhull_2d((const float (*)[2])points, len, index_map);
+
+ ret = PyList_New(len_ret);
+ for (i = 0; i < len_ret; i++) {
+ PyList_SET_ITEM(ret, i, PyLong_FromLong(index_map[i]));
+ }
+
+ MEM_freeN(index_map);
+
+ PyMem_Free(points);
+ }
+ else {
+ ret = PyList_New(0);
+ }
+
+
+ return ret;
+}
+
#endif /* MATH_STANDALONE */
@@ -1508,6 +1609,8 @@ static PyMethodDef M_Geometry_methods[] = {
#ifndef MATH_STANDALONE
{"interpolate_bezier", (PyCFunction) M_Geometry_interpolate_bezier, METH_VARARGS, M_Geometry_interpolate_bezier_doc},
{"tessellate_polygon", (PyCFunction) M_Geometry_tessellate_polygon, METH_O, M_Geometry_tessellate_polygon_doc},
+ {"convex_hull_2d", (PyCFunction) M_Geometry_convex_hull_2d, METH_O, M_Geometry_convex_hull_2d_doc},
+ {"box_fit_2d", (PyCFunction) M_Geometry_box_fit_2d, METH_O, M_Geometry_box_fit_2d_doc},
{"box_pack_2d", (PyCFunction) M_Geometry_box_pack_2d, METH_O, M_Geometry_box_pack_2d_doc},
#endif
{NULL, NULL, 0, NULL}
diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m
index 7b42c89d936..8cf91e44c77 100644
--- a/source/blender/quicktime/apple/qtkit_export.m
+++ b/source/blender/quicktime/apple/qtkit_export.m
@@ -317,7 +317,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
int success = 1;
OSStatus err = noErr;
- if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport");
+ if (qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport");
[QTMovie enterQTKitOnThread];
@@ -476,7 +476,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
err = AudioFileCreateWithURL(outputFileURL, audioFileType, &qtexport->audioOutputFormat, kAudioFileFlags_EraseFile, &qtexport->audioFile);
CFRelease(outputFileURL);
- if(err)
+ if (err)
BKE_report(reports, RPT_ERROR, "\nQuicktime: unable to create temporary audio file. Format error ?");
else {
err = AudioConverterNew(&qtexport->audioInputFormat, &qtexport->audioOutputFormat, &qtexport->audioConverter);
@@ -542,7 +542,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
else
qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->filename error:&error];
- if(qtexport->movie == nil) {
+ if (qtexport->movie == nil) {
BKE_report(reports, RPT_ERROR, "Unable to create quicktime movie.");
success = 0;
if (qtexport->filename) [qtexport->filename release];
@@ -749,13 +749,11 @@ void end_qt(void)
if (audioTmpMovie) {
NSArray *audioTracks = [audioTmpMovie tracksOfMediaType:QTMediaTypeSound];
QTTrack *audioTrack = nil;
- if( [audioTracks count] > 0 )
- {
+ if ( [audioTracks count] > 0 ) {
audioTrack = [audioTracks objectAtIndex:0];
}
- if( audioTrack )
- {
+ if (audioTrack) {
QTTimeRange totalRange;
totalRange.time = QTZeroTime;
totalRange.duration = [[audioTmpMovie attributeForKey:QTMovieDurationAttribute] QTTimeValue];
@@ -798,7 +796,7 @@ void end_qt(void)
[QTMovie exitQTKitOnThread];
- if(qtexport) {
+ if (qtexport) {
MEM_freeN(qtexport);
qtexport = NULL;
}
diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m
index bee26c5348e..fbe4733c3b1 100644
--- a/source/blender/quicktime/apple/qtkit_import.m
+++ b/source/blender/quicktime/apple/qtkit_import.m
@@ -128,7 +128,7 @@ void free_anim_quicktime(struct anim *anim)
if (anim == NULL) return;
if (anim->qtime == NULL) return;
- if(anim->qtime->ibuf)
+ if (anim->qtime->ibuf)
IMB_freeImBuf(anim->qtime->ibuf);
[anim->qtime->media release];
@@ -136,7 +136,7 @@ void free_anim_quicktime(struct anim *anim)
[QTMovie exitQTKitOnThread];
- if(anim->qtime) MEM_freeN (anim->qtime);
+ if (anim->qtime) MEM_freeN (anim->qtime);
anim->qtime = NULL;
@@ -289,7 +289,7 @@ ImBuf *qtime_fetchibuf (struct anim *anim, int position)
}
if (frameImage == nil) {
- if(QTIME_DEBUG) printf ("Error reading frame from Quicktime");
+ if (QTIME_DEBUG) printf ("Error reading frame from Quicktime");
[pool drain];
return NULL;
}
@@ -312,7 +312,7 @@ int startquicktime(struct anim *anim)
anim->qtime = MEM_callocN(sizeof(QuicktimeMovie),"animqt");
if (anim->qtime == NULL) {
- if(QTIME_DEBUG) printf("Can't alloc qtime: %s\n", anim->name);
+ if (QTIME_DEBUG) printf("Can't alloc qtime: %s\n", anim->name);
return -1;
}
@@ -329,9 +329,9 @@ int startquicktime(struct anim *anim)
anim->qtime->movie = [QTMovie movieWithAttributes:attributes error:NULL];
if (!anim->qtime->movie) {
- if(QTIME_DEBUG) printf("qt: bad movie %s\n", anim->name);
+ if (QTIME_DEBUG) printf("qt: bad movie %s\n", anim->name);
MEM_freeN(anim->qtime);
- if(QTIME_DEBUG) printf("qt: can't load %s\n", anim->name);
+ if (QTIME_DEBUG) printf("qt: can't load %s\n", anim->name);
[QTMovie exitQTKitOnThread];
[pool drain];
return -1;
@@ -342,11 +342,11 @@ int startquicktime(struct anim *anim)
videoTracks = [anim->qtime->movie tracksOfMediaType:QTMediaTypeVideo];
- if([videoTracks count] == 0) {
- if(QTIME_DEBUG) printf("qt: no video tracks for movie %s\n", anim->name);
+ if ([videoTracks count] == 0) {
+ if (QTIME_DEBUG) printf("qt: no video tracks for movie %s\n", anim->name);
[anim->qtime->movie release];
MEM_freeN(anim->qtime);
- if(QTIME_DEBUG) printf("qt: can't load %s\n", anim->name);
+ if (QTIME_DEBUG) printf("qt: can't load %s\n", anim->name);
[QTMovie exitQTKitOnThread];
[pool drain];
return -1;
@@ -360,8 +360,8 @@ int startquicktime(struct anim *anim)
anim->x = frameSize.width;
anim->y = frameSize.height;
- if(anim->x == 0 && anim->y == 0) {
- if(QTIME_DEBUG) printf("qt: error, no dimensions\n");
+ if (anim->x == 0 && anim->y == 0) {
+ if (QTIME_DEBUG) printf("qt: error, no dimensions\n");
free_anim_quicktime(anim);
[pool drain];
return -1;
@@ -398,12 +398,12 @@ int imb_is_a_quicktime(char *name)
int result;
NSAutoreleasePool *pool;
- if(!G.have_quicktime) return 0;
+ if (!G.have_quicktime) return 0;
pool = [[NSAutoreleasePool alloc] init];
// don't let quicktime image import handle these
- if( BLI_testextensie(name, ".swf") ||
+ if (BLI_testextensie(name, ".swf") ||
BLI_testextensie(name, ".txt") ||
BLI_testextensie(name, ".mpg") ||
BLI_testextensie(name, ".wav") ||
@@ -437,7 +437,7 @@ ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags)
NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA;
NSAutoreleasePool *pool;
- if(!G.have_quicktime)
+ if (!G.have_quicktime)
return NULL;
pool = [[NSAutoreleasePool alloc] init];
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index e154fd42119..73a89ad884f 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -225,8 +225,8 @@ void RE_init_threadcount(Render *re);
void RE_TileProcessor(struct Render *re);
/* only RE_NewRender() needed, main Blender render calls */
-void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, unsigned int lay, int frame, const short write_still);
-void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, struct Object *camera_override, unsigned int lay, int sfra, int efra, int tfra);
+void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, unsigned int lay_override, int frame, const short write_still);
+void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, struct Object *camera_override, unsigned int lay_override, int sfra, int efra, int tfra);
#ifdef WITH_FREESTYLE
void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Scene *scene, int render);
#endif
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
index 2dc12f39db7..b23d6b09524 100644
--- a/source/blender/render/intern/include/texture.h
+++ b/source/blender/render/intern/include/texture.h
@@ -35,17 +35,17 @@
#define BRICONT \
texres->tin= (texres->tin-0.5f) * tex->contrast+tex->bright-0.5f; \
- if(texres->tin < 0.0f) texres->tin= 0.0f; \
- else if(texres->tin > 1.0f) texres->tin= 1.0f; \
+ if (texres->tin < 0.0f) texres->tin= 0.0f; \
+ else if (texres->tin > 1.0f) texres->tin= 1.0f; \
#define BRICONTRGB \
texres->tr= tex->rfac*((texres->tr-0.5f)*tex->contrast+tex->bright-0.5f); \
- if(texres->tr<0.0f) texres->tr= 0.0f; \
+ if (texres->tr<0.0f) texres->tr= 0.0f; \
texres->tg= tex->gfac*((texres->tg-0.5f)*tex->contrast+tex->bright-0.5f); \
- if(texres->tg<0.0f) texres->tg= 0.0f; \
+ if (texres->tg<0.0f) texres->tg= 0.0f; \
texres->tb= tex->bfac*((texres->tb-0.5f)*tex->contrast+tex->bright-0.5f); \
- if(texres->tb<0.0f) texres->tb= 0.0f; \
- if(tex->saturation != 1.0f) { \
+ if (texres->tb<0.0f) texres->tb= 0.0f; \
+ if (tex->saturation != 1.0f) { \
float _hsv[3]; \
rgb_to_hsv(texres->tr, texres->tg, texres->tb, \
_hsv, _hsv+1, _hsv+2); \
diff --git a/source/blender/render/intern/include/texture_ocean.h b/source/blender/render/intern/include/texture_ocean.h
index 121142aa0b0..4a71aff930a 100644
--- a/source/blender/render/intern/include/texture_ocean.h
+++ b/source/blender/render/intern/include/texture_ocean.h
@@ -26,6 +26,10 @@
#ifndef __TEXTURE_OCEAN_H__
#define __TEXTURE_OCEAN_H__
+/** \file blender/render/intern/include/texture_ocean.h
+ * \ingroup render
+ */
+
int ocean_texture(struct Tex *tex, const float texvec[2], struct TexResult *texres);
#endif /* __TEXTURE_OCEAN_H__ */
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 564cca09834..6e70e670ff8 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -647,6 +647,8 @@ static int get_next_bake_face(BakeShade *bs)
const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
+ const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
+ const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
@@ -686,6 +688,8 @@ static int get_next_bake_face(BakeShade *bs)
if (R.r.bake_flag & R_BAKE_CLEAR) {
if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ else if (R.r.bake_mode == RE_BAKE_DISPLACEMENT)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
else
IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
}
@@ -828,8 +832,11 @@ static void shade_tface(BakeShade *bs)
}
}
- if (bs->use_displacement_buffer)
- userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp");
+ if (bs->use_displacement_buffer) {
+ if (userdata->displacement_buffer == NULL) {
+ userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp");
+ }
+ }
bs->ibuf->userdata = userdata;
@@ -1081,12 +1088,12 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
userdata = (BakeImBufuserData *)ibuf->userdata;
if (userdata) {
- RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter);
-
if (use_displacement_buffer) {
RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
displacement_min, displacement_max);
}
+
+ RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter);
}
ibuf->userflags |= IB_BITMAPDIRTY;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index ab888ba198b..a0104a30d0e 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1741,7 +1741,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
}
if (path_nbr == 0)
- psys->lattice = psys_get_lattice(&sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
/* 3. start creating renderable things */
for (a=0, pa=pars; a<totpart+totchild; a++, pa++, seed++) {
@@ -2094,9 +2094,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
psys->flag &= ~PSYS_DRAWING;
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice= NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
if (path_nbr && (ma->mode_l & MA_TANGENT_STR)==0)
@@ -3279,7 +3279,7 @@ static EdgeHash *make_freestyle_edge_mark_hash(Mesh *me, DerivedMesh *dm)
index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
fed = CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE);
if (fed) {
- edge_hash = BLI_edgehash_new();
+ edge_hash = BLI_edgehash_new(__func__);
if (!index) {
if (me->totedge == totedge) {
for (a = 0; a < me->totedge; a++) {
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index ea22423985b..827a1f8f113 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -49,6 +49,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "RNA_access.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -392,6 +394,17 @@ RenderData *RE_engine_get_render_data(Render *re)
/* Render */
+static bool render_layer_exclude_animated(Scene *scene, SceneRenderLayer *srl)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ RNA_pointer_create(&scene->id, &RNA_SceneRenderLayer, srl, &ptr);
+ prop = RNA_struct_find_property(&ptr, "layers_exclude");
+
+ return RNA_property_animated(&ptr, prop);
+}
+
int RE_engine_render(Render *re, int do_all)
{
RenderEngineType *type = RE_engines_find(re->r.engine);
@@ -420,13 +433,25 @@ int RE_engine_render(Render *re, int do_all)
if (re->r.scemode & R_SINGLE_LAYER) {
srl = BLI_findlink(&re->r.layers, re->r.actlay);
- if (srl)
+ if (srl) {
non_excluded_lay |= ~srl->lay_exclude;
+
+ /* in this case we must update all because animation for
+ * the scene has not been updated yet, and so may not be
+ * up to date until after BKE_scene_update_for_newframe */
+ if (render_layer_exclude_animated(re->scene, srl))
+ non_excluded_lay |= ~0;
+ }
}
else {
- for (srl = re->r.layers.first; srl; srl = srl->next)
- if (!(srl->layflag & SCE_LAY_DISABLE))
+ for (srl = re->r.layers.first; srl; srl = srl->next) {
+ if (!(srl->layflag & SCE_LAY_DISABLE)) {
non_excluded_lay |= ~srl->lay_exclude;
+
+ if (render_layer_exclude_animated(re->scene, srl))
+ non_excluded_lay |= ~0;
+ }
+ }
}
lay &= non_excluded_lay;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 899c9b335be..6118d479cab 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -630,6 +630,22 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
RE_init_threadcount(re);
}
+/* update some variables that can be animated, and otherwise wouldn't be due to
+ * RenderData getting copied once at the start of animation render */
+static void render_update_anim_renderdata(Render *re, RenderData *rd)
+{
+ /* filter */
+ re->r.gauss = rd->gauss;
+
+ /* motion blur */
+ re->r.mblur_samples = rd->mblur_samples;
+ re->r.blurfac = rd->blurfac;
+
+ /* freestyle */
+ re->r.line_thickness_mode = rd->line_thickness_mode;
+ re->r.unit_line_thickness = rd->unit_line_thickness;
+}
+
void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
{
/* re->ok flag? */
@@ -1697,12 +1713,17 @@ static void composite_freestyle_renders(Render *re, int sample)
for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
continue;
+
if (FRS_is_freestyle_enabled(srl)) {
freestyle_render = (Render *)link->data;
- render_result_exr_file_read(freestyle_render, sample);
- FRS_composite_result(re, srl, freestyle_render);
- RE_FreeRenderResult(freestyle_render->result);
- freestyle_render->result = NULL;
+
+ /* may be NULL in case of empty render layer */
+ if (freestyle_render) {
+ render_result_exr_file_read(freestyle_render, sample);
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
}
link = link->next;
}
@@ -1717,8 +1738,9 @@ static void free_all_freestyle_renders(void)
for (re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) {
- if (link->data) {
- freestyle_render = (Render *)link->data;
+ freestyle_render = (Render *)link->data;
+
+ if (freestyle_render) {
freestyle_scene = freestyle_render->scene;
RE_FreeRender(freestyle_render);
BKE_scene_unlink(&re1->freestyle_bmain, freestyle_scene, NULL);
@@ -1752,6 +1774,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba");
for (sample = 0; sample < re->r.osa; sample++) {
+ Scene *sce;
Render *re1;
RenderResult rres;
int mask;
@@ -1763,9 +1786,11 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
/* also function below assumes this */
tag_scenes_for_render(re);
- for (re1 = RenderGlobal.renderlist.first; re1; re1 = re1->next) {
- if (re1->scene->id.flag & LIB_DOIT) {
- if (re1->r.scemode & R_FULL_SAMPLE) {
+ for (sce = re->main->scene.first; sce; sce = sce->id.next) {
+ if (sce->id.flag & LIB_DOIT) {
+ re1 = RE_GetRender(sce->id.name);
+
+ if (re1 && (re1->r.scemode & R_FULL_SAMPLE)) {
if (sample) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
render_result_exr_file_read(re1, sample);
@@ -2364,7 +2389,7 @@ static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)
BKE_ptcache_bake(&baker);
}
/* evaluating scene options for general Blender render */
-static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay, int anim, int anim_init)
+static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay_override, int anim, int anim_init)
{
int winx, winy;
rcti disprect;
@@ -2394,11 +2419,12 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc
re->scene = scene;
re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
re->camera_override = camera_override;
- re->lay = lay;
- re->i.localview = (lay & 0xFF000000) != 0;
+ re->lay = lay_override ? lay_override : scene->lay;
+ re->i.localview = (re->lay & 0xFF000000) != 0;
/* not too nice, but it survives anim-border render */
if (anim) {
+ render_update_anim_renderdata(re, &scene->r);
re->disprect = disprect;
return 1;
}
@@ -2443,14 +2469,14 @@ void RE_SetReports(Render *re, ReportList *reports)
}
/* general Blender frame render call */
-void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay, int frame, const short write_still)
+void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override, unsigned int lay_override, int frame, const short write_still)
{
/* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
G.is_rendering = TRUE;
scene->r.cfra = frame;
- if (render_initialize_from_main(re, bmain, scene, srl, camera_override, lay, 0, 0)) {
+ if (render_initialize_from_main(re, bmain, scene, srl, camera_override, lay_override, 0, 0)) {
MEM_reset_peak_memory();
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
@@ -2516,7 +2542,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
}
- IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
&scene->display_settings, &scene->r.im_format);
ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect,
@@ -2547,7 +2573,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
else {
ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
- IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
&scene->display_settings, &scene->r.im_format);
ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format);
@@ -2567,7 +2593,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
BKE_add_image_extension(name, &imf);
ibuf->planes = 24;
- IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings,
&scene->display_settings, &imf);
BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf);
@@ -2599,14 +2625,14 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
}
/* saves images to disk */
-void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_override, unsigned int lay, int sfra, int efra, int tfra)
+void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_override, unsigned int lay_override, int sfra, int efra, int tfra)
{
bMovieHandle *mh = BKE_movie_handle_get(scene->r.im_format.imtype);
int cfrao = scene->r.cfra;
int nfra, totrendered = 0, totskipped = 0;
/* do not fully call for each frame, it initializes & pops output window */
- if (!render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay, 0, 1))
+ if (!render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay_override, 0, 1))
return;
/* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */
@@ -2651,7 +2677,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
char name[FILE_MAX];
/* only border now, todo: camera lens. (ton) */
- render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay, 1, 0);
+ render_initialize_from_main(re, bmain, scene, NULL, camera_override, lay_override, 1, 0);
if (nfra != scene->r.cfra) {
/*
@@ -2909,7 +2935,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
return 0;
}
- IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, &scene->display_settings, &imf);
+ IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf);
/* to save, we first get absolute path */
BLI_strncpy(filepath, relpath, sizeof(filepath));
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index d4d6bfa5b7f..ce87888b6a0 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -140,7 +140,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
invert_m4_m4(ob->imat, ob->obmat);
total_particles = psys->totpart+psys->totchild;
- psys->lattice=psys_get_lattice(&sim);
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
alloc_point_data(pd, total_particles, data_used);
@@ -215,9 +215,9 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa
BLI_bvhtree_balance(pd->point_tree);
dm->release(dm);
- if (psys->lattice) {
- end_latt_deform(psys->lattice);
- psys->lattice = NULL;
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
}
psys_render_restore(ob, psys);
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 7ae64d499fa..90ae39ee767 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -734,6 +734,15 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
ShadeInput shi = {NULL};
Isect isec;
float dist_mir = origshi->mat->dist_mir;
+
+ /* with high depth the number of rays can explode due to the path splitting
+ * in two each time, giving 2^depth rays. we need to be able to cancel such
+ * a render to avoid hanging, a better solution would be random picking
+ * between directions and russian roulette termination */
+ if (R.test_break(R.tbh)) {
+ zero_v4(col);
+ return;
+ }
copy_v3_v3(isec.start, start);
copy_v3_v3(isec.dir, dir);
@@ -2308,9 +2317,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, const float lampco[3],
}
copy_v3_v3(isec->start, start);
- isec->dir[0] = end[0]-isec->start[0];
- isec->dir[1] = end[1]-isec->start[1];
- isec->dir[2] = end[2]-isec->start[2];
+ sub_v3_v3v3(isec->dir, end, start);
isec->dist = normalize_v3(isec->dir);
if (shi->obi->flag & R_ENV_TRANSFORMED)
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 1f740e3f483..37587d89ce0 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -1191,7 +1191,7 @@ void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rec
}
else if (rr->rectf) {
IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
- view_settings, display_settings, TRUE);
+ view_settings, display_settings, true);
}
else
/* else fill with black */
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index fa3cf1cef87..982e9b1a410 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -1957,36 +1957,38 @@ void add_halo_flare(Render *re)
RenderResult *rr= re->result;
RenderLayer *rl;
HaloRen *har;
- int a, mode, do_draw = FALSE;
+ int a, mode;
/* for now, we get the first renderlayer in list with halos set */
- for (rl= rr->layers.first; rl; rl= rl->next)
- if (rl->layflag & SCE_LAY_HALO)
- break;
-
- if (rl==NULL || rl->rectf==NULL)
- return;
-
- mode= R.r.mode;
- R.r.mode &= ~R_PANORAMA;
-
- project_renderdata(&R, projectverto, 0, 0, 0);
-
- for (a=0; a<R.tothalo; a++) {
- har= R.sortedhalos[a];
+ for (rl= rr->layers.first; rl; rl= rl->next) {
+ int do_draw = FALSE;
+
+ if ((rl->layflag & SCE_LAY_HALO) == 0)
+ continue;
+ if (rl->rectf==NULL)
+ continue;
- if (har->flarec) {
- do_draw = TRUE;
- renderflare(rr, rl->rectf, har);
+ mode= R.r.mode;
+ R.r.mode &= ~R_PANORAMA;
+
+ project_renderdata(&R, projectverto, 0, 0, 0);
+
+ for (a=0; a<R.tothalo; a++) {
+ har= R.sortedhalos[a];
+
+ if (har->flarec && (har->lay & rl->lay)) {
+ do_draw = TRUE;
+ renderflare(rr, rl->rectf, har);
+ }
+ }
+
+ if (do_draw) {
+ /* weak... the display callback wants an active renderlayer pointer... */
+ rr->renlay= rl;
+ re->display_draw(re->ddh, rr, NULL);
}
- }
- if (do_draw) {
- /* weak... the display callback wants an active renderlayer pointer... */
- rr->renlay= rl;
- re->display_draw(re->ddh, rr, NULL);
+ R.r.mode= mode;
}
-
- R.r.mode= mode;
}
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 0d85cfe78b7..0c3bf85cd24 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -1373,7 +1373,7 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3])
/* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */
- while (1) {
+ do {
lambda_o= lambda;
if (lambda_x==lambda_y) {
@@ -1394,7 +1394,13 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3])
}
lambda = min_ff(lambda_x, lambda_y);
-
+
+ /* not making any progress? */
+ if (lambda==lambda_o) break;
+
+ /* clip to end of volume */
+ lambda = min_ff(lambda, 1.0f);
+
zf= zf1 + lambda*(zf2-zf1);
count+= (float)shb->totbuf;
@@ -1409,10 +1415,9 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3])
lightcount+= readshadowbuf_halo(shb, shsample, x, y, z);
}
- /* break after sample, so it takes at least one */
- if (lambda==lambda_o || lambda>=1.0f) break;
}
-
+ while (lambda < 1.0f);
+
if (count!=0.0f) return (lightcount/count);
return 0.0f;
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 178d304eca2..114961394c4 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1191,8 +1191,8 @@ float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *d
float visifac= 1.0f, t;
sub_v3_v3v3(lv, co, lar->co);
- *dist= sqrtf(dot_v3v3(lv, lv));
- t= 1.0f/dist[0];
+ *dist = len_v3(lv);
+ t = 1.0f / (*dist);
mul_v3_fl(lv, t);
/* area type has no quad or sphere option */
diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c
index a7547479093..0d68c40be0f 100644
--- a/source/blender/render/intern/source/texture_ocean.c
+++ b/source/blender/render/intern/source/texture_ocean.c
@@ -23,6 +23,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/blenkernel/intern/texture_ocean.c
+ * \ingroup bke
+ */
+
#include <stddef.h>
#include "BLI_math.h"
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 3f19e77946c..0936d5fcef9 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -109,8 +109,8 @@ static int load_frame_blendervoxel(VoxelData *vd, FILE *fp, int frame)
static int load_frame_raw8(VoxelData *vd, FILE *fp, int frame)
{
const size_t size = vd_resol_size(vd);
+ size_t i;
char *data_c;
- int i;
if (is_vd_res_ok(vd) == FALSE)
return 0;
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index d65db9d47f8..a8ccd1f362f 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -911,7 +911,7 @@ void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4])
void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec,
const float ho1[4], const float ho2[4], const float ho3[4], const float ho4[4],
- int c1, int c2, int c3, int c4)
+ const int c1, const int c2, const int c3, const int c4)
{
float vez[20];
int and, or;
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 8894be111e7..84b376edcd8 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -40,6 +40,7 @@
/* dna-savable wmStructs here */
#include "DNA_windowmanager_types.h"
#include "WM_keymap.h"
+#include "BLI_compiler_attrs.h"
#ifdef __cplusplus
extern "C" {
@@ -76,17 +77,9 @@ void WM_init_native_pixels(bool do_it);
void WM_init (struct bContext *C, int argc, const char **argv);
void WM_exit_ext (struct bContext *C, const short do_python);
-void WM_exit (struct bContext *C)
-#if defined(__GNUC__) || defined(__clang__)
-__attribute__((noreturn))
-#endif
-;
+void WM_exit (struct bContext *C) ATTR_NORETURN;
-void WM_main (struct bContext *C)
-#if defined(__GNUC__) || defined(__clang__)
-__attribute__((noreturn))
-#endif
-;
+void WM_main (struct bContext *C) ATTR_NORETURN;
bool WM_init_game (struct bContext *C);
void WM_init_splash (struct bContext *C);
@@ -118,9 +111,9 @@ void WM_autosave_init(struct wmWindowManager *wm);
void WM_recover_last_session(struct bContext *C, struct ReportList *reports);
/* mouse cursors */
-void WM_cursor_set (struct wmWindow *win, int curs);
-void WM_cursor_modal (struct wmWindow *win, int curs);
-void WM_cursor_restore (struct wmWindow *win);
+void WM_cursor_set(struct wmWindow *win, int curs);
+void WM_cursor_modal_set(struct wmWindow *win, int curs);
+void WM_cursor_modal_restore(struct wmWindow *win);
void WM_cursor_wait (bool val);
void WM_cursor_grab_enable(struct wmWindow *win, bool wrap, bool hide, int bounds[4]);
void WM_cursor_grab_disable(struct wmWindow *win, int mouse_ungrab_xy[2]);
@@ -151,9 +144,9 @@ struct wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers,
void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap);
struct wmEventHandler *WM_event_add_ui_handler(
- const struct bContext *C, ListBase *handlers,
- int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata),
- void (*remove)(struct bContext *C, void *userdata), void *userdata);
+ const struct bContext *C, ListBase *handlers,
+ int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata),
+ void (*remove)(struct bContext *C, void *userdata), void *userdata);
void WM_event_remove_ui_handler(ListBase *handlers,
int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata),
@@ -180,11 +173,7 @@ void WM_main_remove_notifier_reference(const void *reference);
/* reports */
void WM_report(const struct bContext *C, ReportType type, const char *message);
-void WM_reportf(const struct bContext *C, ReportType type, const char *format, ...)
-#ifdef __GNUC__
-__attribute__ ((format(printf, 3, 4)))
-#endif
-;
+void WM_reportf(const struct bContext *C, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4);
void wm_event_add(struct wmWindow *win, const struct wmEvent *event_to_add);
void wm_event_init_from_window(struct wmWindow *win, struct wmEvent *event);
@@ -197,7 +186,8 @@ void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, str
/* operator api, default callbacks */
/* invoke callback, uses enum property named "type" */
-int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op);
+int WM_operator_smooth_viewtx_get(const struct wmOperator *op);
int WM_menu_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
/* invoke callback, confirm menu + exec */
@@ -386,6 +376,7 @@ struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void
int WM_jobs_test(struct wmWindowManager *wm, void *owner, int job_type);
float WM_jobs_progress(struct wmWindowManager *wm, void *owner);
char *WM_jobs_name(struct wmWindowManager *wm, void *owner);
+void *WM_jobs_customdata(struct wmWindowManager *wm, void *owner);
int WM_jobs_is_running(struct wmJob *);
void *WM_jobs_customdata_get(struct wmJob *);
@@ -402,7 +393,7 @@ void WM_jobs_stop(struct wmWindowManager *wm, void *owner, void *startjob);
void WM_jobs_kill(struct wmWindowManager *wm, void *owner, void (*)(void *, short int *, short int *, float *));
void WM_jobs_kill_all(struct wmWindowManager *wm);
void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner);
-void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type);
+void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type);
int WM_jobs_has_running(struct wmWindowManager *wm);
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index cebafcea12d..121e5e401fa 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -44,7 +44,7 @@ struct EnumPropertyItem;
wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname);
wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, const char *idname);
-int WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf);
+bool WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf);
void WM_keyconfig_free (struct wmKeyConfig *keyconf);
void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname);
@@ -64,7 +64,7 @@ wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, in
wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type,
int val, int modifier, int keymodifier);
-int WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
+bool WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len);
wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid);
@@ -72,6 +72,7 @@ wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int sp
wmKeyMap *WM_keymap_find_all(const struct bContext *C, const char *idname, int spaceid, int regionid);
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);
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 f1932c8aa97..ac9af832671 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 "BLI_compiler_attrs.h"
/* exported types for WM */
#include "wm_cursors.h"
@@ -260,7 +261,6 @@ typedef struct wmNotifier {
#define ND_EDITOR_CHANGED (6<<16) /*sent to new editors after switching to them*/
#define ND_SCREENSET (7<<16)
#define ND_SKETCH (8<<16)
-#define ND_SUBWINACTIVE (9<<16)
/* NC_SCENE Scene */
#define ND_SCENEBROWSE (1<<16)
@@ -522,12 +522,8 @@ typedef struct wmOperatorType {
* parameters may be provided through operator properties. cannot use
* any interface code or input device state.
* - see defines below for return values */
- int (*exec)(struct bContext *, struct wmOperator *)
-#ifdef __GNUC__
- __attribute__((warn_unused_result))
-#endif
- ;
-
+ int (*exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT;
+
/* this callback executes on a running operator whenever as property
* is changed. It can correct its own properties or report errors for
* invalid settings in exceptional cases.
@@ -538,25 +534,13 @@ typedef struct wmOperatorType {
* any further events are handled in modal. if the operation is
* canceled due to some external reason, cancel is called
* - see defines below for return values */
- int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *)
-#ifdef __GNUC__
- __attribute__((warn_unused_result))
-#endif
- ;
+ int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
int (*cancel)(struct bContext *, struct wmOperator *);
- int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *)
-#ifdef __GNUC__
- __attribute__((warn_unused_result))
-#endif
- ;
+ int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
/* verify if the operator can be executed in the current context, note
* that the operator might still fail to execute even if this return true */
- int (*poll)(struct bContext *)
-#ifdef __GNUC__
- __attribute__((warn_unused_result))
-#endif
- ;
+ int (*poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT;
/* optional panel for redo and repeat, autogenerated if not set */
void (*ui)(struct bContext *, struct wmOperator *);
@@ -580,11 +564,7 @@ typedef struct wmOperatorType {
/* only used for operators defined with python
* use to store pointers to python functions */
void *pyop_data;
- int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot)
-#ifdef __GNUC__
- __attribute__((warn_unused_result))
-#endif
- ;
+ int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT;
/* RNA integration */
ExtensionRNA ext;
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 89c0cde2e88..74c066d1d86 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -156,8 +156,7 @@ void WM_operator_stack_clear(wmWindowManager *wm)
{
wmOperator *op;
- while ((op = wm->operators.first)) {
- BLI_remlink(&wm->operators, op);
+ while ((op = BLI_pophead(&wm->operators))) {
WM_operator_free(op);
}
@@ -226,7 +225,7 @@ void WM_uilisttype_freelink(uiListType *ult)
/* called on initialize WM_init() */
void WM_uilisttype_init(void)
{
- uilisttypes_hash = BLI_ghash_str_new("uilisttypes_hash gh");
+ uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16);
}
void WM_uilisttype_free(void)
@@ -279,7 +278,8 @@ void WM_menutype_freelink(MenuType *mt)
/* called on initialize WM_init() */
void WM_menutype_init(void)
{
- menutypes_hash = BLI_ghash_str_new("menutypes_hash gh");
+ /* reserve size is set based on blender default setup */
+ menutypes_hash = BLI_ghash_str_new_ex("menutypes_hash gh", 512);
}
void WM_menutype_free(void)
@@ -413,20 +413,17 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
if (wm->autosavetimer)
wm_autosave_timer_ended(wm);
- while ((win = wm->windows.first)) {
- BLI_remlink(&wm->windows, win);
+ while ((win = BLI_pophead(&wm->windows))) {
win->screen = NULL; /* prevent draw clear to use screen */
wm_draw_window_clear(win);
wm_window_free(C, wm, win);
}
- while ((op = wm->operators.first)) {
- BLI_remlink(&wm->operators, op);
+ while ((op = BLI_pophead(&wm->operators))) {
WM_operator_free(op);
}
- while ((keyconf = wm->keyconfigs.first)) {
- BLI_remlink(&wm->keyconfigs, keyconf);
+ while ((keyconf = BLI_pophead(&wm->keyconfigs))) {
WM_keyconfig_free(keyconf);
}
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 515f80b0ade..9b308553006 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -49,6 +49,7 @@
#include "WM_types.h"
#include "WM_api.h"
#include "wm_cursors.h"
+#include "wm_window.h"
/* XXX this still is mess from old code */
@@ -149,7 +150,7 @@ void WM_cursor_set(wmWindow *win, int curs)
}
}
-void WM_cursor_modal(wmWindow *win, int val)
+void WM_cursor_modal_set(wmWindow *win, int val)
{
if (win->lastcursor == 0)
win->lastcursor = win->cursor;
@@ -157,7 +158,7 @@ void WM_cursor_modal(wmWindow *win, int val)
WM_cursor_set(win, val);
}
-void WM_cursor_restore(wmWindow *win)
+void WM_cursor_modal_restore(wmWindow *win)
{
win->modalcursor = 0;
if (win->lastcursor)
@@ -174,10 +175,10 @@ void WM_cursor_wait(bool val)
for (; win; win = win->next) {
if (val) {
- WM_cursor_modal(win, BC_WAITCURSOR);
+ WM_cursor_modal_set(win, BC_WAITCURSOR);
}
else {
- WM_cursor_restore(win);
+ WM_cursor_modal_restore(win);
}
}
}
@@ -233,25 +234,32 @@ void WM_cursor_grab_disable(wmWindow *win, int mouse_ungrab_xy[2])
}
}
+static void wm_cursor_warp_relative(wmWindow *win, int x, int y)
+{
+ /* note: don't use wmEvent coords because of continuous grab [#36409] */
+ int cx, cy;
+ wm_get_cursor_position(win, &cx, &cy);
+ WM_cursor_warp(win, cx + x, cy + y);
+}
+
/* give it a modal keymap one day? */
int wm_cursor_arrow_move(wmWindow *win, wmEvent *event)
{
if (win && event->val == KM_PRESS) {
-
if (event->type == UPARROWKEY) {
- WM_cursor_warp(win, event->x, event->y + 1);
+ wm_cursor_warp_relative(win, 0, 1);
return 1;
}
else if (event->type == DOWNARROWKEY) {
- WM_cursor_warp(win, event->x, event->y - 1);
+ wm_cursor_warp_relative(win, 0, -1);
return 1;
}
else if (event->type == LEFTARROWKEY) {
- WM_cursor_warp(win, event->x - 1, event->y);
+ wm_cursor_warp_relative(win, -1, 0);
return 1;
}
else if (event->type == RIGHTARROWKEY) {
- WM_cursor_warp(win, event->x + 1, event->y);
+ wm_cursor_warp_relative(win, 1, 0);
return 1;
}
}
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 0c78338c18a..4c58089f4e7 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -226,17 +226,17 @@ static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event)
/* check buttons (XXX todo rna and value) */
if (UI_but_active_drop_name(C) ) {
- strcpy(drag->opname, IFACE_("Paste name"));
+ BLI_strncpy(drag->opname, IFACE_("Paste name"), sizeof(drag->opname));
}
else {
const char *opname = wm_dropbox_active(C, drag, event);
if (opname) {
- BLI_strncpy(drag->opname, opname, FILE_MAX);
- // WM_cursor_modal(win, CURSOR_COPY);
+ BLI_strncpy(drag->opname, opname, sizeof(drag->opname));
+ // WM_cursor_modal_set(win, CURSOR_COPY);
}
// else
- // WM_cursor_restore(win);
+ // WM_cursor_modal_restore(win);
/* unsure about cursor type, feels to be too much */
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index b4f193bdbe6..825c1ca9252 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -85,10 +85,11 @@
# include "RNA_enum_types.h"
#endif
+static void wm_notifier_clear(wmNotifier *note);
static void update_tablet_data(wmWindow *win, wmEvent *event);
static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
- short context, short poll_only);
+ const short context, const bool poll_only);
/* ************ event management ************** */
@@ -126,8 +127,7 @@ void wm_event_free_all(wmWindow *win)
{
wmEvent *event;
- while ((event = win->queue.first)) {
- BLI_remlink(&win->queue, event);
+ while ((event = BLI_pophead(&win->queue))) {
wm_event_free(event);
}
}
@@ -218,19 +218,18 @@ void WM_main_remove_notifier_reference(const void *reference)
note_next = note->next;
if (note->reference == reference) {
- BLI_remlink(&wm->queue, note);
- MEM_freeN(note);
+ /* don't remove because this causes problems for #wm_event_do_notifiers
+ * which may be looping on the data (deleting screens) */
+ wm_notifier_clear(note);
}
}
}
}
-static wmNotifier *wm_notifier_next(wmWindowManager *wm)
+static void wm_notifier_clear(wmNotifier *note)
{
- wmNotifier *note = wm->queue.first;
-
- if (note) BLI_remlink(&wm->queue, note);
- return note;
+ /* NULL the entire notifier, only leaving (next, prev) members intact */
+ memset(((char *)note) + sizeof(Link), 0, sizeof(*note) - sizeof(Link));
}
/* called in mainloop */
@@ -265,7 +264,6 @@ void wm_event_do_notifiers(bContext *C)
if (note->category == NC_SCREEN) {
if (note->data == ND_SCREENBROWSE) {
/* free popup handlers only [#35434] */
- wmWindow *win = CTX_wm_window(C);
UI_remove_popup_handlers_all(C, &win->modalhandlers);
@@ -308,7 +306,7 @@ void wm_event_do_notifiers(bContext *C)
}
/* the notifiers are sent without context, to keep it clean */
- while ( (note = wm_notifier_next(wm)) ) {
+ while ((note = BLI_pophead(&wm->queue))) {
for (win = wm->windows.first; win; win = win->next) {
/* filter out notifiers */
@@ -493,7 +491,7 @@ int WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
static void wm_operator_print(bContext *C, wmOperator *op)
{
/* context is needed for enum function */
- char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
+ char *buf = WM_operator_pystring(C, op->type, op->ptr, false);
printf("%s\n", buf);
MEM_freeN(buf);
}
@@ -628,7 +626,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, int cal
if (op->type->flag & OPTYPE_REGISTER) {
if (G.background == 0) { /* ends up printing these in the terminal, gets annoying */
/* Report the python string representation of the operator */
- char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
+ char *buf = WM_operator_pystring(C, op->type, op->ptr, false);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
MEM_freeN(buf);
}
@@ -662,7 +660,7 @@ static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
if (repeat == 0) {
if (G.debug & G_DEBUG_WM) {
- char *buf = WM_operator_pystring(C, op->type, op->ptr, 1);
+ char *buf = WM_operator_pystring(C, op->type, op->ptr, false);
BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
MEM_freeN(buf);
}
@@ -964,9 +962,8 @@ int WM_operator_last_properties_store(wmOperator *UNUSED(op))
#endif
static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
- PointerRNA *properties, ReportList *reports, short poll_only)
+ PointerRNA *properties, ReportList *reports, const bool poll_only)
{
- wmWindowManager *wm = CTX_wm_manager(C);
int retval = OPERATOR_PASS_THROUGH;
/* this is done because complicated setup is done to call this function that is better not duplicated */
@@ -974,9 +971,12 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
return WM_operator_poll(C, ot);
if (WM_operator_poll(C, ot)) {
+ wmWindowManager *wm = CTX_wm_manager(C);
wmOperator *op = wm_operator_create(wm, ot, properties, reports); /* if reports == NULL, they'll be initialized */
const short is_nested_call = (wm->op_undo_depth != 0);
+ op->flag |= OP_IS_INVOKE;
+
/* initialize setting from previous run */
if (!is_nested_call) { /* not called by py script */
WM_operator_last_properties_init(op);
@@ -1102,9 +1102,8 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
*
* invokes operator in context */
static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
- short context, short poll_only)
+ const short context, const bool poll_only)
{
- wmWindow *window = CTX_wm_window(C);
wmEvent *event;
int retval;
@@ -1113,16 +1112,23 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA
/* dummie test */
if (ot && C) {
+ wmWindow *window = CTX_wm_window(C);
+
switch (context) {
case WM_OP_INVOKE_DEFAULT:
case WM_OP_INVOKE_REGION_WIN:
case WM_OP_INVOKE_AREA:
case WM_OP_INVOKE_SCREEN:
/* window is needed for invoke, cancel operator */
- if (window == NULL)
+ if (window == NULL) {
+ if (poll_only) {
+ CTX_wm_operator_poll_msg_set(C, "Missing 'window' in context");
+ }
return 0;
- else
+ }
+ else {
event = window->eventstate;
+ }
break;
default:
event = NULL;
@@ -1323,9 +1329,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
wmWindowManager *wm = CTX_wm_manager(C);
/* C is zero on freeing database, modal handlers then already were freed */
- while ((handler = handlers->first)) {
- BLI_remlink(handlers, handler);
-
+ while ((handler = BLI_pophead(handlers))) {
if (handler->op) {
if (handler->op->type->cancel) {
ScrArea *area = CTX_wm_area(C);
@@ -2100,7 +2104,7 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
win->screen->do_draw_drag = TRUE;
/* restore cursor (disabled, see wm_dragdrop.c) */
- // WM_cursor_restore(win);
+ // WM_cursor_modal_restore(win);
}
/* overlap fails otherwise */
@@ -2167,7 +2171,7 @@ void wm_event_do_handlers(bContext *C)
while ( (event = win->queue.first) ) {
int action = WM_HANDLER_CONTINUE;
-#ifdef DEBUG
+#ifndef NDEBUG
if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
printf("\n%s: Handling event\n", __func__);
WM_event_print(event);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index f4b50667b2f..cc4d422331d 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -554,7 +554,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
}
if (success == 0) {
- success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL);
+ success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true);
if (wmbase.first == NULL) wm_clear_default_size(C);
BLI_init_temporary_dir(U.tempdir);
@@ -810,15 +810,14 @@ int write_crash_blend(void)
}
}
-int wm_file_write(bContext *C, const char *target, int fileflags, ReportList *reports)
+int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *reports)
{
Library *li;
int len;
- char filepath[FILE_MAX];
int *thumb = NULL;
ImBuf *ibuf_thumb = NULL;
- len = strlen(target);
+ len = strlen(filepath);
if (len == 0) {
BKE_report(reports, RPT_ERROR, "Path is empty, cannot save");
@@ -830,9 +829,9 @@ int wm_file_write(bContext *C, const char *target, int fileflags, ReportList *re
return -1;
}
- BLI_strncpy(filepath, target, FILE_MAX);
- BLI_replace_extension(filepath, FILE_MAX, ".blend");
- /* don't use 'target' anymore */
+ /* note: used to replace the file extension (to ensure '.blend'),
+ * no need to now because the operator ensures,
+ * its handy for scripts to save to a predefined name without blender editing it */
/* send the OnSave event */
for (li = G.main->library.first; li; li = li->id.next) {
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index adf159bcfee..05ee23e2361 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -40,6 +40,7 @@
#include "BLI_math.h"
#include "BLI_scanfill.h" /* lasso tessellation */
#include "BLI_utildefines.h"
+#include "BLI_lasso.h"
#include "BKE_context.h"
@@ -231,56 +232,73 @@ static void wm_gesture_draw_circle(wmGesture *gt)
}
-static void draw_filled_lasso(wmGesture *gt)
+struct LassoFillData {
+ unsigned int *px;
+ int width;
+};
+
+static void draw_filled_lasso_px_cb(int x, int y, void *user_data)
+{
+ struct LassoFillData *data = user_data;
+ unsigned char *col = (unsigned char *)&(data->px[(y * data->width) + x]);
+ col[0] = col[1] = col[2] = 0xff;
+ col[3] = 0x10;
+}
+
+static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
{
- ScanFillContext sf_ctx;
- ScanFillVert *sf_vert = NULL, *sf_vert_last = NULL, *sf_vert_first = NULL;
- ScanFillFace *sf_tri;
short *lasso = (short *)gt->customdata;
+ const int tot = gt->points;
+ int (*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__);
int i;
-
- BLI_scanfill_begin(&sf_ctx);
- for (i = 0; i < gt->points; i++, lasso += 2) {
- float co[3];
-
- co[0] = (float)lasso[0];
- co[1] = (float)lasso[1];
- co[2] = 0.0f;
-
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
- if (sf_vert_last)
- /* e = */ /* UNUSED */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
- sf_vert_last = sf_vert;
- if (sf_vert_first == NULL) sf_vert_first = sf_vert;
+ rcti rect;
+ rcti rect_win;
+
+ for (i = 0; i < tot; i++, lasso += 2) {
+ moves[i][0] = lasso[0];
+ moves[i][1] = lasso[1];
}
-
- /* highly unlikely this will fail, but could crash if (gt->points == 0) */
- if (sf_vert_first) {
- const float zvec[3] = {0.0f, 0.0f, 1.0f};
- BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
- BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES, zvec);
-
+
+ BLI_lasso_boundbox(&rect, (const int (*)[2])moves, tot);
+
+ wm_subwindow_getrect(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);
+
+ /* highly unlikely this will fail, but could crash if (tot == 0) */
+ if (BLI_rcti_is_empty(&rect) == false) {
+ const int w = BLI_rcti_size_x(&rect);
+ const int h = BLI_rcti_size_y(&rect);
+ unsigned int *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__);
+ struct LassoFillData lasso_fill_data = {pixel_buf, w};
+
+ fill_poly_v2i_n(
+ rect.xmin, rect.ymin, rect.xmax, rect.ymax,
+ (const int (*)[2])moves, tot,
+ draw_filled_lasso_px_cb, &lasso_fill_data);
+
glEnable(GL_BLEND);
- glColor4f(1.0, 1.0, 1.0, 0.05);
- glBegin(GL_TRIANGLES);
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- glVertex2fv(sf_tri->v1->co);
- glVertex2fv(sf_tri->v2->co);
- glVertex2fv(sf_tri->v3->co);
- }
- glEnd();
+ // glColor4f(1.0, 1.0, 1.0, 0.05);
+
+ glRasterPos2f(rect.xmin, rect.ymin);
+
+ glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_buf);
+
glDisable(GL_BLEND);
-
- BLI_scanfill_end(&sf_ctx);
+ MEM_freeN(pixel_buf);
}
+
+ MEM_freeN(moves);
}
-static void wm_gesture_draw_lasso(wmGesture *gt)
+
+static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt)
{
short *lasso = (short *)gt->customdata;
int i;
- draw_filled_lasso(gt);
+ draw_filled_lasso(win, gt);
glEnable(GL_LINE_STIPPLE);
glColor3ub(96, 96, 96);
@@ -347,9 +365,9 @@ void wm_gesture_draw(wmWindow *win)
wm_gesture_draw_cross(win, gt);
}
else if (gt->type == WM_GESTURE_LINES)
- wm_gesture_draw_lasso(gt);
+ wm_gesture_draw_lasso(win, gt);
else if (gt->type == WM_GESTURE_LASSO)
- wm_gesture_draw_lasso(gt);
+ wm_gesture_draw_lasso(win, gt);
else if (gt->type == WM_GESTURE_STRAIGHTLINE)
wm_gesture_draw_line(gt);
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 63cf1eeb40d..4e9b849af40 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -51,6 +51,7 @@
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BKE_blender.h"
@@ -510,6 +511,8 @@ void WM_exit_ext(bContext *C, const short do_python)
GHOST_DisposeSystemPaths();
+ BLI_threadapi_exit();
+
if (MEM_get_memory_blocks_in_use() != 0) {
printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use());
MEM_printmemlist();
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index c6e067dc2f9..c9c3d2df788 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -255,6 +255,17 @@ char *WM_jobs_name(wmWindowManager *wm, void *owner)
return NULL;
}
+void *WM_jobs_customdata(wmWindowManager *wm, void *owner)
+{
+ wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY);
+
+ if (wm_job)
+ return WM_jobs_customdata_get(wm_job);
+
+ return NULL;
+
+}
+
int WM_jobs_is_running(wmJob *wm_job)
{
return wm_job->running;
@@ -463,15 +474,16 @@ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner)
}
-void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type)
+void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type)
{
wmJob *wm_job, *next_job;
for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) {
next_job = wm_job->next;
- if (wm_job->job_type == job_type)
- wm_jobs_kill_job(wm, wm_job);
+ if (!owner || wm_job->owner == owner)
+ if (wm_job->job_type == job_type)
+ wm_jobs_kill_job(wm, wm_job);
}
}
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index ff805579b44..43a98a4600b 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -101,7 +101,7 @@ static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
if (strcmp(a->idname, b->idname) != 0)
return 0;
- if (!RNA_struct_equals(a->ptr, b->ptr, true))
+ if (!RNA_struct_equals(a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE))
return 0;
if ((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE))
@@ -190,7 +190,7 @@ wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
return keyconf;
}
-int WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
+bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
{
if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) {
if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) {
@@ -201,10 +201,10 @@ int WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
BLI_remlink(&wm->keyconfigs, keyconf);
WM_keyconfig_free(keyconf);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -299,6 +299,21 @@ void WM_keymap_free(wmKeyMap *keymap)
BLI_freelistN(&keymap->items);
}
+bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap)
+{
+ if (BLI_findindex(&keyconf->keymaps, keymap) != -1) {
+
+ WM_keymap_free(keymap);
+ BLI_remlink(&keyconf->keymaps, keymap);
+ MEM_freeN(keymap);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier)
{
kmi->type = type;
@@ -375,7 +390,7 @@ wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type,
return kmi;
}
-int WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
+bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
{
if (BLI_findindex(&keymap->items, kmi) != -1) {
if (kmi->ptr) {
@@ -385,10 +400,10 @@ int WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
BLI_freelinkN(&keymap->items, kmi);
WM_keyconfig_update_tag(keymap, NULL);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index f1a9f6dc007..5e1e5890c6b 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -542,22 +542,20 @@ char *WM_operator_pystring(bContext *C, wmOperatorType *ot, PointerRNA *opptr, i
/* only to get the orginal props for comparisons */
PointerRNA opptr_default;
- if (all_args == 0 || opptr == NULL) {
+ if (opptr == NULL) {
WM_operator_properties_create_ptr(&opptr_default, ot);
-
- if (opptr == NULL)
- opptr = &opptr_default;
+ opptr = &opptr_default;
}
WM_operator_py_idname(idname_py, ot->idname);
BLI_dynstr_appendf(dynstr, "bpy.ops.%s(", idname_py);
- cstring_args = RNA_pointer_as_string_keywords(C, opptr, &opptr_default, FALSE,
+ cstring_args = RNA_pointer_as_string_keywords(C, opptr, false,
all_args, max_prop_length);
BLI_dynstr_append(dynstr, cstring_args);
MEM_freeN(cstring_args);
- if (all_args == 0 || opptr == &opptr_default)
+ if (opptr == &opptr_default)
WM_operator_properties_free(&opptr_default);
BLI_dynstr_append(dynstr, ")");
@@ -796,7 +794,7 @@ void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, con
void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
{
- RNA_STRUCT_BEGIN(ptr, prop)
+ RNA_STRUCT_BEGIN (ptr, prop)
{
switch (RNA_property_type(prop)) {
case PROP_ENUM:
@@ -833,7 +831,7 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
int WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
{
int is_change = FALSE;
- RNA_STRUCT_BEGIN(ptr, prop)
+ RNA_STRUCT_BEGIN (ptr, prop)
{
switch (RNA_property_type(prop)) {
case PROP_POINTER:
@@ -866,7 +864,7 @@ void WM_operator_properties_reset(wmOperator *op)
PropertyRNA *iterprop;
iterprop = RNA_struct_iterator_property(op->type->srna);
- RNA_PROP_BEGIN(op->ptr, itemptr, iterprop)
+ RNA_PROP_BEGIN (op->ptr, itemptr, iterprop)
{
PropertyRNA *prop = itemptr.data;
@@ -892,33 +890,38 @@ void WM_operator_properties_free(PointerRNA *ptr)
/* ************ default op callbacks, exported *********** */
-int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *UNUSED(event))
+void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ if (op->flag & OP_IS_INVOKE) {
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
- const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
+ const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
- /* always run, so the values are initialized,
- * otherwise we may get differ behavior when (dia != 1.0) */
- RNA_STRUCT_BEGIN(op->ptr, prop)
- {
- if (RNA_property_type(prop) == PROP_FLOAT) {
- PropertySubType pstype = RNA_property_subtype(prop);
- if (pstype == PROP_DISTANCE) {
- /* we don't support arrays yet */
- BLI_assert(RNA_property_array_check(prop) == FALSE);
- /* initialize */
- if (!RNA_property_is_set_ex(op->ptr, prop, FALSE)) {
- const float value = RNA_property_float_get_default(op->ptr, prop) * dia;
- RNA_property_float_set(op->ptr, prop, value);
+ /* always run, so the values are initialized,
+ * otherwise we may get differ behavior when (dia != 1.0) */
+ RNA_STRUCT_BEGIN (op->ptr, prop)
+ {
+ if (RNA_property_type(prop) == PROP_FLOAT) {
+ PropertySubType pstype = RNA_property_subtype(prop);
+ if (pstype == PROP_DISTANCE) {
+ /* we don't support arrays yet */
+ BLI_assert(RNA_property_array_check(prop) == FALSE);
+ /* initialize */
+ if (!RNA_property_is_set_ex(op->ptr, prop, FALSE)) {
+ const float value = RNA_property_float_get_default(op->ptr, prop) * dia;
+ RNA_property_float_set(op->ptr, prop, value);
+ }
}
}
}
+ RNA_STRUCT_END;
}
- RNA_STRUCT_END;
+}
- return op->type->exec(C, op);
+int WM_operator_smooth_viewtx_get(const wmOperator *op)
+{
+ return (op->flag & OP_IS_INVOKE) ? U.smooth_viewtx : 0;
}
/* invoke callback, uses enum property named "type" */
@@ -1137,10 +1140,16 @@ void WM_operator_properties_select_all(wmOperatorType *ot)
void WM_operator_properties_border(wmOperatorType *ot)
{
- RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+ PropertyRNA *prop;
+
+ prop = RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect)
@@ -1171,14 +1180,18 @@ void WM_operator_properties_mouse_select(wmOperatorType *ot)
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
{
- RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX);
+ PropertyRNA *prop;
+
+ prop = RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
if (cursor) {
- PropertyRNA *prop;
-
prop = RNA_def_int(ot->srna, "cursor", cursor, 0, INT_MAX,
"Cursor", "Mouse cursor style to use during the modal operator", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN);
@@ -1553,7 +1566,7 @@ static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg
static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unused);
-/* XXX: hack to refresh splash screen with updated prest menu name,
+/* XXX: hack to refresh splash screen with updated preset menu name,
* since popup blocks don't get regenerated like panels do */
static void wm_block_splash_refreshmenu(bContext *UNUSED(C), void *UNUSED(arg_block), void *UNUSED(arg))
{
@@ -1668,7 +1681,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url",
"http://www.blender.org/development/credits");
uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url",
- "http://www.blender.org/development/release-logs/blender-268");
+ "http://www.blender.org/development/release-logs/blender-269");
uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url",
"http://wiki.blender.org/index.php/Doc:2.6/Manual");
uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org");
@@ -2253,7 +2266,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
}
else {
- RNA_BEGIN(op->ptr, itemptr, "files")
+ RNA_BEGIN (op->ptr, itemptr, "files")
{
RNA_string_get(&itemptr, "name", name);
BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
@@ -2419,15 +2432,10 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot)
/* *************** save file as **************** */
-static void untitled(char *filepath)
+static void wm_filepath_default(char *filepath)
{
- if (G.save_over == 0 && strlen(filepath) < FILE_MAX - 16) {
- char *c = (char *)BLI_last_slash(filepath);
-
- if (c)
- strcpy(&c[1], "untitled.blend");
- else
- strcpy(filepath, "untitled.blend");
+ if (G.save_over == false) {
+ BLI_ensure_filename(filepath, FILE_MAX, "untitled.blend");
}
}
@@ -2455,7 +2463,7 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent
else
BLI_strncpy(name, G.main->name, FILE_MAX);
- untitled(name);
+ wm_filepath_default(name);
RNA_string_set(op->ptr, "filepath", name);
WM_event_add_fileselect(C, op);
@@ -2471,11 +2479,12 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
save_set_compress(op);
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ if (RNA_struct_property_is_set(op->ptr, "filepath")) {
RNA_string_get(op->ptr, "filepath", path);
+ }
else {
BLI_strncpy(path, G.main->name, FILE_MAX);
- untitled(path);
+ wm_filepath_default(path);
}
fileflags = G.fileflags & ~G_FILE_USERPREFS;
@@ -2566,7 +2575,7 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
else
BLI_strncpy(name, G.main->name, FILE_MAX);
- untitled(name);
+ wm_filepath_default(name);
RNA_string_set(op->ptr, "filepath", name);
@@ -2750,7 +2759,7 @@ static void wm_gesture_end(bContext *C, wmOperator *op)
ED_area_tag_redraw(CTX_wm_area(C));
if (RNA_struct_find_property(op->ptr, "cursor") )
- WM_cursor_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(CTX_wm_window(C));
}
int WM_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -3059,7 +3068,7 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wm_gesture_tag_redraw(C);
if (RNA_struct_find_property(op->ptr, "cursor") )
- WM_cursor_modal(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
return OPERATOR_RUNNING_MODAL;
}
@@ -3074,7 +3083,7 @@ int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wm_gesture_tag_redraw(C);
if (RNA_struct_find_property(op->ptr, "cursor") )
- WM_cursor_modal(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
return OPERATOR_RUNNING_MODAL;
}
@@ -3199,7 +3208,7 @@ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op,
int i = 0;
mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__);
- RNA_PROP_BEGIN(op->ptr, itemptr, prop)
+ RNA_PROP_BEGIN (op->ptr, itemptr, prop)
{
float loc[2];
@@ -3225,7 +3234,7 @@ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op,
static int gesture_lasso_exec(bContext *C, wmOperator *op)
{
- RNA_BEGIN(op->ptr, itemptr, "path")
+ RNA_BEGIN (op->ptr, itemptr, "path")
{
float loc[2];
@@ -3291,7 +3300,7 @@ int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *e
wm_gesture_tag_redraw(C);
if (RNA_struct_find_property(op->ptr, "cursor") )
- WM_cursor_modal(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
+ WM_cursor_modal_set(CTX_wm_window(C), RNA_int_get(op->ptr, "cursor"));
return OPERATOR_RUNNING_MODAL;
}
@@ -3385,6 +3394,7 @@ typedef struct {
int initial_mouse[2];
unsigned int gltex;
ListBase orig_paintcursors;
+ bool use_secondary_tex;
void *cursor;
} RadialControl;
@@ -3428,7 +3438,7 @@ static void radial_control_set_tex(RadialControl *rc)
switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) {
case ID_BR:
- if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data))) {
+ if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data, rc->use_secondary_tex))) {
glGenTextures(1, &rc->gltex);
glBindTexture(GL_TEXTURE_2D, rc->gltex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ibuf->x, ibuf->y, 0,
@@ -3701,6 +3711,8 @@ static int radial_control_get_properties(bContext *C, wmOperator *op)
}
}
+ rc->use_secondary_tex = RNA_boolean_get(op->ptr, "secondary_tex");
+
return 1;
}
@@ -3894,6 +3906,7 @@ static void WM_OT_radial_control(wmOperatorType *ot)
RNA_def_string(ot->srna, "fill_color_path", "", 0, "Fill Color Path", "Path of property used to set the fill color of the control");
RNA_def_string(ot->srna, "zoom_path", "", 0, "Zoom Path", "Path of property used to set the zoom level for the control");
RNA_def_string(ot->srna, "image_id", "", 0, "Image ID", "Path of ID that is used to generate an image for the control");
+ RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
}
/* ************************** timer for testing ***************** */
@@ -4142,7 +4155,8 @@ void wm_operatortype_free(void)
/* called on initialize WM_init() */
void wm_operatortype_init(void)
{
- global_ops_hash = BLI_ghash_str_new("wm_operatortype_init gh");
+ /* reserve size is set based on blender default setup */
+ global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048);
WM_operatortype_append(WM_OT_window_duplicate);
WM_operatortype_append(WM_OT_read_history);
@@ -4259,6 +4273,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf)
/* assign map to operators */
WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line");
WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient");
+ WM_modalkeymap_assign(keymap, "MESH_OT_bisect");
}
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index e8ab1fef8b7..a02fc75a3fb 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -13,7 +13,7 @@
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * 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.
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 4ad4286b657..ae535ed45e8 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -148,6 +148,15 @@ void wm_subwindow_getmatrix(wmWindow *win, int swinid, float mat[4][4])
}
}
+void wm_subwindow_getrect(wmWindow *win, int swinid, rcti *r_rect)
+{
+ wmSubWindow *swin = swin_from_swinid(win, swinid);
+
+ if (swin) {
+ *r_rect = swin->winrct;
+ }
+}
+
/* 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, rcti *winrct)
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 062107f834e..9e89c17e024 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -114,8 +114,8 @@ void wm_get_screensize(int *width_r, int *height_r)
*height_r = uiheight;
}
-/* size of all screens, useful since the mouse is bound by this */
-void wm_get_screensize_all(int *width_r, int *height_r)
+/* size of all screens (desktop), useful since the mouse is bound by this */
+void wm_get_desktopsize(int *width_r, int *height_r)
{
unsigned int uiwidth;
unsigned int uiheight;
@@ -375,15 +375,15 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
/* needed so we can detect the graphics card below */
GPU_extensions_init();
- /* set the state*/
- GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate);
-
win->ghostwin = ghostwin;
GHOST_SetWindowUserData(ghostwin, win); /* pointer back */
if (win->eventstate == NULL)
win->eventstate = MEM_callocN(sizeof(wmEvent), "window event state");
+ /* set the state */
+ GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate);
+
/* until screens get drawn, make it nice gray */
glClearColor(0.55, 0.55, 0.55, 0.0);
/* Crash on OSS ATI: bugs.launchpad.net/ubuntu/+source/mesa/+bug/656100 */
@@ -856,7 +856,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
GHOST_DisposeRectangle(client_rect);
- wm_get_screensize_all(&scr_w, &scr_h);
+ wm_get_desktopsize(&scr_w, &scr_h);
sizex = r - l;
sizey = b - t;
posx = l;
diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h
index 064d00b0723..a70e7765ecf 100644
--- a/source/blender/windowmanager/wm_subwindow.h
+++ b/source/blender/windowmanager/wm_subwindow.h
@@ -45,6 +45,7 @@ void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct);
void wm_subwindow_getsize(wmWindow *win, int swinid, int *x, int *y);
void wm_subwindow_getorigin(wmWindow *win, int swinid, int *x, int *y);
void wm_subwindow_getmatrix(wmWindow *win, int swinid, float mat[4][4]);
+void wm_subwindow_getrect(wmWindow *win, int swinid, struct rcti *r_rect);
unsigned int index_to_framebuffer(int index);
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index d7e938fec7c..e0639b098a8 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -40,7 +40,7 @@ void wm_ghost_init (bContext *C);
void wm_ghost_exit(void);
void wm_get_screensize(int *width_r, int *height_r);
-void wm_get_screensize_all(int *width_r, int *height_r);
+void wm_get_desktopsize(int *width_r, int *height_r);
wmWindow *wm_window_new (bContext *C);
void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win);
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 21502492c05..f55f307e095 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -207,8 +207,11 @@ void WM_jobs_kill_all_except(struct wmWindowManager *wm) {STUB_ASSERT(0);}
char *WM_clipboard_text_get(int selection) {STUB_ASSERT(0); return (char *)0;}
void WM_clipboard_text_set(char *buf, int selection) {STUB_ASSERT(0);}
-void WM_cursor_restore(struct wmWindow *win) {STUB_ASSERT(0);}
-void WM_cursor_time(struct wmWindow *win, int nr) {STUB_ASSERT(0);}
+void WM_cursor_set(struct wmWindow *win, int curor) {STUB_ASSERT(0);}
+void WM_cursor_modal_set(struct wmWindow *win, int curor) {STUB_ASSERT(0);}
+void WM_cursor_modal_restore(struct wmWindow *win) {STUB_ASSERT(0);}
+void WM_cursor_time(struct wmWindow *win, int nr) {STUB_ASSERT(0);}
+void WM_cursor_warp(struct wmWindow *win, int x, int y) {STUB_ASSERT(0);}
void WM_uilisttype_init(void) {STUB_ASSERT(0);}
struct uiListType *WM_uilisttype_find(const char *idname, int quiet) {STUB_ASSERT(0); return (struct uiListType *)NULL;}
@@ -273,6 +276,7 @@ struct wmKeyMap *WM_keymap_list_find(struct ListBase *lb, char *idname, int spac
struct wmKeyConfig *WM_keyconfig_new(struct wmWindowManager *wm, char *idname) {STUB_ASSERT(0); return (struct wmKeyConfig *) NULL;}
struct wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, char *idname) {STUB_ASSERT(0); return (struct wmKeyConfig *) NULL;}
void WM_keyconfig_remove(struct wmWindowManager *wm, char *idname) {STUB_ASSERT(0);}
+void WM_keymap_remove(struct wmKeyConfig *keyconf, char *idname) {STUB_ASSERT(0);}
void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname) {STUB_ASSERT(0);}
void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi) {STUB_ASSERT(0);}
void WM_keymap_restore_to_default(struct wmKeyMap *keymap) {STUB_ASSERT(0);}
@@ -331,6 +335,7 @@ void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic)
void ED_view3D_background_image_clear(struct View3D *v3d) {STUB_ASSERT(0);}
void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]) {STUB_ASSERT(0);}
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) {STUB_ASSERT(0); return 0.0f;}
+void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa) {STUB_ASSERT(0);}
void view3d_apply_mat4(float mat[4][4], float *ofs, float *quat, float *dist) {STUB_ASSERT(0);}
int text_file_modified(struct Text *text) {STUB_ASSERT(0); return 0;}
void ED_node_shader_default(struct bContext *C, struct ID *id) {STUB_ASSERT(0);}
@@ -458,7 +463,7 @@ void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *pro
void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) {STUB_ASSERT(0);}
void uiTemplateList(struct uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
- const char *active_propname, int rows, int maxrows, int layout_type) {STUB_ASSERT(0);}
+ const char *active_propname, int rows, int maxrows, int layout_type, int columns) {STUB_ASSERT(0);}
void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {STUB_ASSERT(0);}
void uiTemplateOperatorSearch(struct uiLayout *layout) {STUB_ASSERT(0);}
void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {STUB_ASSERT(0);}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 8ff4ec445ea..b24339cff1b 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -234,8 +234,16 @@ set(BLENDER_TEXT_FILES
${CMAKE_SOURCE_DIR}/release/text/Python-license.txt
${CMAKE_SOURCE_DIR}/release/text/copyright.txt
${CMAKE_SOURCE_DIR}/release/text/readme.html
+ ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-bfont.ttf.txt
)
+if(WITH_INTERNATIONAL)
+ list(APPEND BLENDER_TEXT_FILES
+ ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-droidsans.ttf.txt
+ ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-bmonofont-i18n.ttf.txt
+ )
+endif()
+
# -----------------------------------------------------------------------------
# Platform Specific Var: TARGETDIR_VER
@@ -992,6 +1000,10 @@ endif()
list(APPEND BLENDER_SORTED_LIBS bf_quicktime)
endif()
+ if(WITH_INPUT_NDOF)
+ list(APPEND BLENDER_SORTED_LIBS bf_intern_ghostndof3dconnexion)
+ endif()
+
if(WITH_MOD_BOOLEAN)
list(APPEND BLENDER_SORTED_LIBS extern_carve)
endif()
diff --git a/source/creator/creator.c b/source/creator/creator.c
index a710c07f34b..a3bce79b6e7 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -76,13 +76,13 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
+#include "BLI_blenlib.h"
+#include "BLI_mempool.h"
#include "DNA_ID.h"
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
-#include "BLI_blenlib.h"
-
#include "BKE_blender.h"
#include "BKE_brush.h"
#include "BKE_context.h"
@@ -92,6 +92,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_modifier.h"
#include "BKE_packedFile.h"
#include "BKE_scene.h"
#include "BKE_node.h"
@@ -117,8 +118,6 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "BLI_scanfill.h" /* for BLI_setErrorCallBack, TODO, move elsewhere */
-
#ifdef WITH_FREESTYLE
# include "FRS_freestyle.h"
#endif
@@ -173,11 +172,12 @@ static int print_version(int argc, const char **argv, void *data);
#endif
/* for the callbacks: */
-
+#ifndef WITH_PYTHON_MODULE
#define BLEND_VERSION_FMT "Blender %d.%02d (sub %d)"
#define BLEND_VERSION_ARG BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION
/* pass directly to printf */
#define BLEND_VERSION_STRING_FMT BLEND_VERSION_FMT "\n", BLEND_VERSION_ARG
+#endif
/* Initialize callbacks for the modules that need them */
static void setCallbacks(void);
@@ -412,10 +412,13 @@ static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data)
G.debug |= G_DEBUG; /* std output printf's */
printf(BLEND_VERSION_STRING_FMT);
MEM_set_memory_debug();
+#ifdef DEBUG
+ BLI_mempool_set_memory_debug();
+#endif
#ifdef WITH_BUILDINFO
printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
-#endif // WITH_BUILDINFO
+#endif
BLI_argsPrint(data);
return 0;
@@ -1517,6 +1520,7 @@ int main(int argc, const char **argv)
IMB_init();
BKE_images_init();
+ BKE_modifier_init();
BKE_brush_system_init();
@@ -1682,12 +1686,6 @@ void main_python_exit(void)
}
#endif
-static void error_cb(const char *err)
-{
-
- printf("%s\n", err); /* XXX do this in WM too */
-}
-
static void mem_error_cb(const char *errorStr)
{
fputs(errorStr, stderr);
@@ -1698,9 +1696,4 @@ static void setCallbacks(void)
{
/* Error output from the alloc routines: */
MEM_set_error_callback(mem_error_cb);
-
-
- /* BLI_blenlib: */
-
- BLI_setErrorCallBack(error_cb); /* */
}
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 7b5f5a7096a..484e51c4ed1 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -266,7 +266,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
bool animation_record = (SYS_GetCommandLineInt(syshandle, "animation_record", 0) != 0);
- bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0);
+ bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0) && GPU_display_list_support();
#ifdef WITH_PYTHON
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
#endif
@@ -290,7 +290,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
if (startscene->gm.vsync == VSYNC_ADAPTIVE)
canvas->SetSwapInterval(-1);
else
- canvas->SetSwapInterval(startscene->gm.vsync); // VSYNC_OFF == 0, VSYNC_ON == 1, so this works
+ canvas->SetSwapInterval((startscene->gm.vsync == VSYNC_ON) ? 1 : 0);
RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
RAS_IRasterizer* rasterizer = NULL;
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
index a6b71e0bc43..bcc62a341f8 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
@@ -211,7 +211,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
MT_Vector3 dir = (campos - objpos).safe_normalized();
MT_Vector3 up(0,0,1.0);
- KX_GameObject* gameobj = (KX_GameObject*)m_clientobject;
+ KX_GameObject* gameobj = (KX_GameObject *)this->m_clientobject;
// get scaling of halo object
MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling();
@@ -225,7 +225,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
}
MT_Vector3 left = dir.normalized();
- dir = (up.cross(left)).normalized();
+ dir = (left.cross(up)).normalized();
// we have calculated the row vectors, now we keep
// local scaling into account:
@@ -241,14 +241,13 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
glTranslated(objpos[0],objpos[1],objpos[2]);
glMultMatrixd(maat);
-
}
else {
if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
{
// shadow must be cast to the ground, physics system needed here!
MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
- KX_GameObject *gameobj = (KX_GameObject*)m_clientobject;
+ KX_GameObject *gameobj = (KX_GameObject *)this->m_clientobject;
MT_Vector3 direction = MT_Vector3(0,0,-1);
direction.normalize();
@@ -328,7 +327,7 @@ void KX_BlenderRenderTools::RenderText(
RAS_IPolyMaterial* polymat,
float v1[3], float v2[3], float v3[3], float v4[3], int glattrib)
{
- const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
+ const STR_String &mytext = ((CValue *)m_clientobject)->GetPropertyText("Text");
const unsigned int flag = polymat->GetFlag();
struct MTFace* tface = 0;
@@ -408,3 +407,4 @@ void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
}
}
}
+
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 90383021c90..a28906254a1 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -66,6 +66,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
float endtime,
struct bAction *action,
short playtype,
+ short blend_mode,
short blendin,
short priority,
short layer,
@@ -88,6 +89,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
m_stridelength(stride),
m_layer_weight(layer_weight),
m_playtype(playtype),
+ m_blendmode(blend_mode),
m_priority(priority),
m_layer(layer),
m_ipo_flags(ipo_flags),
@@ -187,6 +189,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
bool bUseContinue = false;
KX_GameObject *obj = (KX_GameObject*)GetParent();
short playtype = BL_Action::ACT_MODE_PLAY;
+ short blendmode = (m_blendmode == ACT_ACTION_ADD) ? BL_Action::ACT_BLEND_ADD : BL_Action::ACT_BLEND_BLEND;
float start = m_startframe;
float end = m_endframe;
@@ -283,7 +286,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
ResetStartTime(curtime);
}
- if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags))
+ if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags, 1.f, blendmode))
{
m_flag |= ACT_FLAG_ACTIVE;
if (bUseContinue)
@@ -328,7 +331,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
// Convert into a play action and play back to the beginning
end = start;
start = obj->GetActionFrame(m_layer);
- obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags);
+ obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags, 1.f, blendmode);
m_flag |= ACT_FLAG_PLAY_END;
break;
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
index ce805c774ef..4579a21f554 100644
--- a/source/gameengine/Converter/BL_ActionActuator.h
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -48,6 +48,7 @@ public:
float endtime,
struct bAction *action,
short playtype,
+ short blend_mode,
short blendin,
short priority,
short layer,
@@ -129,6 +130,7 @@ protected:
float m_stridelength;
float m_layer_weight;
short m_playtype;
+ short m_blendmode;
short m_priority;
short m_layer;
short m_ipo_flags;
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 55d9decb333..d8ddb33ddc4 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -32,6 +32,7 @@
#include "BL_ArmatureObject.h"
#include "BL_ActionActuator.h"
+#include "BL_Action.h"
#include "KX_BlenderSceneConverter.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -50,7 +51,6 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_nla_types.h"
#include "DNA_constraint_types.h"
#include "KX_PythonSeq.h"
#include "KX_PythonInit.h"
@@ -137,25 +137,22 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
/* Only allowed for Poses with identical channels */
-void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
+void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
{
- short mode= ACTSTRIPMODE_BLEND;
-
bPoseChannel *dchan;
const bPoseChannel *schan;
bConstraint *dcon, *scon;
float dstweight;
int i;
- switch (mode) {
- case ACTSTRIPMODE_BLEND:
- dstweight = 1.0F - srcweight;
- break;
- case ACTSTRIPMODE_ADD:
- dstweight = 1.0F;
- break;
- default :
- dstweight = 1.0F;
+ if (mode == BL_Action::ACT_BLEND_BLEND)
+ {
+ dstweight = 1.0f - srcweight;
+ } else if (mode == BL_Action::ACT_BLEND_ADD)
+ {
+ dstweight = 1.0f;
+ } else {
+ dstweight = 1.0f;
}
schan= (bPoseChannel *)src->chanbase.first;
@@ -167,7 +164,7 @@ void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
copy_qt_qt(dquat, dchan->quat);
copy_qt_qt(squat, schan->quat);
- if (mode==ACTSTRIPMODE_BLEND)
+ if (mode==BL_Action::ACT_BLEND_BLEND)
interp_qt_qtqt(dchan->quat, dquat, squat, srcweight);
else {
mul_fac_qt_fl(squat, srcweight);
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
index 445b9af1b10..81388355fc4 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.h
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -147,7 +147,7 @@ protected:
};
/* Pose function specific to the game engine */
-void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
+void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode); /* was blend_poses */
//void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
void game_copy_pose(struct bPose **dst, struct bPose *src, int copy_con);
void game_free_pose(struct bPose *pose);
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 99613f8bd99..dd9609968b0 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -2950,7 +2950,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
struct Object* blenderobj = gameobj->GetBlenderObject();
int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
- BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,layerMask,isInActiveLayer,rendertools,converter);
+ BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,layerMask,isInActiveLayer,converter);
}
for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
{
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp
index 59cf10d326a..5aec3c9e965 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.cpp
+++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp
@@ -159,16 +159,20 @@ bool BL_ShapeDeformer::Update(void)
/* the key coefficient have been set already, we just need to blend the keys */
Object* blendobj = m_gameobj->GetBlendObject();
- // make sure the vertex weight cache is in line with this object
- m_pMeshObject->CheckWeightCache(blendobj);
-
/* we will blend the key directly in m_transverts array: it is used by armature as the start position */
/* m_key can be NULL in case of Modifier deformer */
if (m_key) {
+ WeightsArrayCache cache = {0, NULL};
+ float **per_keyblock_weights;
+
/* store verts locally */
VerifyStorage();
- BKE_key_evaluate_relative(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts, m_key, NULL, 0); /* last arg is ignored */
+ per_keyblock_weights = BKE_keyblock_get_per_block_weights(blendobj, m_key, &cache);
+ BKE_key_evaluate_relative(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts,
+ m_key, NULL, per_keyblock_weights, 0); /* last arg is ignored */
+ BKE_keyblock_free_per_block_weights(m_key, per_keyblock_weights, &cache);
+
m_bDynamic = true;
}
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 5b528972e00..e9461a15578 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -120,7 +120,6 @@ void BL_ConvertActuators(const char* maggiename,
KX_KetsjiEngine* ketsjiEngine,
int activeLayerBitInfo,
bool isInActiveLayer,
- RAS_IRenderTools* rendertools,
KX_BlenderSceneConverter* converter
)
{
@@ -206,8 +205,8 @@ void BL_ConvertActuators(const char* maggiename,
case ACT_ACTION:
{
bActionActuator* actact = (bActionActuator*) bact->data;
- STR_String propname = (actact->name ? actact->name : "");
- STR_String propframe = (actact->frameProp ? actact->frameProp : "");
+ STR_String propname = actact->name;
+ STR_String propframe = actact->frameProp;
short ipo_flags = 0;
@@ -225,6 +224,7 @@ void BL_ConvertActuators(const char* maggiename,
actact->end,
actact->act,
actact->type, // + 1, because Blender starts to count at zero,
+ actact->blend_mode,
actact->blendin,
actact->priority,
actact->layer,
@@ -241,8 +241,8 @@ void BL_ConvertActuators(const char* maggiename,
{
if (blenderobject->type==OB_MESH) {
bActionActuator* actact = (bActionActuator*) bact->data;
- STR_String propname = (actact->name ? actact->name : "");
- STR_String propframe = (actact->frameProp ? actact->frameProp : "");
+ STR_String propname = actact->name;
+ STR_String propframe = actact->frameProp;
BL_ShapeActionActuator* tmpbaseact = new BL_ShapeActionActuator(
gameobj,
@@ -748,9 +748,8 @@ void BL_ConvertActuators(const char* maggiename,
break;
};
- if (sceneact->scene)
- {
- nextSceneName = sceneact->scene->id.name + 2; // this '2' is necessary to remove prefix 'SC'
+ if (sceneact->scene) {
+ nextSceneName = sceneact->scene->id.name + 2;
}
break;
diff --git a/source/gameengine/Converter/KX_ConvertActuators.h b/source/gameengine/Converter/KX_ConvertActuators.h
index 385d274bf89..688b5db50ce 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.h
+++ b/source/gameengine/Converter/KX_ConvertActuators.h
@@ -40,7 +40,6 @@ void BL_ConvertActuators(const char* maggiename,
class KX_KetsjiEngine* ketsjiEngine,
int activeLayerBitInfo,
bool isInActiveLayer,
- class RAS_IRenderTools* rendertools,
class KX_BlenderSceneConverter* converter);
#endif /* __KX_CONVERTACTUATORS_H__ */
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index 1aae2738311..3bb12c12cd1 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -194,30 +194,6 @@ void BL_ConvertSensors(struct Object* blenderobject,
break;
}
- case SENS_TOUCH:
- {
- SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
- if (eventmgr)
- {
- STR_String touchpropertyname;
- bTouchSensor* blendertouchsensor = (bTouchSensor*)sens->data;
-
- if (blendertouchsensor->ma)
- {
- touchpropertyname = (char*) (blendertouchsensor->ma->id.name+2);
- }
- bool bFindMaterial = true;
- if (gameobj->GetPhysicsController())
- {
- gamesensor = new KX_TouchSensor(eventmgr,
- gameobj,
- bFindMaterial,
- false,
- touchpropertyname);
- }
- }
- break;
- }
case SENS_MESSAGE:
{
KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*)
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index 8e729ffd7ae..793ce6a7b83 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -39,6 +39,8 @@
#include "SCA_Joystick.h"
#include "SCA_JoystickPrivate.h"
+#include "BLI_path_util.h"
+
SCA_Joystick::SCA_Joystick(short int index)
:
m_joyindex(index),
@@ -88,14 +90,26 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
if (m_refCount == 0)
{
int i;
+
/* The video subsystem is required for joystick input to work. However,
- * when GHOST is running under SDL, video is initialized elsewhere.
- * Do this once only. */
+ * when GHOST is running under SDL, video is initialized elsewhere. We
+ * also need to set the videodriver to dummy, and do it here to avoid
+ * interfering with addons that may use SDL too.
+ *
+ * We also init SDL once only. */
# ifdef WITH_GHOST_SDL
- if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1 ) {
+ int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1 );
# else
- if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) == -1 ) {
+ /* set and restore environment variable */
+ char *videodriver = getenv("SDL_VIDEODRIVER");
+ BLI_setenv("SDL_VIDEODRIVER", "dummy");
+
+ int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) != -1 );
+
+ BLI_setenv("SDL_VIDEODRIVER", videodriver);
# endif
+
+ if (!success) {
JOYSTICK_ECHO("Error-Initializing-SDL: " << SDL_GetError());
return NULL;
}
@@ -278,7 +292,11 @@ void SCA_Joystick::DestroyJoystickDevice(void)
{
#ifdef WITH_SDL
if (m_isinit) {
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ if (SDL_JoystickGetAttached(m_private->m_joystick)) {
+#else
if (SDL_JoystickOpened(m_joyindex)) {
+#endif
JOYSTICK_ECHO("Closing-joystick " << m_joyindex);
SDL_JoystickClose(m_private->m_joystick);
}
@@ -290,7 +308,12 @@ void SCA_Joystick::DestroyJoystickDevice(void)
int SCA_Joystick::Connected(void)
{
#ifdef WITH_SDL
- if (m_isinit && SDL_JoystickOpened(m_joyindex))
+ if (m_isinit
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ && SDL_JoystickGetAttached(m_private->m_joystick))
+#else
+ && SDL_JoystickOpened(m_joyindex))
+#endif
return 1;
#endif
return 0;
@@ -328,7 +351,11 @@ int SCA_Joystick::pAxisTest(int axisnum)
const char *SCA_Joystick::GetName()
{
#ifdef WITH_SDL
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ return SDL_JoystickName(m_private->m_joystick);
+#else
return SDL_JoystickName(m_joyindex);
+#endif
#else /* WITH_SDL */
return "";
#endif /* WITH_SDL */
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
index f50137cfcf6..2911b3b1a14 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
@@ -118,7 +118,7 @@ void SCA_Joystick::HandleEvents(void)
break;
#endif
default:
- printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n");
+ printf("SCA_Joystick::HandleEvents, Unknown SDL event (%d), this should not happen\n", sdl_event.type);
break;
}
}
diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp
index 60b4d19e155..c98c86639d3 100644
--- a/source/gameengine/GameLogic/SCA_IScene.cpp
+++ b/source/gameengine/GameLogic/SCA_IScene.cpp
@@ -87,7 +87,7 @@ void SCA_IScene::AddDebugProperty(class CValue* debugprop,
void SCA_IScene::RemoveObjectDebugProperties(class CValue* gameobj)
{
vector<SCA_DebugProp*>::iterator it = m_debugList.begin();
- while(it != m_debugList.end()) {
+ while (it != m_debugList.end()) {
CValue* debugobj = (*it)->m_obj;
if (debugobj == gameobj) {
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
index e8c29d5aa4f..0d851c4f10d 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
@@ -66,9 +66,7 @@ unsigned int GPC_RenderTools::m_numgllights;
GPC_RenderTools::GPC_RenderTools()
{
-// XXX m_font = BMF_GetFont(BMF_kHelvetica10);
-
- glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights);
+ glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights);
if (m_numgllights < 8)
m_numgllights = 8;
}
@@ -220,7 +218,7 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
MT_Vector3 dir = (campos - objpos).safe_normalized();
MT_Vector3 up(0,0,1.0);
- KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ KX_GameObject* gameobj = (KX_GameObject *)this->m_clientobject;
// get scaling of halo object
MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling();
@@ -256,7 +254,7 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
{
// shadow must be cast to the ground, physics system needed here!
MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
- KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject;
+ KX_GameObject *gameobj = (KX_GameObject *)this->m_clientobject;
MT_Vector3 direction = MT_Vector3(0,0,-1);
direction.normalize();
@@ -280,6 +278,12 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
// couldn't find something to cast the shadow on...
glMultMatrixd(oglmatrix);
}
+ else
+ { // we found the "ground", but the cast matrix doesn't take
+ // scaling in consideration, so we must apply the object scale
+ MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
+ glScalef(size[0], size[1], size[2]);
+ }
} else
{
@@ -490,7 +494,7 @@ void GPC_RenderTools::RenderText(
RAS_IPolyMaterial* polymat,
float v1[3], float v2[3], float v3[3], float v4[3], int glattrib)
{
- STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
+ const STR_String &mytext = ((CValue *)m_clientobject)->GetPropertyText("Text");
const unsigned int flag = polymat->GetFlag();
struct MTFace* tface = 0;
@@ -562,8 +566,7 @@ void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
glAccum(GL_LOAD, 1.0);
rasterizer->SetMotionBlurState(2);
}
- else if (motionblurvalue>=0.0 && motionblurvalue<=1.0)
- {
+ else if (motionblurvalue >= 0.0f && motionblurvalue <= 1.0f) {
glAccum(GL_MULT, motionblurvalue);
glAccum(GL_ACCUM, 1-motionblurvalue);
glAccum(GL_RETURN, 1.0);
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index c3cbf381af4..c74e3daf7b2 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -566,7 +566,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixedtime", (gm->flag & GAME_ENABLE_ALL_FRAMES)) != 0);
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
- bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0);
+ bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0) && GPU_display_list_support();
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0);
bool restrictAnimFPS = gm->flag & GAME_RESTRICT_ANIM_UPDATES;
@@ -586,7 +586,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
if (gm->vsync == VSYNC_ADAPTIVE)
m_canvas->SetSwapInterval(-1);
else
- m_canvas->SetSwapInterval(gm->vsync); // VSYNC_OFF == 0, VSYNC_ON == 1, so this works
+ m_canvas->SetSwapInterval((gm->vsync == VSYNC_ON) ? 1 : 0);
m_canvas->Init();
if (gm->flag & GAME_SHOW_MOUSE)
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index ccbcdd25639..5bed4fa40b6 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -57,22 +57,29 @@ extern "C"
{
#endif // __cplusplus
#include "MEM_guardedalloc.h"
+#include "BLI_threads.h"
+#include "BLI_mempool.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLO_readfile.h"
+#include "BLO_runtime.h"
+
#include "BKE_blender.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_library.h"
-#include "BLI_threads.h"
-#include "BLI_blenlib.h"
-#include "DNA_scene_types.h"
-#include "DNA_userdef_types.h"
-#include "BLO_readfile.h"
-#include "BLO_runtime.h"
-#include "IMB_imbuf.h"
+#include "BKE_modifier.h"
#include "BKE_text.h"
#include "BKE_sound.h"
+
+#include "IMB_imbuf.h"
int GHOST_HACK_getFirstFile(char buf[]);
@@ -456,6 +463,7 @@ int main(int argc, char** argv)
IMB_init();
BKE_images_init();
+ BKE_modifier_init();
#ifdef WITH_FFMPEG
IMB_ffmpeg_init();
@@ -577,8 +585,11 @@ int main(int argc, char** argv)
case 'd':
i++;
- G.debug |= G_DEBUG; /* std output printf's */
+ G.debug |= G_DEBUG;
MEM_set_memory_debug();
+#ifdef DEBUG
+ BLI_mempool_set_memory_debug();
+#endif
break;
case 'f':
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index 9d189a6170e..6d9b22eed91 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -65,7 +65,8 @@ BL_Action::BL_Action(class KX_GameObject* gameobj)
m_blendstart(0.f),
m_speed(0.f),
m_priority(0),
- m_playmode(0),
+ m_playmode(ACT_MODE_PLAY),
+ m_blendmode(ACT_BLEND_BLEND),
m_ipo_flags(0),
m_done(true),
m_calc_localtime(true)
@@ -104,7 +105,8 @@ bool BL_Action::Play(const char* name,
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed)
+ float playback_speed,
+ short blend_mode)
{
// Only start playing a new action if we're done, or if
@@ -229,6 +231,7 @@ bool BL_Action::Play(const char* name,
m_endframe = end;
m_blendin = blendin;
m_playmode = play_mode;
+ m_blendmode = blend_mode;
m_endtime = 0.f;
m_blendframe = 0.f;
m_blendstart = 0.f;
@@ -423,7 +426,7 @@ void BL_Action::Update(float curtime)
float weight = 1.f - (m_blendframe/m_blendin);
// Blend the poses
- game_blend_poses(m_pose, m_blendinpose, weight);
+ game_blend_poses(m_pose, m_blendinpose, weight, ACT_BLEND_BLEND);
}
@@ -431,7 +434,7 @@ void BL_Action::Update(float curtime)
if (m_layer_weight >= 0)
{
obj->GetMRDPose(&m_blendpose);
- game_blend_poses(m_pose, m_blendpose, m_layer_weight);
+ game_blend_poses(m_pose, m_blendpose, m_layer_weight, m_blendmode);
}
obj->SetPose(m_pose);
diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h
index e4088633e61..e9d09916517 100644
--- a/source/gameengine/Ketsji/BL_Action.h
+++ b/source/gameengine/Ketsji/BL_Action.h
@@ -34,7 +34,6 @@
#include "MEM_guardedalloc.h"
#endif
-
class BL_Action
{
private:
@@ -64,6 +63,7 @@ private:
short m_priority;
short m_playmode;
+ short m_blendmode;
short m_ipo_flags;
@@ -91,7 +91,8 @@ public:
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed);
+ float playback_speed,
+ short blend_mode);
/**
* Stop playing the action
*/
@@ -114,7 +115,7 @@ public:
void SetPlayMode(short play_mode);
void SetTimes(float start, float end);
- enum
+ enum
{
ACT_MODE_PLAY = 0,
ACT_MODE_LOOP,
@@ -124,6 +125,13 @@ public:
enum
{
+ ACT_BLEND_BLEND=0,
+ ACT_BLEND_ADD=1,
+ ACT_BLEND_MAX,
+ };
+
+ enum
+ {
ACT_IPOFLAG_FORCE = 1,
ACT_IPOFLAG_LOCAL = 2,
ACT_IPOFLAG_ADD = 4,
diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index e3402972ca6..2e882ceba74 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -25,6 +25,7 @@
*/
#include "BL_ActionManager.h"
+#include "BL_Action.h"
BL_ActionManager::BL_ActionManager(class KX_GameObject *obj)
{
@@ -72,12 +73,13 @@ bool BL_ActionManager::PlayAction(const char* name,
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed)
+ float playback_speed,
+ short blend_mode)
{
// Disable layer blending on the first layer
if (layer == 0) layer_weight = -1.f;
- return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
+ return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
}
void BL_ActionManager::StopAction(short layer)
diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h
index 600e7b6621e..8c5b8e909da 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -27,10 +27,14 @@
#ifndef __BL_ACTIONMANAGER_H__
#define __BL_ACTIONMANAGER_H__
-#include "BL_Action.h"
+#ifdef WITH_CXX_GUARDEDALLOC
+ #include "MEM_guardedalloc.h"
+#endif
#define MAX_ACTION_LAYERS 8
+class BL_Action;
+
/**
* BL_ActionManager is responsible for handling a KX_GameObject's actions.
*/
@@ -52,7 +56,8 @@ public:
short play_mode=0,
float layer_weight=0.f,
short ipo_flags=0,
- float playback_speed=1.f);
+ float playback_speed=1.f,
+ short blend_mode=0);
/**
* Gets the current frame of an action
*/
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index 97dc8f72aec..6f6925dcf76 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -44,7 +44,6 @@
BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer)
:
- mScene(scene),
mMat(ma),
mLightLayer(lightlayer),
mGPUMat(NULL)
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h
index 71f66c2a49d..e03bb5a11d9 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.h
+++ b/source/gameengine/Ketsji/BL_BlenderShader.h
@@ -57,7 +57,6 @@ class BL_Material;
class BL_BlenderShader
{
private:
- KX_Scene *mScene;
struct Scene *mBlenderScene;
struct Material *mMat;
int mLightLayer;
@@ -86,13 +85,6 @@ public:
void ReloadMaterial();
int GetAlphaBlend();
- void SetScene(KX_Scene *scene)
- {
- mScene = scene;
- mBlenderScene = scene->GetBlenderScene();
- ReloadMaterial();
- }
-
bool Equals(BL_BlenderShader *blshader);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 28abdc898ae..b3a38cb4f98 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -808,9 +808,7 @@ void KX_BlenderMaterial::UpdateIPO(
void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
{
mScene= static_cast<KX_Scene *>(val);
- if (mBlenderShader)
- mBlenderShader->SetScene(mScene);
-
+
OnConstruction();
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index ec62ae63f0c..e06f7ab6633 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -73,6 +73,7 @@ typedef unsigned long uint_ptr;
#include "KX_ObstacleSimulation.h"
#include "BL_ActionManager.h"
+#include "BL_Action.h"
#include "PyObjectPlus.h" /* python stuff */
@@ -113,8 +114,10 @@ KX_GameObject::KX_GameObject(
m_pDupliGroupObject(NULL),
m_actionManager(NULL),
m_isDeformable(false)
+
#ifdef WITH_PYTHON
- , m_attr_dict(NULL)
+ , m_attr_dict(NULL),
+ m_collisionCallbacks(NULL)
#endif
{
m_ignore_activity_culling = false;
@@ -132,6 +135,20 @@ KX_GameObject::KX_GameObject(
KX_GameObject::~KX_GameObject()
{
+#ifdef WITH_PYTHON
+ if (m_attr_dict) {
+ PyDict_Clear(m_attr_dict); /* in case of circular refs or other weird cases */
+ /* Py_CLEAR: Py_DECREF's and NULL's */
+ Py_CLEAR(m_attr_dict);
+ }
+ // Unregister collision callbacks
+ // Do this before we start freeing physics information like m_pClient_info
+ if (m_collisionCallbacks){
+ UnregisterCollisionCallbacks();
+ Py_CLEAR(m_collisionCallbacks);
+ }
+#endif // WITH_PYTHON
+
RemoveMeshes();
// is this delete somewhere ?
@@ -179,13 +196,6 @@ KX_GameObject::~KX_GameObject()
{
m_pInstanceObjects->Release();
}
-#ifdef WITH_PYTHON
- if (m_attr_dict) {
- PyDict_Clear(m_attr_dict); /* in case of circular refs or other weird cases */
- /* Py_CLEAR: Py_DECREF's and NULL's */
- Py_CLEAR(m_attr_dict);
- }
-#endif // WITH_PYTHON
}
KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo *info)
@@ -429,9 +439,10 @@ bool KX_GameObject::PlayAction(const char* name,
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed)
+ float playback_speed,
+ short blend_mode)
{
- return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
+ return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
}
void KX_GameObject::StopAction(short layer)
@@ -1334,6 +1345,77 @@ const MT_Point3& KX_GameObject::NodeGetLocalPosition() const
}
+void KX_GameObject::UnregisterCollisionCallbacks()
+{
+ if (!GetPhysicsController()) {
+ printf("Warning, trying to unregister collision callbacks for object without collisions: %s!\n", GetName().ReadPtr());
+ return;
+ }
+
+ // Unregister from callbacks
+ KX_Scene* scene = GetScene();
+ PHY_IPhysicsEnvironment* pe = scene->GetPhysicsEnvironment();
+ PHY_IPhysicsController* spc = static_cast<PHY_IPhysicsController*> (GetPhysicsController()->GetUserData());
+ // If we are the last to unregister on this physics controller
+ if (pe->removeCollisionCallback(spc)){
+ // If we are a sensor object
+ if (m_pClient_info->isSensor())
+ // Remove sensor body from physics world
+ pe->removeSensor(spc);
+ }
+}
+
+void KX_GameObject::RegisterCollisionCallbacks()
+{
+ if (!GetPhysicsController()) {
+ printf("Warning, trying to register collision callbacks for object without collisions: %s!\n", GetName().ReadPtr());
+ return;
+ }
+
+ // Register from callbacks
+ KX_Scene* scene = GetScene();
+ PHY_IPhysicsEnvironment* pe = scene->GetPhysicsEnvironment();
+ PHY_IPhysicsController* spc = static_cast<PHY_IPhysicsController*> (GetPhysicsController()->GetUserData());
+ // If we are the first to register on this physics controller
+ if (pe->requestCollisionCallback(spc)){
+ // If we are a sensor object
+ if (m_pClient_info->isSensor())
+ // Add sensor body to physics world
+ pe->addSensor(spc);
+ }
+}
+void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider)
+{
+ #ifdef WITH_PYTHON
+ Py_ssize_t len;
+ PyObject* collision_callbacks = m_collisionCallbacks;
+
+ if (collision_callbacks && (len=PyList_GET_SIZE(collision_callbacks)))
+ {
+ PyObject* args = Py_BuildValue("(O)", collider->GetProxy()); // save python creating each call
+ PyObject *func;
+ PyObject *ret;
+
+ // Iterate the list and run the callbacks
+ for (Py_ssize_t pos=0; pos < len; pos++)
+ {
+ func = PyList_GET_ITEM(collision_callbacks, pos);
+ ret = PyObject_Call(func, args, NULL);
+
+ if (ret == NULL) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ else {
+ Py_DECREF(ret);
+ }
+ }
+
+ Py_DECREF(args);
+ }
+ #endif
+}
+
/* Suspend/ resume: for the dynamic behavior, there is a simple
* method. For the residual motion, there is not. I wonder what the
* correct solution is for Sumo. Remove from the motion-update tree?
@@ -1714,6 +1796,7 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
+ KX_PYATTRIBUTE_RW_FUNCTION("collisionCallbacks", KX_GameObject, pyattr_get_collisionCallbacks, pyattr_set_collisionCallbacks),
KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state),
KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes),
KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
@@ -2006,6 +2089,51 @@ PyObject *KX_GameObject::pyattr_get_group_members(void *self_v, const KX_PYATTRI
Py_RETURN_NONE;
}
+PyObject* KX_GameObject::pyattr_get_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+
+ // Only objects with a physics controller should have collision callbacks
+ if (!self->GetPhysicsController()) {
+ PyErr_SetString(PyExc_AttributeError, "KX_GameObject.collisionCallbacks: attribute only available for objects with collisions enabled");
+ return NULL;
+ }
+
+ // Return the existing callbacks
+ if (self->m_collisionCallbacks == NULL)
+ {
+ self->m_collisionCallbacks = PyList_New(0);
+ // Subscribe to collision update from KX_TouchManager
+ self->RegisterCollisionCallbacks();
+ }
+ Py_INCREF(self->m_collisionCallbacks);
+ return self->m_collisionCallbacks;
+}
+
+int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+
+ // Only objects with a physics controller should have collision callbacks
+ if (!self->GetPhysicsController()) {
+ PyErr_SetString(PyExc_AttributeError, "KX_GameObject.collisionCallbacks: attribute only available for objects with collisions enabled");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (!PyList_CheckExact(value))
+ {
+ PyErr_SetString(PyExc_ValueError, "Expected a list");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ Py_XDECREF(self->m_collisionCallbacks);
+ Py_INCREF(value);
+
+ self->m_collisionCallbacks = value;
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
@@ -3311,11 +3439,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
short layer=0, priority=0;
short ipo_flags=0;
short play_mode=0;
+ short blend_mode=0;
- static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", NULL};
+ static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", "blend_mode", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhf:playAction", const_cast<char**>(kwlist),
- &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhfh:playAction", const_cast<char**>(kwlist),
+ &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed, &blend_mode))
return NULL;
layer_check(layer, "playAction");
@@ -3323,7 +3452,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX)
{
printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1);
- play_mode = BL_Action::ACT_MODE_MAX;
+ play_mode = BL_Action::ACT_MODE_PLAY;
+ }
+
+ if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX)
+ {
+ printf("KX_GameObject.playAction(): given blend_mode (%d) is out of range (0 - %d), setting to ACT_BLEND_BLEND", blend_mode, BL_Action::ACT_BLEND_MAX-1);
+ blend_mode = BL_Action::ACT_BLEND_BLEND;
}
if (layer_weight < 0.f || layer_weight > 1.f)
@@ -3332,7 +3467,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
layer_weight = 0.f;
}
- PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed);
+ PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed, blend_mode);
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 13a79cebefb..dde3ff53299 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -137,21 +137,22 @@ public:
#ifdef WITH_PYTHON
// Python attributes that wont convert into CValue
- //
+ //
// there are 2 places attributes can be stored, in the CValue,
// where attributes are converted into BGE's CValue types
// these can be used with property actuators
//
// For the python API, For types that cannot be converted into CValues (lists, dicts, GameObjects)
// these will be put into "m_attr_dict", logic bricks cannot access them.
- //
+ //
// rules for setting attributes.
- //
+ //
// * there should NEVER be a CValue and a m_attr_dict attribute with matching names. get/sets make sure of this.
// * if CValue conversion fails, use a PyObject in "m_attr_dict"
// * when assigning a value, first see if it can be a CValue, if it can remove the "m_attr_dict" and set the CValue
- //
- PyObject* m_attr_dict;
+ //
+ PyObject* m_attr_dict;
+ PyObject* m_collisionCallbacks;
#endif
virtual void /* This function should be virtual - derived classed override it */
@@ -255,7 +256,8 @@ public:
short play_mode=0,
float layer_weight=0.f,
short ipo_flags=0,
- float playback_speed=1.f);
+ float playback_speed=1.f,
+ short blend_mode=0);
/**
* Gets the current frame of an action
@@ -871,6 +873,9 @@ public:
* \section Logic bubbling methods.
*/
+ void RegisterCollisionCallbacks();
+ void UnregisterCollisionCallbacks();
+ void RunCollisionCallbacks(KX_GameObject *collider);
/**
* Stop making progress
*/
@@ -1039,6 +1044,8 @@ public:
static PyObject* pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_obcolor(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_collisionCallbacks(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
/* Experimental! */
static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 32666ec0792..c685dcfe068 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -1201,6 +1201,7 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
/* render */
m_rasterizer->ClearDepthBuffer();
+ m_rasterizer->ClearColorBuffer();
scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
/* unbind framebuffer object, restore drawmode, free camera */
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index a8f309cc592..0e4db0d351e 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -48,6 +48,9 @@
#include "DNA_scene_types.h"
#include "DNA_lamp_types.h"
#include "GPU_material.h"
+
+#include "BKE_scene.h"
+#include "MEM_guardedalloc.h"
KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
class RAS_IRenderTools* rendertools,
@@ -62,6 +65,7 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
m_rendertools->AddLight(&m_lightobj);
m_glsl = glsl;
m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene();
+ m_base = NULL;
};
@@ -78,6 +82,11 @@ KX_LightObject::~KX_LightObject()
}
m_rendertools->RemoveLight(&m_lightobj);
+
+ if (m_base) {
+ BKE_scene_base_unlink(m_blenderscene, m_base);
+ MEM_freeN(m_base);
+ }
}
@@ -216,6 +225,13 @@ void KX_LightObject::Update()
}
}
+void KX_LightObject::UpdateScene(KX_Scene *kxscene)
+{
+ m_lightobj.m_scene = (void*)kxscene;
+ m_blenderscene = kxscene->GetBlenderScene();
+ m_base = BKE_scene_base_add(m_blenderscene, GetBlenderObject());
+}
+
bool KX_LightObject::HasShadowBuffer()
{
GPULamp *lamp;
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index f88fc7f6a1b..43421a3faf3 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -37,6 +37,7 @@
struct GPULamp;
struct Scene;
+struct Base;
class KX_Camera;
class RAS_IRasterizer;
class RAS_IRenderTools;
@@ -50,6 +51,7 @@ protected:
class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj
bool m_glsl;
Scene* m_blenderscene;
+ Base* m_base;
public:
KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl);
@@ -69,7 +71,7 @@ public:
struct Image *GetTextureImage(short texslot);
void Update();
- void UpdateScene(class KX_Scene *kxscene) {m_lightobj.m_scene = (void*)kxscene;}
+ void UpdateScene(class KX_Scene *kxscene);
virtual int GetGameObjectType() { return OBJ_LIGHT; }
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index d8b4bf9e8bd..29f28b7cc24 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -1378,14 +1378,14 @@ static PyObject *gPySetVsync(PyObject *, PyObject *args)
if (!PyArg_ParseTuple(args, "i:setVsync", &interval))
return NULL;
- if (interval < VSYNC_OFF || interval > VSYNC_ADAPTIVE) {
+ if (interval < 0 || interval > VSYNC_ADAPTIVE) {
PyErr_SetString(PyExc_ValueError, "Rasterizer.setVsync(value): value must be VSYNC_OFF, VSYNC_ON, or VSYNC_ADAPTIVE");
return NULL;
}
if (interval == VSYNC_ADAPTIVE)
interval = -1;
- gp_Canvas->SetSwapInterval(interval);
+ gp_Canvas->SetSwapInterval((interval == VSYNC_ON) ? 1 : 0);
Py_RETURN_NONE;
}
@@ -1675,16 +1675,16 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_POS_X, KX_RadarSensor::KX_RADAR_AXIS_POS_X);
KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_POS_Y, KX_RadarSensor::KX_RADAR_AXIS_POS_Y);
KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_POS_Z, KX_RadarSensor::KX_RADAR_AXIS_POS_Z);
- KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_X, KX_RadarSensor::KX_RADAR_AXIS_NEG_Y);
- KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_Y, KX_RadarSensor::KX_RADAR_AXIS_NEG_X);
+ KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_X, KX_RadarSensor::KX_RADAR_AXIS_NEG_X);
+ KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_Y, KX_RadarSensor::KX_RADAR_AXIS_NEG_Y);
KX_MACRO_addTypesToDict(d, KX_RADAR_AXIS_NEG_Z, KX_RadarSensor::KX_RADAR_AXIS_NEG_Z);
/* Ray Sensor */
KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_POS_X, KX_RaySensor::KX_RAY_AXIS_POS_X);
KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_POS_Y, KX_RaySensor::KX_RAY_AXIS_POS_Y);
KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_POS_Z, KX_RaySensor::KX_RAY_AXIS_POS_Z);
- KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_X, KX_RaySensor::KX_RAY_AXIS_NEG_Y);
- KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Y, KX_RaySensor::KX_RAY_AXIS_NEG_X);
+ KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_X, KX_RaySensor::KX_RAY_AXIS_NEG_X);
+ KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Y, KX_RaySensor::KX_RAY_AXIS_NEG_Y);
KX_MACRO_addTypesToDict(d, KX_RAY_AXIS_NEG_Z, KX_RaySensor::KX_RAY_AXIS_NEG_Z);
/* Dynamic actuator */
@@ -1820,6 +1820,10 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_LOOP, BL_Action::ACT_MODE_LOOP);
KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_PING_PONG, BL_Action::ACT_MODE_PING_PONG);
+ /* BL_Action blend modes */
+ KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_BLEND, BL_Action::ACT_BLEND_BLEND);
+ KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_ADD, BL_Action::ACT_BLEND_ADD);
+
// Check for errors
if (PyErr_Occurred())
{
diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h
index 9d40fb55747..ca14867e892 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.h
+++ b/source/gameengine/Ketsji/KX_RaySensor.h
@@ -83,8 +83,8 @@ public:
//Python Interface
enum RayAxis {
- KX_RAY_AXIS_POS_Y = 0,
- KX_RAY_AXIS_POS_X,
+ KX_RAY_AXIS_POS_X = 0,
+ KX_RAY_AXIS_POS_Y,
KX_RAY_AXIS_POS_Z,
KX_RAY_AXIS_NEG_X,
KX_RAY_AXIS_NEG_Y,
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 35084061ab0..4fa51b48ab8 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -445,7 +445,7 @@ void KX_Scene::AddObjectDebugProperties(class KX_GameObject* gameobj)
Object* blenderobject = gameobj->GetBlenderObject();
bProperty* prop = (bProperty*)blenderobject->prop.first;
- while(prop) {
+ while (prop) {
if (prop->flag & PROP_DEBUG)
AddDebugProperty(gameobj,STR_String(prop->name));
prop = prop->next;
@@ -1953,8 +1953,6 @@ bool KX_Scene::MergeScene(KX_Scene *other)
GetBucketManager()->MergeBucketManager(other->GetBucketManager(), this);
- /* move materials across, assume they both use the same scene-converters */
- GetSceneConverter()->MergeScene(this, other);
/* active + inactive == all ??? - lets hope so */
for (int i = 0; i < other->GetObjectList()->GetCount(); i++)
@@ -1991,7 +1989,12 @@ bool KX_Scene::MergeScene(KX_Scene *other)
if (env) /* bullet scene? - dummy scenes don't need touching */
env->MergeEnvironment(env_other);
#endif
-
+
+ /* move materials across, assume they both use the same scene-converters
+ * Do this after lights are merged so materials can use the lights in shaders
+ */
+ GetSceneConverter()->MergeScene(this, other);
+
/* merge logic */
{
SCA_LogicManager *logicmgr= GetLogicManager();
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 5438ae5a97c..3a4b1d82946 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -109,7 +109,7 @@ void KX_SoundActuator::play()
try
{
- m_handle = AUD_getDevice()->play(sound, 0);
+ m_handle = AUD_getDevice()->play(sound);
}
catch(AUD_Exception&)
{
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
index 96872f4e6fd..1a9e1442cc8 100644
--- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
@@ -81,28 +81,42 @@ bool KX_TouchEventManager::newBroadphaseResponse(void *client_data,
void *object2,
const PHY_CollData *coll_data)
{
- PHY_IPhysicsController* ctrl = static_cast<PHY_IPhysicsController*>(object1);
- KX_ClientObjectInfo *info = (ctrl) ? static_cast<KX_ClientObjectInfo*>(ctrl->getNewClientInfo()) : NULL;
+ PHY_IPhysicsController* ctrl1 = static_cast<PHY_IPhysicsController*>(object1);
+ PHY_IPhysicsController* ctrl2 = static_cast<PHY_IPhysicsController*>(object2);
+
+ KX_ClientObjectInfo *info1 = (ctrl1) ? static_cast<KX_ClientObjectInfo*>(ctrl1->getNewClientInfo()) : NULL;
+ KX_ClientObjectInfo *info2 = (ctrl1) ? static_cast<KX_ClientObjectInfo*>(ctrl2->getNewClientInfo()) : NULL;
+
// This call back should only be called for controllers of Near and Radar sensor
- if (!info)
+ if (!info1)
return true;
- switch (info->m_type)
+ // Get KX_GameObjects for callbacks
+ KX_GameObject* gobj1 = info1->m_gameobject;
+ KX_GameObject* gobj2 = (info2) ? info2->m_gameobject : NULL;
+
+ bool has_py_callbacks = false;
+
+ // Consider callbacks for broadphase inclusion if it's a sensor object type
+ if (gobj1 && gobj2)
+ has_py_callbacks = gobj1->m_collisionCallbacks || gobj2->m_collisionCallbacks;
+
+ switch (info1->m_type)
{
case KX_ClientObjectInfo::SENSOR:
- if (info->m_sensors.size() == 1)
+ if (info1->m_sensors.size() == 1)
{
// only one sensor for this type of object
- KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(*info->m_sensors.begin());
- return touchsensor->BroadPhaseFilterCollision(object1,object2);
+ KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(*info1->m_sensors.begin());
+ return touchsensor->BroadPhaseFilterCollision(object1, object2);
}
break;
case KX_ClientObjectInfo::OBSENSOR:
case KX_ClientObjectInfo::OBACTORSENSOR:
// this object may have multiple collision sensors,
// check is any of them is interested in this object
- for (std::list<SCA_ISensor*>::iterator it = info->m_sensors.begin();
- it != info->m_sensors.end();
+ for (std::list<SCA_ISensor*>::iterator it = info1->m_sensors.begin();
+ it != info1->m_sensors.end();
++it)
{
if ((*it)->GetSensorType() == SCA_ISensor::ST_TOUCH)
@@ -112,7 +126,8 @@ bool KX_TouchEventManager::newBroadphaseResponse(void *client_data,
return true;
}
}
- return false;
+
+ return has_py_callbacks;
// quiet the compiler
case KX_ClientObjectInfo::STATIC:
@@ -155,32 +170,43 @@ void KX_TouchEventManager::EndFrame()
void KX_TouchEventManager::NextFrame()
{
- if (!m_sensors.Empty())
- {
SG_DList::iterator<KX_TouchSensor> it(m_sensors);
for (it.begin();!it.end();++it)
(*it)->SynchronizeTransform();
for (std::set<NewCollision>::iterator cit = m_newCollisions.begin(); cit != m_newCollisions.end(); ++cit)
{
+ // Controllers
PHY_IPhysicsController* ctrl1 = (*cit).first;
-// PHY_IPhysicsController* ctrl2 = (*cit).second;
-// KX_GameObject* gameOb1 = ctrl1->getClientInfo();
-// KX_GameObject* gameOb1 = ctrl1->getClientInfo();
+ PHY_IPhysicsController* ctrl2 = (*cit).second;
- KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo *>(ctrl1->getNewClientInfo());
+ // Sensor iterator
list<SCA_ISensor*>::iterator sit;
+
+ // First client info
+ KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo*>(ctrl1->getNewClientInfo());
+ // First gameobject
+ KX_GameObject *kxObj1 = KX_GameObject::GetClientObject(client_info);
+ // Invoke sensor response for each object
if (client_info) {
for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit) {
- static_cast<KX_TouchSensor*>(*sit)->NewHandleCollision((*cit).first, (*cit).second, NULL);
+ static_cast<KX_TouchSensor*>(*sit)->NewHandleCollision(ctrl1, ctrl2, NULL);
}
}
- client_info = static_cast<KX_ClientObjectInfo *>((*cit).second->getNewClientInfo());
+
+ // Second client info
+ client_info = static_cast<KX_ClientObjectInfo *>(ctrl2->getNewClientInfo());
+ // Second gameobject
+ KX_GameObject *kxObj2 = KX_GameObject::GetClientObject(client_info);
if (client_info) {
for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit) {
- static_cast<KX_TouchSensor*>(*sit)->NewHandleCollision((*cit).second, (*cit).first, NULL);
+ static_cast<KX_TouchSensor*>(*sit)->NewHandleCollision(ctrl2, ctrl1, NULL);
}
}
+ // Run python callbacks
+ kxObj1->RunCollisionCallbacks(kxObj2);
+ kxObj2->RunCollisionCallbacks(kxObj1);
+
}
m_newCollisions.clear();
@@ -188,4 +214,3 @@ void KX_TouchEventManager::NextFrame()
for (it.begin();!it.end();++it)
(*it)->Activate(m_logicmgr);
}
-}
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
index 7d1190bef5c..713d324bf17 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
@@ -378,17 +378,10 @@ void RAS_BucketManager::MergeBucketManager(RAS_BucketManager *other, SCA_IScene
{
/* concatinate lists */
// printf("BEFORE %d %d\n", GetSolidBuckets().size(), GetAlphaBuckets().size());
- BucketList::iterator it;
-
- for (it = other->GetSolidBuckets().begin(); it != other->GetSolidBuckets().end(); ++it)
- (*it)->GetPolyMaterial()->Replace_IScene(scene);
GetSolidBuckets().insert( GetSolidBuckets().end(), other->GetSolidBuckets().begin(), other->GetSolidBuckets().end() );
other->GetSolidBuckets().clear();
- for (it = other->GetAlphaBuckets().begin(); it != other->GetAlphaBuckets().end(); ++it)
- (*it)->GetPolyMaterial()->Replace_IScene(scene);
-
GetAlphaBuckets().insert( GetAlphaBuckets().end(), other->GetAlphaBuckets().begin(), other->GetAlphaBuckets().end() );
other->GetAlphaBuckets().clear();
//printf("AFTER %d %d\n", GetSolidBuckets().size(), GetAlphaBuckets().size());
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
index 2af71c5efa9..8a9672f0092 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -125,17 +125,6 @@ RAS_MeshObject::~RAS_MeshObject()
{
vector<RAS_Polygon*>::iterator it;
- if (m_mesh && m_mesh->key)
- {
- KeyBlock *kb;
- // remove the weight cache to avoid memory leak
- for (kb = (KeyBlock *)m_mesh->key->block.first; kb; kb = (KeyBlock *)kb->next) {
- if (kb->weights)
- MEM_freeN(kb->weights);
- kb->weights= NULL;
- }
- }
-
for (it=m_Polygons.begin(); it!=m_Polygons.end(); it++)
delete (*it);
@@ -559,61 +548,3 @@ void RAS_MeshObject::SchedulePolygons(int drawingmode)
m_bMeshModified = true;
}
}
-
-static int get_def_index(Object* ob, const char* vgroup)
-{
- bDeformGroup *curdef;
- int index = 0;
-
- for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++)
- if (!strcmp(curdef->name, vgroup))
- return index;
-
- return -1;
-}
-
-void RAS_MeshObject::CheckWeightCache(Object* obj)
-{
- KeyBlock *kb;
- int kbindex, defindex;
- MDeformVert *dv= NULL;
- int totvert, i;
- float *weights;
-
- if (!m_mesh->key)
- return;
-
- for (kbindex = 0, kb = (KeyBlock *)m_mesh->key->block.first; kb; kb = kb->next, kbindex++)
- {
- // first check the cases where the weight must be cleared
- if (kb->vgroup[0] == 0 ||
- m_mesh->dvert == NULL ||
- (defindex = get_def_index(obj, kb->vgroup)) == -1) {
- if (kb->weights) {
- MEM_freeN(kb->weights);
- kb->weights = NULL;
- }
- m_cacheWeightIndex[kbindex] = -1;
- } else if (m_cacheWeightIndex[kbindex] != defindex) {
- // a weight array is required but the cache is not matching
- if (kb->weights) {
- MEM_freeN(kb->weights);
- kb->weights = NULL;
- }
-
- dv= m_mesh->dvert;
- totvert= m_mesh->totvert;
-
- weights= (float*)MEM_mallocN(totvert*sizeof(float), "weights");
-
- for (i=0; i < totvert; i++, dv++) {
- weights[i] = defvert_find_weight(dv, defindex);
- }
-
- kb->weights = weights;
- m_cacheWeightIndex[kbindex] = defindex;
- }
- }
-}
-
-
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h
index d77d0483024..e5ae78d006e 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.h
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.h
@@ -83,9 +83,6 @@ public:
virtual ~RAS_MeshObject();
- // for shape keys,
- void CheckWeightCache(struct Object* obj);
-
/* materials */
int NumMaterials();
const STR_String& GetMaterialName(unsigned int matid);
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
index a1c0836417a..e1dbd6f0a7f 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
@@ -127,11 +127,8 @@ bool RAS_ListSlot::End()
RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock, int storage)
-: RAS_OpenGLRasterizer(canvas, storage),
- mATI(false)
+: RAS_OpenGLRasterizer(canvas, storage)
{
- if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc."))
- mATI = true;
}
RAS_ListRasterizer::~RAS_ListRasterizer()
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
index 558850a9173..d394c72b2a2 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
@@ -51,7 +51,6 @@ typedef std::map<DerivedMesh*, RAS_ListSlots*> RAS_DerivedMeshLists;
class RAS_ListRasterizer : public RAS_OpenGLRasterizer
{
- bool mATI;
RAS_ArrayLists mArrayLists;
RAS_DerivedMeshLists mDerivedMeshLists;
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index c24cfdb4ef0..bfc74e0c6dc 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -1010,7 +1010,11 @@ void RAS_OpenGLRasterizer::DisableMotionBlur()
void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend)
{
- GPU_set_material_alpha_blend(alphablend);
+ /* Variance shadow maps don't handle alpha well, best to not allow it for now */
+ if (m_drawingmode == KX_SHADOW && m_usingoverrideshader)
+ GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
+ else
+ GPU_set_material_alpha_blend(alphablend);
/*
if (alphablend == m_last_alphablend)
return;
diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py
index effc06cd15f..ad8a6919c91 100644
--- a/source/tests/bl_run_operators.py
+++ b/source/tests/bl_run_operators.py
@@ -342,7 +342,8 @@ def ctx_editmode_curves():
def ctx_editmode_curves_empty():
bpy.ops.curve.primitive_nurbs_circle_add()
bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.curve.delete(type='ALL')
+ bpy.ops.curve.select_all(action='SELECT')
+ bpy.ops.curve.delete(type='VERT')
def ctx_editmode_surface():