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:
authorPhil Gosch <phil@saphirestudio.at>2017-07-11 20:51:35 +0300
committerPhil Gosch <phil@saphirestudio.at>2017-07-11 20:51:35 +0300
commit99c3d1106e3ff73e2111781d8e38307b2164d57c (patch)
treea40f7ddf5c7bc1ee531f05df70cce5a994bccf1a /source
parent2dae9a1596d93f0ed8e782f0c5152db231ed1abe (diff)
parentbb0e8f1c552adfb67f34551f061f2b901e1f2d90 (diff)
Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools
Diffstat (limited to 'source')
-rw-r--r--source/blender/alembic/ABC_alembic.h55
-rw-r--r--source/blender/alembic/intern/abc_archive.cc41
-rw-r--r--source/blender/alembic/intern/abc_archive.h9
-rw-r--r--source/blender/alembic/intern/abc_camera.cc20
-rw-r--r--source/blender/alembic/intern/abc_camera.h7
-rw-r--r--source/blender/alembic/intern/abc_curves.cc78
-rw-r--r--source/blender/alembic/intern/abc_curves.h14
-rw-r--r--source/blender/alembic/intern/abc_customdata.cc173
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc320
-rw-r--r--source/blender/alembic/intern/abc_exporter.h28
-rw-r--r--source/blender/alembic/intern/abc_hair.cc45
-rw-r--r--source/blender/alembic/intern/abc_hair.h2
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc101
-rw-r--r--source/blender/alembic/intern/abc_mesh.h22
-rw-r--r--source/blender/alembic/intern/abc_nurbs.cc3
-rw-r--r--source/blender/alembic/intern/abc_nurbs.h2
-rw-r--r--source/blender/alembic/intern/abc_object.cc111
-rw-r--r--source/blender/alembic/intern/abc_object.h47
-rw-r--r--source/blender/alembic/intern/abc_points.cc34
-rw-r--r--source/blender/alembic/intern/abc_points.h13
-rw-r--r--source/blender/alembic/intern/abc_transform.cc53
-rw-r--r--source/blender/alembic/intern/abc_transform.h11
-rw-r--r--source/blender/alembic/intern/abc_util.cc352
-rw-r--r--source/blender/alembic/intern/abc_util.h95
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc640
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c1
-rw-r--r--source/blender/blenkernel/BKE_action.h4
-rw-r--r--source/blender/blenkernel/BKE_animsys.h6
-rw-r--r--source/blender/blenkernel/BKE_appdir.h4
-rw-r--r--source/blender/blenkernel/BKE_armature.h3
-rw-r--r--source/blender/blenkernel/BKE_blender.h12
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h20
-rw-r--r--source/blender/blenkernel/BKE_boids.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h2
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h2
-rw-r--r--source/blender/blenkernel/BKE_camera.h2
-rw-r--r--source/blender/blenkernel/BKE_cloth.h6
-rw-r--r--source/blender/blenkernel/BKE_colortools.h4
-rw-r--r--source/blender/blenkernel/BKE_curve.h6
-rw-r--r--source/blender/blenkernel/BKE_deform.h4
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h14
-rw-r--r--source/blender/blenkernel/BKE_font.h3
-rw-r--r--source/blender/blenkernel/BKE_global.h5
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h2
-rw-r--r--source/blender/blenkernel/BKE_group.h2
-rw-r--r--source/blender/blenkernel/BKE_icons.h6
-rw-r--r--source/blender/blenkernel/BKE_idprop.h13
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/BKE_key.h2
-rw-r--r--source/blender/blenkernel/BKE_lamp.h2
-rw-r--r--source/blender/blenkernel/BKE_lattice.h2
-rw-r--r--source/blender/blenkernel/BKE_library.h12
-rw-r--r--source/blender/blenkernel/BKE_library_query.h9
-rw-r--r--source/blender/blenkernel/BKE_library_remap.h5
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h10
-rw-r--r--source/blender/blenkernel/BKE_mask.h8
-rw-r--r--source/blender/blenkernel/BKE_material.h2
-rw-r--r--source/blender/blenkernel/BKE_mball.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h5
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h10
-rw-r--r--source/blender/blenkernel/BKE_object.h15
-rw-r--r--source/blender/blenkernel/BKE_paint.h4
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/BKE_property.h4
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h4
-rw-r--r--source/blender/blenkernel/BKE_sca.h8
-rw-r--r--source/blender/blenkernel/BKE_speaker.h2
-rw-r--r--source/blender/blenkernel/BKE_text.h2
-rw-r--r--source/blender/blenkernel/BKE_texture.h10
-rw-r--r--source/blender/blenkernel/BKE_tracking.h2
-rw-r--r--source/blender/blenkernel/BKE_world.h2
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c22
-rw-r--r--source/blender/blenkernel/intern/action.c4
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c67
-rw-r--r--source/blender/blenkernel/intern/appdir.c173
-rw-r--r--source/blender/blenkernel/intern/armature.c11
-rw-r--r--source/blender/blenkernel/intern/armature_update.c6
-rw-r--r--source/blender/blenkernel/intern/blender.c120
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c6
-rw-r--r--source/blender/blenkernel/intern/blendfile.c94
-rw-r--r--source/blender/blenkernel/intern/boids.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c4
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c6
-rw-r--r--source/blender/blenkernel/intern/cachefile.c7
-rw-r--r--source/blender/blenkernel/intern/camera.c2
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c256
-rw-r--r--source/blender/blenkernel/intern/cloth.c37
-rw-r--r--source/blender/blenkernel/intern/colortools.c4
-rw-r--r--source/blender/blenkernel/intern/constraint.c12
-rw-r--r--source/blender/blenkernel/intern/curve.c6
-rw-r--r--source/blender/blenkernel/intern/customdata.c71
-rw-r--r--source/blender/blenkernel/intern/deform.c4
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c2
-rw-r--r--source/blender/blenkernel/intern/displist.c11
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c4
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c17
-rw-r--r--source/blender/blenkernel/intern/effect.c26
-rw-r--r--source/blender/blenkernel/intern/fcurve.c6
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c14
-rw-r--r--source/blender/blenkernel/intern/font.c10
-rw-r--r--source/blender/blenkernel/intern/gpencil.c2
-rw-r--r--source/blender/blenkernel/intern/group.c4
-rw-r--r--source/blender/blenkernel/intern/icons.c6
-rw-r--r--source/blender/blenkernel/intern/idprop.c182
-rw-r--r--source/blender/blenkernel/intern/image.c48
-rw-r--r--source/blender/blenkernel/intern/key.c2
-rw-r--r--source/blender/blenkernel/intern/lamp.c2
-rw-r--r--source/blender/blenkernel/intern/lattice.c4
-rw-r--r--source/blender/blenkernel/intern/library.c269
-rw-r--r--source/blender/blenkernel/intern/library_query.c153
-rw-r--r--source/blender/blenkernel/intern/library_remap.c93
-rw-r--r--source/blender/blenkernel/intern/linestyle.c10
-rw-r--r--source/blender/blenkernel/intern/mask.c12
-rw-r--r--source/blender/blenkernel/intern/material.c2
-rw-r--r--source/blender/blenkernel/intern/mball.c2
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c11
-rw-r--r--source/blender/blenkernel/intern/mesh.c38
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c455
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c4
-rw-r--r--source/blender/blenkernel/intern/movieclip.c2
-rw-r--r--source/blender/blenkernel/intern/node.c13
-rw-r--r--source/blender/blenkernel/intern/object.c23
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c18
-rw-r--r--source/blender/blenkernel/intern/object_update.c19
-rw-r--r--source/blender/blenkernel/intern/ocean.c2
-rw-r--r--source/blender/blenkernel/intern/packedFile.c4
-rw-r--r--source/blender/blenkernel/intern/paint.c4
-rw-r--r--source/blender/blenkernel/intern/particle.c10
-rw-r--r--source/blender/blenkernel/intern/particle_child.c8
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c2
-rw-r--r--source/blender/blenkernel/intern/particle_system.c4
-rw-r--r--source/blender/blenkernel/intern/pbvh.c68
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c4
-rw-r--r--source/blender/blenkernel/intern/property.c4
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c10
-rw-r--r--source/blender/blenkernel/intern/sca.c8
-rw-r--r--source/blender/blenkernel/intern/scene.c18
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c2
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c15
-rw-r--r--source/blender/blenkernel/intern/sequencer.c10
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c9
-rw-r--r--source/blender/blenkernel/intern/softbody.c12
-rw-r--r--source/blender/blenkernel/intern/speaker.c2
-rw-r--r--source/blender/blenkernel/intern/text.c2
-rw-r--r--source/blender/blenkernel/intern/texture.c40
-rw-r--r--source/blender/blenkernel/intern/tracking.c65
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c17
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c8
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c62
-rw-r--r--source/blender/blenkernel/intern/world.c2
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c7
-rw-r--r--source/blender/blenkernel/intern/writeframeserver.c4
-rw-r--r--source/blender/blenkernel/tracking_private.h11
-rw-r--r--source/blender/blenlib/BLI_alloca.h4
-rw-r--r--source/blender/blenlib/BLI_array.h4
-rw-r--r--source/blender/blenlib/BLI_compiler_attrs.h8
-rw-r--r--source/blender/blenlib/BLI_compiler_compat.h5
-rw-r--r--source/blender/blenlib/BLI_dynstr.h6
-rw-r--r--source/blender/blenlib/BLI_fileops.h4
-rw-r--r--source/blender/blenlib/BLI_fileops_types.h6
-rw-r--r--source/blender/blenlib/BLI_ghash.h21
-rw-r--r--source/blender/blenlib/BLI_hash.h66
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h4
-rw-r--r--source/blender/blenlib/BLI_listbase.h6
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h8
-rw-r--r--source/blender/blenlib/BLI_math_vector.h4
-rw-r--r--source/blender/blenlib/BLI_path_util.h29
-rw-r--r--source/blender/blenlib/BLI_rect.h1
-rw-r--r--source/blender/blenlib/BLI_stack.h8
-rw-r--r--source/blender/blenlib/BLI_strict_flags.h2
-rw-r--r--source/blender/blenlib/BLI_sys_types.h4
-rw-r--r--source/blender/blenlib/BLI_task.h7
-rw-r--r--source/blender/blenlib/BLI_winstuff.h29
-rw-r--r--source/blender/blenlib/CMakeLists.txt1
-rw-r--r--source/blender/blenlib/intern/BLI_dynstr.c70
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c17
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c154
-rw-r--r--source/blender/blenlib/intern/array_store.c4
-rw-r--r--source/blender/blenlib/intern/fileops.c5
-rw-r--r--source/blender/blenlib/intern/hash_mm2a.c6
-rw-r--r--source/blender/blenlib/intern/listbase.c36
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c2
-rw-r--r--source/blender/blenlib/intern/math_geom.c17
-rw-r--r--source/blender/blenlib/intern/math_matrix.c22
-rw-r--r--source/blender/blenlib/intern/math_rotation.c55
-rw-r--r--source/blender/blenlib/intern/math_vector.c85
-rw-r--r--source/blender/blenlib/intern/path_util.c193
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c96
-rw-r--r--source/blender/blenlib/intern/rct.c8
-rw-r--r--source/blender/blenlib/intern/storage.c32
-rw-r--r--source/blender/blenlib/intern/string.c4
-rw-r--r--source/blender/blenlib/intern/string_utf8.c12
-rw-r--r--source/blender/blenlib/intern/task.c175
-rw-r--r--source/blender/blenlib/intern/threads.c5
-rw-r--r--source/blender/blenlib/intern/winstuff.c2
-rw-r--r--source/blender/blenloader/BLO_readfile.h20
-rw-r--r--source/blender/blenloader/CMakeLists.txt6
-rw-r--r--source/blender/blenloader/intern/readblenentry.c15
-rw-r--r--source/blender/blenloader/intern/readfile.c1066
-rw-r--r--source/blender/blenloader/intern/readfile.h2
-rw-r--r--source/blender/blenloader/intern/versioning_260.c3
-rw-r--r--source/blender/blenloader/intern/versioning_270.c60
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c16
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c3
-rw-r--r--source/blender/blenloader/intern/writefile.c2081
-rw-r--r--source/blender/blentranslation/CMakeLists.txt2
-rw-r--r--source/blender/blentranslation/msgfmt/CMakeLists.txt50
-rw-r--r--source/blender/blentranslation/msgfmt/msgfmt.c464
-rw-r--r--source/blender/bmesh/bmesh.h5
-rw-r--r--source/blender/bmesh/bmesh_class.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c90
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h52
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c68
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c161
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c43
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c18
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h15
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c16
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c101
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c36
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c2
-rw-r--r--source/blender/bmesh/operators/bmo_bisect_plane.c7
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect_nonplanar.c4
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c8
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c2
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c4
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c20
-rw-r--r--source/blender/bmesh/operators/bmo_fill_holes.c2
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c6
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c12
-rw-r--r--source/blender/bmesh/operators/bmo_offset_edgeloops.c4
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c82
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c21
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c6
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c26
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c10
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c136
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c55
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.h2
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c28
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c40
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c60
-rw-r--r--source/blender/bmesh/tools/bmesh_path.h4
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c98
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.h2
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.c10
-rw-r--r--source/blender/collada/AnimationImporter.cpp2
-rw-r--r--source/blender/collada/ArmatureExporter.cpp80
-rw-r--r--source/blender/collada/ArmatureExporter.h2
-rw-r--r--source/blender/collada/ArmatureImporter.cpp65
-rw-r--r--source/blender/collada/ControllerExporter.cpp125
-rw-r--r--source/blender/collada/ControllerExporter.h2
-rw-r--r--source/blender/collada/DocumentExporter.cpp8
-rw-r--r--source/blender/collada/DocumentImporter.cpp8
-rw-r--r--source/blender/collada/EffectExporter.cpp134
-rw-r--r--source/blender/collada/EffectExporter.h1
-rw-r--r--source/blender/collada/ErrorHandler.cpp9
-rw-r--r--source/blender/collada/ExportSettings.h7
-rw-r--r--source/blender/collada/GeometryExporter.cpp303
-rw-r--r--source/blender/collada/GeometryExporter.h34
-rw-r--r--source/blender/collada/ImageExporter.cpp28
-rw-r--r--source/blender/collada/ImportSettings.h1
-rw-r--r--source/blender/collada/InstanceWriter.cpp63
-rw-r--r--source/blender/collada/InstanceWriter.h3
-rw-r--r--source/blender/collada/MaterialExporter.cpp35
-rw-r--r--source/blender/collada/MeshImporter.cpp7
-rw-r--r--source/blender/collada/SceneExporter.cpp5
-rw-r--r--source/blender/collada/SkinInfo.cpp2
-rw-r--r--source/blender/collada/TransformReader.cpp23
-rw-r--r--source/blender/collada/TransformReader.h5
-rw-r--r--source/blender/collada/TransformWriter.cpp7
-rw-r--r--source/blender/collada/TransformWriter.h3
-rw-r--r--source/blender/collada/collada.cpp17
-rw-r--r--source/blender/collada/collada.h17
-rw-r--r--source/blender/collada/collada_internal.cpp27
-rw-r--r--source/blender/collada/collada_internal.h8
-rw-r--r--source/blender/collada/collada_utils.cpp380
-rw-r--r--source/blender/collada/collada_utils.h25
-rw-r--r--source/blender/compositor/CMakeLists.txt4
-rw-r--r--source/blender/compositor/COM_compositor.h13
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp105
-rw-r--r--source/blender/compositor/nodes/COM_BrightnessNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp45
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cpp87
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.h8
-rw-r--r--source/blender/compositor/operations/COM_BrightnessOperation.cpp14
-rw-r--r--source/blender/compositor/operations/COM_BrightnessOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp186
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h122
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.cpp29
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.h2
-rw-r--r--source/blender/depsgraph/CMakeLists.txt2
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc81
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc42
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc387
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h18
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc102
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc22
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc715
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h47
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc165
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc25
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc4
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc121
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc127
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h23
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc72
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc36
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc12
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h145
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc12
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_debug.cc6
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc46
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.cc108
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.h53
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc59
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h10
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.cc20
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.h13
-rw-r--r--source/blender/depsgraph/util/deg_util_foreach.h25
-rw-r--r--source/blender/editors/animation/anim_draw.c1
-rw-r--r--source/blender/editors/animation/anim_markers.c3
-rw-r--r--source/blender/editors/animation/keyframes_edit.c2
-rw-r--r--source/blender/editors/armature/armature_naming.c4
-rw-r--r--source/blender/editors/armature/pose_slide.c2
-rw-r--r--source/blender/editors/armature/reeb.c2
-rw-r--r--source/blender/editors/curve/editcurve.c8
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c35
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c27
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c114
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h94
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c30
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c37
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c66
-rw-r--r--source/blender/editors/include/ED_clip.h2
-rw-r--r--source/blender/editors/include/ED_image.h2
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h7
-rw-r--r--source/blender/editors/include/UI_icons.h4
-rw-r--r--source/blender/editors/include/UI_interface.h3
-rw-r--r--source/blender/editors/interface/interface.c27
-rw-r--r--source/blender/editors/interface/interface_anim.c2
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c18
-rw-r--r--source/blender/editors/interface/interface_handlers.c114
-rw-r--r--source/blender/editors/interface/interface_intern.h1
-rw-r--r--source/blender/editors/interface/interface_layout.c61
-rw-r--r--source/blender/editors/interface/interface_regions.c30
-rw-r--r--source/blender/editors/interface/interface_templates.c2
-rw-r--r--source/blender/editors/interface/interface_utils.c10
-rw-r--r--source/blender/editors/interface/interface_widgets.c19
-rw-r--r--source/blender/editors/io/io_alembic.c66
-rw-r--r--source/blender/editors/io/io_cache.c2
-rw-r--r--source/blender/editors/io/io_collada.c134
-rw-r--r--source/blender/editors/mask/mask_add.c13
-rw-r--r--source/blender/editors/mask/mask_draw.c7
-rw-r--r--source/blender/editors/mask/mask_ops.c4
-rw-r--r--source/blender/editors/mesh/editface.c19
-rw-r--r--source/blender/editors/mesh/editmesh_add.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c4
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c6
-rw-r--r--source/blender/editors/mesh/meshtools.c38
-rw-r--r--source/blender/editors/object/object_add.c53
-rw-r--r--source/blender/editors/object/object_bake_api.c29
-rw-r--r--source/blender/editors/object/object_group.c3
-rw-r--r--source/blender/editors/object/object_modifier.c5
-rw-r--r--source/blender/editors/object/object_relations.c223
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c36
-rw-r--r--source/blender/editors/physics/particle_edit.c2
-rw-r--r--source/blender/editors/physics/physics_fluid.c112
-rw-r--r--source/blender/editors/physics/physics_pointcache.c42
-rw-r--r--source/blender/editors/render/render_internal.c5
-rw-r--r--source/blender/editors/render/render_opengl.c23
-rw-r--r--source/blender/editors/render/render_preview.c2
-rw-r--r--source/blender/editors/render/render_shading.c2
-rw-r--r--source/blender/editors/render/render_update.c6
-rw-r--r--source/blender/editors/render/render_view.c19
-rw-r--r--source/blender/editors/screen/area.c2
-rw-r--r--source/blender/editors/screen/glutil.c8
-rw-r--r--source/blender/editors/screen/screen_edit.c14
-rw-r--r--source/blender/editors/screen/screen_ops.c68
-rw-r--r--source/blender/editors/sound/sound_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_editor.c12
-rw-r--r--source/blender/editors/space_clip/clip_utils.c5
-rw-r--r--source/blender/editors/space_clip/space_clip.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c3
-rw-r--r--source/blender/editors/space_clip/tracking_ops_plane.c3
-rw-r--r--source/blender/editors/space_file/filelist.c2
-rw-r--r--source/blender/editors/space_file/fsmenu.c46
-rw-r--r--source/blender/editors/space_image/image_buttons.c36
-rw-r--r--source/blender/editors/space_image/image_ops.c15
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c2
-rw-r--r--source/blender/editors/space_nla/nla_draw.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c43
-rw-r--r--source/blender/editors/space_node/node_add.c22
-rw-r--r--source/blender/editors/space_node/node_buttons.c11
-rw-r--r--source/blender/editors/space_node/node_draw.c28
-rw-r--r--source/blender/editors/space_node/node_edit.c16
-rw-r--r--source/blender/editors/space_node/node_group.c12
-rw-r--r--source/blender/editors/space_node/node_view.c14
-rw-r--r--source/blender/editors/space_node/space_node.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c38
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c61
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c22
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c5
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c2
-rw-r--r--source/blender/editors/space_text/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_text/space_text.c4
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c6
-rw-r--r--source/blender/editors/space_text/text_format.h2
-rw-r--r--source/blender/editors/space_text/text_format_pov.c809
-rw-r--r--source/blender/editors/space_text/text_format_pov_ini.c488
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c5
-rw-r--r--source/blender/editors/space_view3d/drawobject.c47
-rw-r--r--source/blender/editors/space_view3d/drawsimdebug.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c21
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c164
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c126
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h2
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c16
-rw-r--r--source/blender/editors/transform/transform.c46
-rw-r--r--source/blender/editors/transform/transform_conversions.c20
-rw-r--r--source/blender/editors/transform/transform_generics.c2
-rw-r--r--source/blender/editors/transform/transform_input.c13
-rw-r--r--source/blender/editors/transform/transform_manipulator.c142
-rw-r--r--source/blender/editors/transform/transform_orientations.c6
-rw-r--r--source/blender/editors/transform/transform_snap_object.c9
-rw-r--r--source/blender/editors/util/numinput.c6
-rw-r--r--source/blender/editors/util/undo.c3
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c1
-rw-r--r--source/blender/freestyle/intern/application/AppView.cpp6
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp2
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp12
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.h6
-rw-r--r--source/blender/gpu/GPU_buffers.h45
-rw-r--r--source/blender/gpu/GPU_material.h5
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c4
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c104
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c4
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c4
-rw-r--r--source/blender/gpu/intern/gpu_debug.c5
-rw-r--r--source/blender/gpu/intern/gpu_draw.c36
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c6
-rw-r--r--source/blender/gpu/intern/gpu_material.c29
-rw-r--r--source/blender/gpu/intern/gpu_select.c6
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c18
-rw-r--r--source/blender/gpu/intern/gpu_shader.c1
-rw-r--r--source/blender/gpu/intern/gpu_texture.c14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl206
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h22
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h7
-rw-r--r--source/blender/imbuf/intern/IMB_colormanagement_intern.h2
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c13
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c2
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.c15
-rw-r--r--source/blender/imbuf/intern/colormanagement.c57
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp4
-rw-r--r--source/blender/imbuf/intern/filter.c6
-rw-r--r--source/blender/imbuf/intern/metadata.c2
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp4
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp16
-rw-r--r--source/blender/imbuf/intern/png.c3
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c3
-rw-r--r--source/blender/makesdna/DNA_ID.h2
-rw-r--r--source/blender/makesdna/DNA_cachefile_types.h4
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h1
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesdna/DNA_object_fluidsim.h1
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h40
-rw-r--r--source/blender/makesdna/DNA_space_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h13
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/RNA_define.h1
-rw-r--r--source/blender/makesrna/RNA_types.h2
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt3
-rw-r--r--source/blender/makesrna/intern/makesrna.c4
-rw-r--r--source/blender/makesrna/intern/rna_ID.c8
-rw-r--r--source/blender/makesrna/intern/rna_access.c89
-rw-r--r--source/blender/makesrna/intern/rna_action.c3
-rw-r--r--source/blender/makesrna/intern/rna_animation.c3
-rw-r--r--source/blender/makesrna/intern/rna_armature.c3
-rw-r--r--source/blender/makesrna/intern/rna_color.c5
-rw-r--r--source/blender/makesrna/intern/rna_define.c17
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c3
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c8
-rw-r--r--source/blender/makesrna/intern/rna_image.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c16
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c53
-rw-r--r--source/blender/makesrna/intern/rna_object.c13
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c62
-rw-r--r--source/blender/makesrna/intern/rna_particle.c9
-rw-r--r--source/blender/makesrna/intern/rna_render.c104
-rw-r--r--source/blender/makesrna/intern/rna_scene.c49
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c126
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c69
-rw-r--r--source/blender/makesrna/intern/rna_space.c330
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui.c1
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c42
-rw-r--r--source/blender/makesrna/intern/rna_wm.c242
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c11
-rw-r--r--source/blender/modifiers/intern/MOD_array.c43
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c5
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c1
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c10
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c13
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.c31
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_mdd.c5
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c6
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c6
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c4
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c29
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c1
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c31
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c6
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c3
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c3
-rw-r--r--source/blender/nodes/CMakeLists.txt5
-rw-r--r--source/blender/nodes/NOD_composite.h4
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h3
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c35
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_bilateralblur.c1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_brightness.c5
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_directionalblur.c1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c541
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switchview.c1
-rw-r--r--source/blender/nodes/intern/node_exec.c3
-rw-r--r--source/blender/nodes/shader/node_shader_util.c52
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c114
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.c12
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp51
-rw-r--r--source/blender/physics/intern/implicit.h10
-rw-r--r--source/blender/physics/intern/implicit_blender.c34
-rw-r--r--source/blender/python/BPY_extern.h3
-rw-r--r--source/blender/python/generic/idprop_py_api.c440
-rw-r--r--source/blender/python/generic/py_capi_utils.c51
-rw-r--r--source/blender/python/generic/py_capi_utils.h7
-rw-r--r--source/blender/python/intern/CMakeLists.txt9
-rw-r--r--source/blender/python/intern/bpy_app.c17
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c4
-rw-r--r--source/blender/python/intern/bpy_app_opensubdiv.c109
-rw-r--r--source/blender/python/intern/bpy_app_opensubdiv.h (renamed from source/blender/depsgraph/util/deg_util_hash.h)23
-rw-r--r--source/blender/python/intern/bpy_app_sdl.c2
-rw-r--r--source/blender/python/intern/bpy_interface.c61
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c4
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.h4
-rw-r--r--source/blender/python/intern/bpy_props.c169
-rw-r--r--source/blender/python/intern/bpy_props.h4
-rw-r--r--source/blender/python/intern/bpy_rna.c88
-rw-r--r--source/blender/python/intern/bpy_rna.h1
-rw-r--r--source/blender/python/intern/bpy_utils_units.c2
-rw-r--r--source/blender/python/mathutils/mathutils.c35
-rw-r--r--source/blender/python/mathutils/mathutils_Color.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c4
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c30
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c2
-rw-r--r--source/blender/render/CMakeLists.txt5
-rw-r--r--source/blender/render/extern/include/RE_engine.h7
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h25
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h4
-rw-r--r--source/blender/render/intern/include/render_result.h7
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/include/rendercore.h8
-rw-r--r--source/blender/render/intern/source/bake_api.c4
-rw-r--r--source/blender/render/intern/source/convertblender.c9
-rw-r--r--source/blender/render/intern/source/envmap.c16
-rw-r--r--source/blender/render/intern/source/external_engine.c41
-rw-r--r--source/blender/render/intern/source/pipeline.c75
-rw-r--r--source/blender/render/intern/source/render_result.c671
-rw-r--r--source/blender/render/intern/source/render_texture.c63
-rw-r--r--source/blender/render/intern/source/rendercore.c410
-rw-r--r--source/blender/render/intern/source/renderdatabase.c9
-rw-r--r--source/blender/render/intern/source/shadeoutput.c14
-rw-r--r--source/blender/render/intern/source/sunsky.c2
-rw-r--r--source/blender/render/intern/source/volumetric.c6
-rw-r--r--source/blender/render/intern/source/zbuf.c229
-rw-r--r--source/blender/windowmanager/CMakeLists.txt4
-rw-r--r--source/blender/windowmanager/WM_api.h4
-rw-r--r--source/blender/windowmanager/WM_types.h8
-rw-r--r--source/blender/windowmanager/intern/wm.c39
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c17
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c18
-rw-r--r--source/blender/windowmanager/intern/wm_files.c324
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c3
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c4
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c7
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c65
-rw-r--r--source/blender/windowmanager/intern/wm_window.c90
-rw-r--r--source/blender/windowmanager/wm_files.h5
-rw-r--r--source/blender/windowmanager/wm_window.h2
-rw-r--r--source/blenderplayer/CMakeLists.txt35
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c31
-rw-r--r--source/creator/CMakeLists.txt168
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp6
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp2
-rw-r--r--source/gameengine/Expressions/intern/HashedPtr.cpp4
-rw-r--r--source/gameengine/Expressions/intern/InputParser.cpp2
-rw-r--r--source/gameengine/Expressions/intern/PyObjectPlus.cpp8
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp4
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.h2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_MouseDevice.h2
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp2
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp2
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp2
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp2
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Dome.h2
-rw-r--r--source/gameengine/Ketsji/KX_IPO_SGController.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_ObstacleSimulation.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp4
-rw-r--r--source/gameengine/Physics/Bullet/CMakeLists.txt1
-rw-r--r--source/gameengine/Rasterizer/CMakeLists.txt1
-rw-r--r--source/gameengine/Rasterizer/RAS_2DFilterManager.cpp4
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp6
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h2
-rw-r--r--source/gameengine/VideoTexture/ImageBase.cpp2
-rw-r--r--source/gameengine/VideoTexture/ImageBase.h2
-rw-r--r--source/gameengine/VideoTexture/ImageRender.cpp2
-rw-r--r--source/gameengine/VideoTexture/ImageViewport.cpp2
-rw-r--r--source/gameengine/VideoTexture/Texture.cpp2
-rw-r--r--source/gameengine/VideoTexture/VideoDeckLink.h2
681 files changed, 16156 insertions, 10881 deletions
diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h
index e92d5f2d9f7..70250310213 100644
--- a/source/blender/alembic/ABC_alembic.h
+++ b/source/blender/alembic/ABC_alembic.h
@@ -47,47 +47,63 @@ struct AlembicExportParams {
double frame_start;
double frame_end;
- double frame_step_xform;
- double frame_step_shape;
+ unsigned int frame_samples_xform;
+ unsigned int frame_samples_shape;
double shutter_open;
double shutter_close;
- /* bools */
- unsigned int selected_only : 1;
- unsigned int uvs : 1;
- unsigned int normals : 1;
- unsigned int vcolors : 1;
- unsigned int apply_subdiv : 1;
- unsigned int flatten_hierarchy : 1;
- unsigned int visible_layers_only : 1;
- unsigned int renderable_only : 1;
- unsigned int face_sets : 1;
- unsigned int use_subdiv_schema : 1;
- unsigned int packuv : 1;
- unsigned int triangulate : 1;
+ bool selected_only;
+ bool uvs;
+ bool normals;
+ bool vcolors;
+ bool apply_subdiv;
+ bool flatten_hierarchy;
+ bool visible_layers_only;
+ bool renderable_only;
+ bool face_sets;
+ bool use_subdiv_schema;
+ bool packuv;
+ bool triangulate;
+ bool export_hair;
+ bool export_particles;
unsigned int compression_type : 1;
+ /* See MOD_TRIANGULATE_NGON_xxx and MOD_TRIANGULATE_QUAD_xxx
+ * in DNA_modifier_types.h */
int quad_method;
int ngon_method;
+
float global_scale;
};
-void ABC_export(
+/* The ABC_export and ABC_import functions both take a as_background_job
+ * parameter, and return a boolean.
+ *
+ * When as_background_job=true, returns false immediately after scheduling
+ * a background job.
+ *
+ * When as_background_job=false, performs the export synchronously, and returns
+ * true when the export was ok, and false if there were any errors.
+ */
+
+bool ABC_export(
struct Scene *scene,
struct bContext *C,
const char *filepath,
- const struct AlembicExportParams *params);
+ const struct AlembicExportParams *params,
+ bool as_background_job);
-void ABC_import(struct bContext *C,
+bool ABC_import(struct bContext *C,
const char *filepath,
float scale,
bool is_sequence,
bool set_frame_range,
int sequence_len,
int offset,
- bool validate_meshes);
+ bool validate_meshes,
+ bool as_background_job);
AbcArchiveHandle *ABC_create_handle(const char *filename, struct ListBase *object_paths);
@@ -105,6 +121,7 @@ struct DerivedMesh *ABC_read_mesh(struct CacheReader *reader,
const char **err_str,
int flags);
+void CacheReader_incref(struct CacheReader *reader);
void CacheReader_free(struct CacheReader *reader);
struct CacheReader *CacheReader_open_alembic_object(struct AbcArchiveHandle *handle,
diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_archive.cc
index 5f8fc1a3739..bd16196cb78 100644
--- a/source/blender/alembic/intern/abc_archive.cc
+++ b/source/blender/alembic/intern/abc_archive.cc
@@ -23,11 +23,17 @@
*/
#include "abc_archive.h"
+extern "C"
+{
+ #include "BKE_blender_version.h"
+}
#ifdef WIN32
# include "utfconv.h"
#endif
+#include <fstream>
+
using Alembic::Abc::Exception;
using Alembic::Abc::ErrorHandler;
using Alembic::Abc::IArchive;
@@ -38,8 +44,9 @@ static IArchive open_archive(const std::string &filename,
const std::vector<std::istream *> &input_streams,
bool &is_hdf5)
{
+ is_hdf5 = false;
+
try {
- is_hdf5 = false;
Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams);
return IArchive(archive_reader(filename),
@@ -63,6 +70,27 @@ static IArchive open_archive(const std::string &filename,
return IArchive();
}
#else
+ /* Inspect the file to see whether it's really a HDF5 file. */
+ char header[4]; /* char(0x89) + "HDF" */
+ std::ifstream the_file(filename.c_str(), std::ios::in | std::ios::binary);
+ if (!the_file) {
+ std::cerr << "Unable to open " << filename << std::endl;
+ }
+ else if (!the_file.read(header, sizeof(header))) {
+ std::cerr << "Unable to read from " << filename << std::endl;
+ }
+ else if (strncmp(header + 1, "HDF", 3)) {
+ std::cerr << filename << " has an unknown file format, unable to read." << std::endl;
+ }
+ else {
+ is_hdf5 = true;
+ std::cerr << filename << " is in the obsolete HDF5 format, unable to read." << std::endl;
+ }
+
+ if (the_file.is_open()) {
+ the_file.close();
+ }
+
return IArchive();
#endif
}
@@ -83,16 +111,20 @@ ArchiveReader::ArchiveReader(const char *filename)
m_streams.push_back(&m_infile);
- bool is_hdf5;
- m_archive = open_archive(filename, m_streams, is_hdf5);
+ m_archive = open_archive(filename, m_streams, m_is_hdf5);
/* We can't open an HDF5 file from a stream, so close it. */
- if (is_hdf5) {
+ if (m_is_hdf5) {
m_infile.close();
m_streams.clear();
}
}
+bool ArchiveReader::is_hdf5() const
+{
+ return m_is_hdf5;
+}
+
bool ArchiveReader::valid() const
{
return m_archive.valid();
@@ -115,6 +147,7 @@ static OArchive create_archive(std::ostream *ostream,
{
md.set(Alembic::Abc::kApplicationNameKey, "Blender");
md.set(Alembic::Abc::kUserDescriptionKey, scene_name);
+ md.set("blender_version", versionstr);
time_t raw_time;
time(&raw_time);
diff --git a/source/blender/alembic/intern/abc_archive.h b/source/blender/alembic/intern/abc_archive.h
index d412574b736..84309fbc9df 100644
--- a/source/blender/alembic/intern/abc_archive.h
+++ b/source/blender/alembic/intern/abc_archive.h
@@ -44,12 +44,21 @@ class ArchiveReader {
Alembic::Abc::IArchive m_archive;
std::ifstream m_infile;
std::vector<std::istream *> m_streams;
+ bool m_is_hdf5;
public:
explicit ArchiveReader(const char *filename);
bool valid() const;
+ /**
+ * Returns true when either Blender is compiled with HDF5 support and
+ * the archive was succesfully opened (valid() will also return true),
+ * or when Blender was built without HDF5 support but a HDF5 file was
+ * detected (valid() will return false).
+ */
+ bool is_hdf5() const;
+
Alembic::Abc::IObject getTop();
};
diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc
index 4f70b2a972c..16416205983 100644
--- a/source/blender/alembic/intern/abc_camera.cc
+++ b/source/blender/alembic/intern/abc_camera.cc
@@ -117,11 +117,27 @@ bool AbcCameraReader::valid() const
return m_schema.valid();
}
-void AbcCameraReader::readObjectData(Main *bmain, float time)
+bool AbcCameraReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const
+{
+ if (!Alembic::AbcGeom::ICamera::matches(alembic_header)) {
+ *err_str = "Object type mismatch, Alembic object path pointed to Camera when importing, but not any more.";
+ return false;
+ }
+
+ if (ob->type != OB_CAMERA) {
+ *err_str = "Object type mismatch, Alembic object path points to Camera.";
+ return false;
+ }
+
+ return true;
+}
+
+void AbcCameraReader::readObjectData(Main *bmain, const ISampleSelector &sample_sel)
{
Camera *bcam = static_cast<Camera *>(BKE_camera_add(bmain, m_data_name.c_str()));
- ISampleSelector sample_sel(time);
CameraSample cam_sample;
m_schema.get(cam_sample, sample_sel);
diff --git a/source/blender/alembic/intern/abc_camera.h b/source/blender/alembic/intern/abc_camera.h
index fafb4d3eb39..16c5cccd5ea 100644
--- a/source/blender/alembic/intern/abc_camera.h
+++ b/source/blender/alembic/intern/abc_camera.h
@@ -54,8 +54,11 @@ public:
AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
bool valid() const;
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
- void readObjectData(Main *bmain, float time);
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
};
-#endif /* __ABC_CAMERA_H__ */ \ No newline at end of file
+#endif /* __ABC_CAMERA_H__ */
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc
index 0542255d84b..f73fe957fea 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_curves.cc
@@ -49,19 +49,26 @@ using Alembic::Abc::Int32ArraySamplePtr;
using Alembic::Abc::FloatArraySamplePtr;
using Alembic::Abc::P3fArraySamplePtr;
using Alembic::Abc::UcharArraySamplePtr;
+using Alembic::Abc::PropertyHeader;
+using Alembic::AbcGeom::ICompoundProperty;
using Alembic::AbcGeom::ICurves;
using Alembic::AbcGeom::ICurvesSchema;
using Alembic::AbcGeom::IFloatGeomParam;
+using Alembic::AbcGeom::IInt16Property;
using Alembic::AbcGeom::ISampleSelector;
using Alembic::AbcGeom::kWrapExisting;
using Alembic::AbcGeom::CurvePeriodicity;
+using Alembic::AbcGeom::OCompoundProperty;
using Alembic::AbcGeom::OCurves;
using Alembic::AbcGeom::OCurvesSchema;
+using Alembic::AbcGeom::OInt16Property;
using Alembic::AbcGeom::ON3fGeomParam;
using Alembic::AbcGeom::OV2fGeomParam;
+#define ABC_CURVE_RESOLUTION_U_PROPNAME "blender:resolution"
+
/* ************************************************************************** */
AbcCurveWriter::AbcCurveWriter(Scene *scene,
@@ -73,6 +80,11 @@ AbcCurveWriter::AbcCurveWriter(Scene *scene,
{
OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
m_schema = curves.getSchema();
+
+ Curve *cu = static_cast<Curve *>(m_object->data);
+ OCompoundProperty user_props = m_schema.getUserProperties();
+ OInt16Property user_prop_resolu(user_props, ABC_CURVE_RESOLUTION_U_PROPNAME);
+ user_prop_resolu.set(cu->resolu);
}
void AbcCurveWriter::do_write()
@@ -95,7 +107,7 @@ void AbcCurveWriter::do_write()
for (; nurbs; nurbs = nurbs->next) {
if (nurbs->bp) {
curve_basis = Alembic::AbcGeom::kNoBasis;
- curve_type = Alembic::AbcGeom::kLinear;
+ curve_type = Alembic::AbcGeom::kVariableOrder;
const int totpoint = nurbs->pntsu * nurbs->pntsv;
@@ -160,7 +172,7 @@ void AbcCurveWriter::do_write()
}
}
- orders.push_back(nurbs->orderu + 1);
+ orders.push_back(nurbs->orderu);
vert_counts.push_back(verts.size());
}
@@ -199,17 +211,44 @@ bool AbcCurveReader::valid() const
return m_curves_schema.valid();
}
-void AbcCurveReader::readObjectData(Main *bmain, float time)
+bool AbcCurveReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const
+{
+ if (!Alembic::AbcGeom::ICurves::matches(alembic_header)) {
+ *err_str = "Object type mismatch, Alembic object path pointed to Curves when importing, but not any more.";
+ return false;
+ }
+
+ if (ob->type != OB_CURVE) {
+ *err_str = "Object type mismatch, Alembic object path points to Curves.";
+ return false;
+ }
+
+ return true;
+}
+
+void AbcCurveReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
{
Curve *cu = BKE_curve_add(bmain, m_data_name.c_str(), OB_CURVE);
cu->flag |= CU_DEFORM_FILL | CU_3D;
cu->actvert = CU_ACT_NONE;
+ cu->resolu = 1;
+
+ ICompoundProperty user_props = m_curves_schema.getUserProperties();
+ if (user_props) {
+ const PropertyHeader *header = user_props.getPropertyHeader(ABC_CURVE_RESOLUTION_U_PROPNAME);
+ if (header != NULL && header->isScalar() && IInt16Property::matches(*header)) {
+ IInt16Property resolu(user_props, header->getName());
+ cu->resolu = resolu.getValue(sample_sel);
+ }
+ }
m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str());
m_object->data = cu;
- read_curve_sample(cu, m_curves_schema, time);
+ read_curve_sample(cu, m_curves_schema, sample_sel);
if (has_animations(m_curves_schema, m_settings)) {
addCacheModifier();
@@ -218,9 +257,8 @@ void AbcCurveReader::readObjectData(Main *bmain, float time)
/* ************************************************************************** */
-void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
+void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const ISampleSelector &sample_sel)
{
- const ISampleSelector sample_sel(time);
ICurvesSchema::Sample smp = schema.getValue(sample_sel);
const Int32ArraySamplePtr num_vertices = smp.getCurvesNumVertices();
const P3fArraySamplePtr positions = smp.getPositions();
@@ -250,13 +288,19 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
nu->pntsv = 1;
nu->flag |= CU_SMOOTH;
- nu->orderu = num_verts;
-
- if (smp.getType() == Alembic::AbcGeom::kCubic) {
- nu->orderu = 3;
- }
- else if (orders && orders->size() > i) {
- nu->orderu = static_cast<short>((*orders)[i] - 1);
+ switch (smp.getType()) {
+ case Alembic::AbcGeom::kCubic:
+ nu->orderu = 4;
+ break;
+ case Alembic::AbcGeom::kVariableOrder:
+ if (orders && orders->size() > i) {
+ nu->orderu = static_cast<short>((*orders)[i]);
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ case Alembic::AbcGeom::kLinear:
+ default:
+ nu->orderu = 2;
}
if (periodicity == Alembic::AbcGeom::kNonPeriodic) {
@@ -361,9 +405,11 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
* object directly and create a new DerivedMesh from that. Also we might need to
* create new or delete existing NURBS in the curve.
*/
-DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float time, int /*read_flag*/, const char ** /*err_str*/)
+DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/,
+ const ISampleSelector &sample_sel,
+ int /*read_flag*/,
+ const char ** /*err_str*/)
{
- ISampleSelector sample_sel(time);
const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel);
const P3fArraySamplePtr &positions = sample.getPositions();
@@ -377,7 +423,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float
if (curve_count != num_vertices->size()) {
BKE_nurbList_free(&curve->nurb);
- read_curve_sample(curve, m_curves_schema, time);
+ read_curve_sample(curve, m_curves_schema, sample_sel);
}
else {
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_curves.h
index 2757d179a47..a9231f947b2 100644
--- a/source/blender/alembic/intern/abc_curves.h
+++ b/source/blender/alembic/intern/abc_curves.h
@@ -54,13 +54,21 @@ public:
AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
bool valid() const;
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
- void readObjectData(Main *bmain, float time);
- DerivedMesh *read_derivedmesh(DerivedMesh *, const float time, int read_flag, const char **err_str);
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm,
+ const Alembic::Abc::ISampleSelector &sample_sel,
+ int read_flag,
+ const char **err_str);
};
/* ************************************************************************** */
-void read_curve_sample(Curve *cu, const Alembic::AbcGeom::ICurvesSchema &schema, const float time);
+void read_curve_sample(Curve *cu,
+ const Alembic::AbcGeom::ICurvesSchema &schema,
+ const Alembic::Abc::ISampleSelector &sample_selector);
#endif /* __ABC_CURVES_H__ */
diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc
index 0d11ab79ddd..1d2bc689027 100644
--- a/source/blender/alembic/intern/abc_customdata.cc
+++ b/source/blender/alembic/intern/abc_customdata.cc
@@ -227,48 +227,6 @@ using Alembic::AbcGeom::IC3fGeomParam;
using Alembic::AbcGeom::IC4fGeomParam;
using Alembic::AbcGeom::IV2fGeomParam;
-static void read_mcols(const CDStreamConfig &config, void *data,
- const C3fArraySamplePtr &c3f_ptr, const C4fArraySamplePtr &c4f_ptr)
-{
- MCol *cfaces = static_cast<MCol *>(data);
- MPoly *polys = config.mpoly;
- MLoop *mloops = config.mloop;
-
- if (c3f_ptr) {
- for (int i = 0; i < config.totpoly; ++i) {
- MPoly *p = &polys[i];
- MCol *cface = &cfaces[p->loopstart + p->totloop];
- MLoop *mloop = &mloops[p->loopstart + p->totloop];
-
- for (int j = 0; j < p->totloop; ++j) {
- cface--;
- mloop--;
- const Imath::C3f &color = (*c3f_ptr)[mloop->v];
- cface->a = FTOCHAR(color[0]);
- cface->r = FTOCHAR(color[1]);
- cface->g = FTOCHAR(color[2]);
- cface->b = 255;
- }
- }
- }
- else if (c4f_ptr) {
- for (int i = 0; i < config.totpoly; ++i) {
- MPoly *p = &polys[i];
- MCol *cface = &cfaces[p->loopstart + p->totloop];
- MLoop *mloop = &mloops[p->loopstart + p->totloop];
-
- for (int j = 0; j < p->totloop; ++j) {
- cface--;
- mloop--;
- const Imath::C4f &color = (*c4f_ptr)[mloop->v];
- cface->a = FTOCHAR(color[0]);
- cface->r = FTOCHAR(color[1]);
- cface->g = FTOCHAR(color[2]);
- cface->b = FTOCHAR(color[3]);
- }
- }
- }
-}
static void read_uvs(const CDStreamConfig &config, void *data,
const Alembic::AbcGeom::V2fArraySamplePtr &uvs,
@@ -294,57 +252,108 @@ static void read_uvs(const CDStreamConfig &config, void *data,
}
}
-static void read_custom_data_ex(const ICompoundProperty &prop,
- const PropertyHeader &prop_header,
- const CDStreamConfig &config,
- const Alembic::Abc::ISampleSelector &iss,
- int data_type)
+static void read_custom_data_mcols(const ICompoundProperty &arbGeomParams,
+ const PropertyHeader &prop_header,
+ const CDStreamConfig &config,
+ const Alembic::Abc::ISampleSelector &iss)
{
- if (data_type == CD_MLOOPCOL) {
- C3fArraySamplePtr c3f_ptr = C3fArraySamplePtr();
- C4fArraySamplePtr c4f_ptr = C4fArraySamplePtr();
+ C3fArraySamplePtr c3f_ptr = C3fArraySamplePtr();
+ C4fArraySamplePtr c4f_ptr = C4fArraySamplePtr();
+ bool use_c3f_ptr;
+ bool is_facevarying;
+
+ /* Find the correct interpretation of the data */
+ if (IC3fGeomParam::matches(prop_header)) {
+ IC3fGeomParam color_param(arbGeomParams, prop_header.getName());
+ IC3fGeomParam::Sample sample;
+ BLI_assert(!strcmp("rgb", color_param.getInterpretation()));
+
+ color_param.getIndexed(sample, iss);
+ is_facevarying = sample.getScope() == kFacevaryingScope &&
+ config.totloop == sample.getIndices()->size();
+
+ c3f_ptr = sample.getVals();
+ use_c3f_ptr = true;
+ }
+ else if (IC4fGeomParam::matches(prop_header)) {
+ IC4fGeomParam color_param(arbGeomParams, prop_header.getName());
+ IC4fGeomParam::Sample sample;
+ BLI_assert(!strcmp("rgba", color_param.getInterpretation()));
- if (IC3fGeomParam::matches(prop_header)) {
- IC3fGeomParam color_param(prop, prop_header.getName());
- IC3fGeomParam::Sample sample;
- color_param.getIndexed(sample, iss);
+ color_param.getIndexed(sample, iss);
+ is_facevarying = sample.getScope() == kFacevaryingScope &&
+ config.totloop == sample.getIndices()->size();
- c3f_ptr = sample.getVals();
- }
- else if (IC4fGeomParam::matches(prop_header)) {
- IC4fGeomParam color_param(prop, prop_header.getName());
- IC4fGeomParam::Sample sample;
- color_param.getIndexed(sample, iss);
+ c4f_ptr = sample.getVals();
+ use_c3f_ptr = false;
+ }
+ else {
+ /* this won't happen due to the checks in read_custom_data() */
+ return;
+ }
+ BLI_assert(c3f_ptr || c4f_ptr);
- c4f_ptr = sample.getVals();
- }
+ /* Read the vertex colors */
+ void *cd_data = config.add_customdata_cb(config.user_data,
+ prop_header.getName().c_str(),
+ CD_MLOOPCOL);
+ MCol *cfaces = static_cast<MCol *>(cd_data);
+ MPoly *mpolys = config.mpoly;
+ MLoop *mloops = config.mloop;
- void *cd_data = config.add_customdata_cb(config.user_data,
- prop_header.getName().c_str(),
- data_type);
+ size_t face_index = 0;
+ size_t color_index;
+ for (int i = 0; i < config.totpoly; ++i) {
+ MPoly *poly = &mpolys[i];
+ MCol *cface = &cfaces[poly->loopstart + poly->totloop];
+ MLoop *mloop = &mloops[poly->loopstart + poly->totloop];
- read_mcols(config, cd_data, c3f_ptr, c4f_ptr);
- }
- else if (data_type == CD_MLOOPUV) {
- IV2fGeomParam uv_param(prop, prop_header.getName());
+ for (int j = 0; j < poly->totloop; ++j, ++face_index) {
+ --cface;
+ --mloop;
+ color_index = is_facevarying ? face_index : mloop->v;
- if (!uv_param.isIndexed()) {
- return;
+ if (use_c3f_ptr) {
+ const Imath::C3f &color = (*c3f_ptr)[color_index];
+ cface->a = FTOCHAR(color[0]);
+ cface->r = FTOCHAR(color[1]);
+ cface->g = FTOCHAR(color[2]);
+ cface->b = 255;
+ }
+ else {
+ const Imath::C4f &color = (*c4f_ptr)[color_index];
+ cface->a = FTOCHAR(color[0]);
+ cface->r = FTOCHAR(color[1]);
+ cface->g = FTOCHAR(color[2]);
+ cface->b = FTOCHAR(color[3]);
+ }
}
+ }
+}
- IV2fGeomParam::Sample sample;
- uv_param.getIndexed(sample, iss);
+static void read_custom_data_uvs(const ICompoundProperty &prop,
+ const PropertyHeader &prop_header,
+ const CDStreamConfig &config,
+ const Alembic::Abc::ISampleSelector &iss)
+{
+ IV2fGeomParam uv_param(prop, prop_header.getName());
- if (uv_param.getScope() != kFacevaryingScope) {
- return;
- }
+ if (!uv_param.isIndexed()) {
+ return;
+ }
- void *cd_data = config.add_customdata_cb(config.user_data,
- prop_header.getName().c_str(),
- data_type);
+ IV2fGeomParam::Sample sample;
+ uv_param.getIndexed(sample, iss);
- read_uvs(config, cd_data, sample.getVals(), sample.getIndices());
+ if (uv_param.getScope() != kFacevaryingScope) {
+ return;
}
+
+ void *cd_data = config.add_customdata_cb(config.user_data,
+ prop_header.getName().c_str(),
+ CD_MLOOPUV);
+
+ read_uvs(config, cd_data, sample.getVals(), sample.getIndices());
}
void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss)
@@ -367,7 +376,7 @@ void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &confi
continue;
}
- read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPUV);
+ read_custom_data_uvs(prop, prop_header, config, iss);
continue;
}
@@ -377,7 +386,7 @@ void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &confi
continue;
}
- read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPCOL);
+ read_custom_data_mcols(prop, prop_header, config, iss);
continue;
}
}
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 90a99469389..4fe65b96f36 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -66,13 +66,14 @@ using Alembic::Abc::OBox3dProperty;
ExportSettings::ExportSettings()
: scene(NULL)
+ , logger()
, selected_only(false)
, visible_layers_only(false)
, renderable_only(false)
, frame_start(1)
, frame_end(1)
- , frame_step_xform(1)
- , frame_step_shape(1)
+ , frame_samples_xform(1)
+ , frame_samples_shape(1)
, shutter_open(0.0)
, shutter_close(1.0)
, global_scale(1.0f)
@@ -82,6 +83,8 @@ ExportSettings::ExportSettings()
, export_vcols(false)
, export_face_sets(false)
, export_vweigths(false)
+ , export_hair(true)
+ , export_particles(true)
, apply_subdiv(false)
, use_subdiv_schema(false)
, export_child_hairs(true)
@@ -105,7 +108,7 @@ static bool object_is_smoke_sim(Object *ob)
return false;
}
-static bool object_is_shape(Object *ob)
+static bool object_type_is_exportable(Object *ob)
{
switch (ob->type) {
case OB_MESH:
@@ -114,6 +117,7 @@ static bool object_is_shape(Object *ob)
}
return true;
+ case OB_EMPTY:
case OB_CURVE:
case OB_SURF:
case OB_CAMERA:
@@ -123,14 +127,31 @@ static bool object_is_shape(Object *ob)
}
}
-static bool export_object(const ExportSettings * const settings, Object *ob)
+
+/**
+ * Returns whether this object should be exported into the Alembic file.
+ *
+ * \param settings: export settings, used for options like 'selected only'.
+ * \param ob: the object in question.
+ * \param is_duplicated: Normally false; true when the object is instanced
+ * into the scene by a dupli-object (e.g. part of a dupligroup).
+ * This ignores selection and layer visibility,
+ * and assumes that the dupli-object itself (e.g. the group-instantiating empty) is exported.
+ */
+static bool export_object(const ExportSettings * const settings, Object *ob,
+ bool is_duplicated)
{
- if (settings->selected_only && !parent_selected(ob)) {
- return false;
- }
+ if (!is_duplicated) {
+ /* These two tests only make sense when the object isn't being instanced
+ * into the scene. When it is, its exportability is determined by
+ * its dupli-object and the DupliObject::no_draw property. */
+ if (settings->selected_only && !parent_selected(ob)) {
+ return false;
+ }
- if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) {
- return false;
+ if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) {
+ return false;
+ }
}
if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
@@ -153,11 +174,13 @@ AbcExporter::AbcExporter(Scene *scene, const char *filename, ExportSettings &set
AbcExporter::~AbcExporter()
{
- std::map<std::string, AbcTransformWriter*>::iterator it, e;
- for (it = m_xforms.begin(), e = m_xforms.end(); it != e; ++it) {
- delete it->second;
+ /* Free xforms map */
+ m_xforms_type::iterator it_x, e_x;
+ for (it_x = m_xforms.begin(), e_x = m_xforms.end(); it_x != e_x; ++it_x) {
+ delete it_x->second;
}
+ /* Free shapes vector */
for (int i = 0, e = m_shapes.size(); i != e; ++i) {
delete m_shapes[i];
}
@@ -165,60 +188,56 @@ AbcExporter::~AbcExporter()
delete m_writer;
}
-void AbcExporter::getShutterSamples(double step, bool time_relative,
+void AbcExporter::getShutterSamples(unsigned int nr_of_samples,
+ bool time_relative,
std::vector<double> &samples)
{
+ Scene *scene = m_scene; /* for use in the FPS macro */
samples.clear();
- const double time_factor = time_relative ? m_scene->r.frs_sec : 1.0;
- const double shutter_open = m_settings.shutter_open;
- const double shutter_close = m_settings.shutter_close;
+ unsigned int frame_offset = time_relative ? m_settings.frame_start : 0;
+ double time_factor = time_relative ? FPS : 1.0;
+ double shutter_open = m_settings.shutter_open;
+ double shutter_close = m_settings.shutter_close;
+ double time_inc = (shutter_close - shutter_open) / nr_of_samples;
- /* sample all frame */
- if (shutter_open == 0.0 && shutter_close == 1.0) {
- for (double t = 0.0; t < 1.0; t += step) {
- samples.push_back((t + m_settings.frame_start) / time_factor);
- }
- }
- else {
- /* sample between shutter open & close */
- const int nsamples = static_cast<int>(std::max((1.0 / step) - 1.0, 1.0));
- const double time_inc = (shutter_close - shutter_open) / nsamples;
+ /* sample between shutter open & close */
+ for (int sample=0; sample < nr_of_samples; ++sample) {
+ double sample_time = shutter_open + time_inc * sample;
+ double time = (frame_offset + sample_time) / time_factor;
- for (double t = shutter_open; t <= shutter_close; t += time_inc) {
- samples.push_back((t + m_settings.frame_start) / time_factor);
- }
+ samples.push_back(time);
}
}
Alembic::Abc::TimeSamplingPtr AbcExporter::createTimeSampling(double step)
{
- TimeSamplingPtr time_sampling;
std::vector<double> samples;
if (m_settings.frame_start == m_settings.frame_end) {
- time_sampling.reset(new Alembic::Abc::TimeSampling());
- return time_sampling;
+ return TimeSamplingPtr(new Alembic::Abc::TimeSampling());
}
getShutterSamples(step, true, samples);
- Alembic::Abc::TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / m_scene->r.frs_sec);
- time_sampling.reset(new Alembic::Abc::TimeSampling(ts, samples));
+ Alembic::Abc::TimeSamplingType ts(
+ static_cast<uint32_t>(samples.size()),
+ 1.0 / m_scene->r.frs_sec);
- return time_sampling;
+ return TimeSamplingPtr(new Alembic::Abc::TimeSampling(ts, samples));
}
-void AbcExporter::getFrameSet(double step, std::set<double> &frames)
+void AbcExporter::getFrameSet(unsigned int nr_of_samples,
+ std::set<double> &frames)
{
frames.clear();
std::vector<double> shutter_samples;
- getShutterSamples(step, false, shutter_samples);
+ getShutterSamples(nr_of_samples, false, shutter_samples);
for (double frame = m_settings.frame_start; frame <= m_settings.frame_end; frame += 1.0) {
- for (int j = 0, e = shutter_samples.size(); j < e; ++j) {
+ for (size_t j = 0; j < nr_of_samples; ++j) {
frames.insert(frame + shutter_samples[j]);
}
}
@@ -250,44 +269,37 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
/* Create time samplings for transforms and shapes. */
- TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform);
+ TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_samples_xform);
m_trans_sampling_index = m_writer->archive().addTimeSampling(*trans_time);
TimeSamplingPtr shape_time;
- if ((m_settings.frame_step_shape == m_settings.frame_step_xform) ||
+ if ((m_settings.frame_samples_shape == m_settings.frame_samples_xform) ||
(m_settings.frame_start == m_settings.frame_end))
{
shape_time = trans_time;
m_shape_sampling_index = m_trans_sampling_index;
}
else {
- shape_time = createTimeSampling(m_settings.frame_step_shape);
+ shape_time = createTimeSampling(m_settings.frame_samples_shape);
m_shape_sampling_index = m_writer->archive().addTimeSampling(*shape_time);
}
OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_writer->archive(), m_trans_sampling_index);
- if (m_settings.flatten_hierarchy) {
- createTransformWritersFlat();
- }
- else {
- createTransformWritersHierarchy(bmain->eval_ctx);
- }
-
+ createTransformWritersHierarchy(bmain->eval_ctx);
createShapeWriters(bmain->eval_ctx);
/* Make a list of frames to export. */
std::set<double> xform_frames;
- getFrameSet(m_settings.frame_step_xform, xform_frames);
+ getFrameSet(m_settings.frame_samples_xform, xform_frames);
std::set<double> shape_frames;
- getFrameSet(m_settings.frame_step_shape, shape_frames);
+ getFrameSet(m_settings.frame_samples_shape, shape_frames);
/* Merge all frames needed. */
-
std::set<double> frames(xform_frames);
frames.insert(shape_frames.begin(), shape_frames.end());
@@ -310,7 +322,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
const double frame = *begin;
/* 'frame' is offset by start frame, so need to cancel the offset. */
- setCurrentFrame(bmain, frame - m_settings.frame_start);
+ setCurrentFrame(bmain, frame);
if (shape_frames.count(frame) != 0) {
for (int i = 0, e = m_shapes.size(); i != e; ++i) {
@@ -322,7 +334,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
continue;
}
- std::map<std::string, AbcTransformWriter *>::iterator xit, xe;
+ m_xforms_type::iterator xit, xe;
for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) {
xit->second->write();
}
@@ -346,34 +358,16 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
while (base) {
Object *ob = base->object;
- if (export_object(&m_settings, ob)) {
- switch(ob->type) {
- case OB_LAMP:
- case OB_LATTICE:
- case OB_MBALL:
- case OB_SPEAKER:
- /* We do not export transforms for objects of these classes. */
- break;
-
- default:
- exploreTransform(eval_ctx, ob, ob->parent, NULL);
- }
- }
-
- base = base->next;
- }
-}
+ switch (ob->type) {
+ case OB_LAMP:
+ case OB_LATTICE:
+ case OB_MBALL:
+ case OB_SPEAKER:
+ /* We do not export transforms for objects of these classes. */
+ break;
-void AbcExporter::createTransformWritersFlat()
-{
- Base *base = static_cast<Base *>(m_scene->base.first);
-
- while (base) {
- Object *ob = base->object;
-
- if (export_object(&m_settings, ob) && object_is_shape(ob)) {
- std::string name = get_id_name(ob);
- m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), 0, m_trans_sampling_index, m_settings);
+ default:
+ exploreTransform(eval_ctx, ob, ob->parent);
}
base = base->next;
@@ -382,8 +376,13 @@ void AbcExporter::createTransformWritersFlat()
void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent)
{
+ /* If an object isn't exported itself, its duplilist shouldn't be
+ * exported either. */
+ if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
+ return;
+ }
- if (export_object(&m_settings, ob) && object_is_shape(ob)) {
+ if (object_type_is_exportable(ob)) {
createTransformWriter(ob, parent, dupliObParent);
}
@@ -394,68 +393,91 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Obje
Object *dupli_ob = NULL;
Object *dupli_parent = NULL;
- while (link) {
+ for (; link; link = link->next) {
+ /* This skips things like custom bone shapes. */
+ if (m_settings.renderable_only && link->no_draw) {
+ continue;
+ }
+
if (link->type == OB_DUPLIGROUP) {
dupli_ob = link->ob;
dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob;
exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob);
}
-
- link = link->next;
}
}
free_object_duplilist(lb);
}
-void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent)
+AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent)
{
- const std::string name = get_object_dag_path_name(ob, dupliObParent);
-
/* An object should not be its own parent, or we'll get infinite loops. */
BLI_assert(ob != parent);
BLI_assert(ob != dupliObParent);
- /* check if we have already created a transform writer for this object */
- if (getXForm(name) != NULL){
- std::cerr << "xform " << name << " already exists\n";
- return;
+ std::string name;
+ if (m_settings.flatten_hierarchy) {
+ name = get_id_name(ob);
+ }
+ else {
+ name = get_object_dag_path_name(ob, dupliObParent);
}
- AbcTransformWriter *parent_xform = NULL;
+ /* check if we have already created a transform writer for this object */
+ AbcTransformWriter *my_writer = getXForm(name);
+ if (my_writer != NULL) {
+ return my_writer;
+ }
- if (parent) {
- const std::string parentname = get_object_dag_path_name(parent, dupliObParent);
- parent_xform = getXForm(parentname);
+ AbcTransformWriter *parent_writer = NULL;
+ Alembic::Abc::OObject alembic_parent;
- if (!parent_xform) {
- if (parent->parent) {
- createTransformWriter(parent, parent->parent, dupliObParent);
+ if (m_settings.flatten_hierarchy || parent == NULL) {
+ /* Parentless objects still have the "top object" as parent
+ * in Alembic. */
+ alembic_parent = m_writer->archive().getTop();
+ }
+ else {
+ /* Since there are so many different ways to find parents (as evident
+ * in the number of conditions below), we can't really look up the
+ * parent by name. We'll just call createTransformWriter(), which will
+ * return the parent's AbcTransformWriter pointer. */
+ if (parent->parent) {
+ if (parent == dupliObParent) {
+ parent_writer = createTransformWriter(parent, parent->parent, NULL);
+ }
+ else {
+ parent_writer = createTransformWriter(parent, parent->parent, dupliObParent);
}
- else if (parent == dupliObParent) {
- if (dupliObParent->parent == NULL) {
- createTransformWriter(parent, NULL, NULL);
- }
- else {
- createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent);
- }
+ }
+ else if (parent == dupliObParent) {
+ if (dupliObParent->parent == NULL) {
+ parent_writer = createTransformWriter(parent, NULL, NULL);
}
else {
- createTransformWriter(parent, dupliObParent, dupliObParent);
+ parent_writer = createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent);
}
-
- parent_xform = getXForm(parentname);
}
- }
+ else {
+ parent_writer = createTransformWriter(parent, dupliObParent, dupliObParent);
+ }
- if (parent_xform) {
- m_xforms[name] = new AbcTransformWriter(ob, parent_xform->alembicXform(), parent_xform, m_trans_sampling_index, m_settings);
- m_xforms[name]->setParent(parent);
+ BLI_assert(parent_writer);
+ alembic_parent = parent_writer->alembicXform();
}
- else {
- m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), NULL, m_trans_sampling_index, m_settings);
+
+ my_writer = new AbcTransformWriter(ob, alembic_parent, parent_writer,
+ m_trans_sampling_index, m_settings);
+
+ /* When flattening, the matrix of the dupliobject has to be added. */
+ if (m_settings.flatten_hierarchy && dupliObParent) {
+ my_writer->m_proxy_from = dupliObParent;
}
+
+ m_xforms[name] = my_writer;
+ return my_writer;
}
void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
@@ -472,32 +494,60 @@ void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent)
{
- ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
-
+ /* If an object isn't exported itself, its duplilist shouldn't be
+ * exported either. */
+ if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
+ return;
+ }
+
createShapeWriter(ob, dupliObParent);
+ ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
+
if (lb) {
- DupliObject *dupliob = static_cast<DupliObject *>(lb->first);
+ DupliObject *link = static_cast<DupliObject *>(lb->first);
- while (dupliob) {
- if (dupliob->type == OB_DUPLIGROUP) {
- exploreObject(eval_ctx, dupliob->ob, ob);
+ for (; link; link = link->next) {
+ /* This skips things like custom bone shapes. */
+ if (m_settings.renderable_only && link->no_draw) {
+ continue;
}
- dupliob = dupliob->next;
+ if (link->type == OB_DUPLIGROUP) {
+ exploreObject(eval_ctx, link->ob, ob);
+ }
}
}
free_object_duplilist(lb);
}
-void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
+void AbcExporter::createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform)
{
- if (!object_is_shape(ob)) {
+ if (!m_settings.export_hair && !m_settings.export_particles) {
return;
}
- if (!export_object(&m_settings, ob)) {
+ ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
+
+ for (; psys; psys = psys->next) {
+ if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) {
+ continue;
+ }
+
+ if (m_settings.export_hair && psys->part->type == PART_HAIR) {
+ m_settings.export_child_hairs = true;
+ m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
+ }
+ else if (m_settings.export_particles && psys->part->type == PART_EMITTER) {
+ m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
+ }
+ }
+}
+
+void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
+{
+ if (!object_type_is_exportable(ob)) {
return;
}
@@ -513,32 +563,18 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
AbcTransformWriter *xform = getXForm(name);
if (!xform) {
- std::cerr << __func__ << ": xform " << name << " is NULL\n";
+ ABC_LOG(m_settings.logger) << __func__ << ": xform " << name << " is NULL\n";
return;
}
- ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
+ createParticleSystemsWriters(ob, xform);
- for (; psys; psys = psys->next) {
- if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) {
- continue;
- }
-
- if (psys->part->type == PART_HAIR) {
- m_settings.export_child_hairs = true;
- m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
- }
- else if (psys->part->type == PART_EMITTER) {
- m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
- }
- }
-
- switch(ob->type) {
+ switch (ob->type) {
case OB_MESH:
{
Mesh *me = static_cast<Mesh *>(ob->data);
- if (!me || me->totvert == 0) {
+ if (!me) {
return;
}
diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h
index b0eb8e185d6..f763922a73b 100644
--- a/source/blender/alembic/intern/abc_exporter.h
+++ b/source/blender/alembic/intern/abc_exporter.h
@@ -28,6 +28,8 @@
#include <set>
#include <vector>
+#include "abc_util.h"
+
class AbcObjectWriter;
class AbcTransformWriter;
class ArchiveWriter;
@@ -41,14 +43,15 @@ struct ExportSettings {
ExportSettings();
Scene *scene;
+ SimpleLogger logger;
bool selected_only;
bool visible_layers_only;
bool renderable_only;
double frame_start, frame_end;
- double frame_step_xform;
- double frame_step_shape;
+ double frame_samples_xform;
+ double frame_samples_shape;
double shutter_open;
double shutter_close;
float global_scale;
@@ -60,6 +63,8 @@ struct ExportSettings {
bool export_vcols;
bool export_face_sets;
bool export_vweigths;
+ bool export_hair;
+ bool export_particles;
bool apply_subdiv;
bool use_subdiv_schema;
@@ -86,7 +91,10 @@ class AbcExporter {
ArchiveWriter *m_writer;
- std::map<std::string, AbcTransformWriter *> m_xforms;
+ /* mapping from name to transform writer */
+ typedef std::map<std::string, AbcTransformWriter *> m_xforms_type;
+ m_xforms_type m_xforms;
+
std::vector<AbcObjectWriter *> m_shapes;
public:
@@ -95,20 +103,22 @@ public:
void operator()(Main *bmain, float &progress, bool &was_canceled);
-private:
- void getShutterSamples(double step, bool time_relative, std::vector<double> &samples);
+protected:
+ void getShutterSamples(unsigned int nr_of_samples,
+ bool time_relative,
+ std::vector<double> &samples);
+ void getFrameSet(unsigned int nr_of_samples, std::set<double> &frames);
+private:
Alembic::Abc::TimeSamplingPtr createTimeSampling(double step);
- void getFrameSet(double step, std::set<double> &frames);
-
void createTransformWritersHierarchy(EvaluationContext *eval_ctx);
- void createTransformWritersFlat();
- void createTransformWriter(Object *ob, Object *parent, Object *dupliObParent);
+ AbcTransformWriter * createTransformWriter(Object *ob, Object *parent, Object *dupliObParent);
void exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent = NULL);
void exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent);
void createShapeWriters(EvaluationContext *eval_ctx);
void createShapeWriter(Object *ob, Object *dupliObParent);
+ void createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform);
AbcTransformWriter *getXForm(const std::string &name);
diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc
index e328df24e53..8f8ed2019d5 100644
--- a/source/blender/alembic/intern/abc_hair.cc
+++ b/source/blender/alembic/intern/abc_hair.cc
@@ -56,6 +56,7 @@ AbcHairWriter::AbcHairWriter(Scene *scene,
ExportSettings &settings,
ParticleSystem *psys)
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ , m_uv_warning_shown(false)
{
m_psys = psys;
@@ -75,7 +76,7 @@ void AbcHairWriter::do_write()
return;
}
- DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH);
+ DerivedMesh *dm = mesh_create_derived_render(m_scene, m_object, CD_MASK_MESH);
DM_ensure_tessface(dm);
std::vector<Imath::V3f> verts;
@@ -132,8 +133,10 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
MFace *mface = dm->getTessFaceArray(dm);
MVert *mverts = dm->getVertArray(dm);
- if (!mtface || !mface) {
- std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n");
+ if ((!mtface || !mface) && !m_uv_warning_shown) {
+ std::fprintf(stderr, "Warning, no UV set found for underlying geometry of %s.\n",
+ m_object->id.name + 2);
+ m_uv_warning_shown = true;
}
ParticleData * pa = m_psys->particles;
@@ -238,13 +241,8 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
invert_m4_m4_safe(inv_mat, m_object->obmat);
MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE));
- MFace *mface = dm->getTessFaceArray(dm);
MVert *mverts = dm->getVertArray(dm);
- if (!mtface || !mface) {
- std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n");
- }
-
ParticleCacheKey **cache = m_psys->childcache;
ParticleCacheKey *path;
@@ -253,22 +251,37 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
for (int p = 0; p < m_psys->totchild; ++p, ++pc) {
path = cache[p];
- if (part->from == PART_FROM_FACE) {
+ if (part->from == PART_FROM_FACE &&
+ part->childtype != PART_CHILD_PARTICLES &&
+ mtface) {
const int num = pc->num;
+ if (num < 0) {
+ ABC_LOG(m_settings.logger)
+ << "Warning, child particle of hair system " << m_psys->name
+ << " has unknown face index of geometry of "<< (m_object->id.name + 2)
+ << ", skipping child hair." << std::endl;
+ continue;
+ }
MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE));
MTFace *tface = mtface + num;
- if (mface && mtface) {
- float r_uv[2], tmpnor[3], mapfw[4], vec[3];
+ float r_uv[2], tmpnor[3], mapfw[4], vec[3];
- psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv);
- uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1]));
+ psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv);
+ uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1]));
- psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, tmpnor, NULL, NULL, NULL, NULL);
+ psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, tmpnor, NULL, NULL, NULL, NULL);
- /* Convert Z-up to Y-up. */
- norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1]));
+ /* Convert Z-up to Y-up. */
+ norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1]));
+ }
+ else {
+ if (uv_values.size()) {
+ uv_values.push_back(uv_values[pc->parent]);
+ }
+ if (norm_values.size()) {
+ norm_values.push_back(norm_values[pc->parent]);
}
}
diff --git a/source/blender/alembic/intern/abc_hair.h b/source/blender/alembic/intern/abc_hair.h
index d132b60be12..61f5fe361f8 100644
--- a/source/blender/alembic/intern/abc_hair.h
+++ b/source/blender/alembic/intern/abc_hair.h
@@ -37,6 +37,8 @@ class AbcHairWriter : public AbcObjectWriter {
Alembic::AbcGeom::OCurvesSchema m_schema;
Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
+ bool m_uv_warning_shown;
+
public:
AbcHairWriter(Scene *scene,
Object *ob,
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index 5a57e43326a..9a4ca6f99a8 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -355,7 +355,7 @@ bool AbcMeshWriter::isAnimated() const
md = md->next;
}
- return false;
+ return me->adt != NULL;
}
void AbcMeshWriter::do_write()
@@ -897,19 +897,31 @@ static void *add_customdata_cb(void *user_data, const char *name, int data_type)
{
DerivedMesh *dm = static_cast<DerivedMesh *>(user_data);
CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
- void *cd_ptr = NULL;
-
- if (ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) {
- cd_ptr = CustomData_get_layer_named(dm->getLoopDataLayout(dm), cd_data_type, name);
-
- if (cd_ptr == NULL) {
- cd_ptr = CustomData_add_layer_named(dm->getLoopDataLayout(dm),
- cd_data_type,
- CD_DEFAULT,
- NULL,
- dm->getNumLoops(dm),
- name);
- }
+ void *cd_ptr;
+ CustomData *loopdata;
+ int numloops;
+
+ /* unsupported custom data type -- don't do anything. */
+ if (!ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) {
+ return NULL;
+ }
+
+ loopdata = dm->getLoopDataLayout(dm);
+ cd_ptr = CustomData_get_layer_named(loopdata, cd_data_type, name);
+ if (cd_ptr != NULL) {
+ /* layer already exists, so just return it. */
+ return cd_ptr;
+ }
+
+ /* create a new layer, taking care to construct the hopefully-soon-to-be-removed
+ * CD_MTEXPOLY layer too, with the same name. */
+ numloops = dm->getNumLoops(dm);
+ cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_DEFAULT,
+ NULL, numloops, name);
+ if (cd_data_type == CD_MLOOPUV) {
+ CustomData_add_layer_named(dm->getPolyDataLayout(dm),
+ CD_MTEXPOLY, CD_DEFAULT,
+ NULL, numloops, name);
}
return cd_ptr;
@@ -1009,17 +1021,15 @@ bool AbcMeshReader::valid() const
return m_schema.valid();
}
-void AbcMeshReader::readObjectData(Main *bmain, float time)
+void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
{
Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
m_object->data = mesh;
- const ISampleSelector sample_sel(time);
-
DerivedMesh *dm = CDDM_from_mesh(mesh);
- DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL, NULL);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, MOD_MESHSEQ_READ_ALL, NULL);
if (ndm != dm) {
dm->release(dm);
@@ -1038,9 +1048,28 @@ void AbcMeshReader::readObjectData(Main *bmain, float time)
}
}
-DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str)
+bool AbcMeshReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const
+{
+ if (!Alembic::AbcGeom::IPolyMesh::matches(alembic_header)) {
+ *err_str = "Object type mismatch, Alembic object path pointed to PolyMesh when importing, but not any more.";
+ return false;
+ }
+
+ if (ob->type != OB_MESH) {
+ *err_str = "Object type mismatch, Alembic object path points to PolyMesh.";
+ return false;
+ }
+
+ return true;
+}
+
+DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm,
+ const ISampleSelector &sample_sel,
+ int read_flag,
+ const char **err_str)
{
- ISampleSelector sample_sel(time);
const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel);
const P3fArraySamplePtr &positions = sample.getPositions();
@@ -1080,7 +1109,7 @@ DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time,
}
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
- config.time = time;
+ config.time = sample_sel.getRequestedTime();
bool do_normals = false;
read_mesh_sample(&settings, m_schema, sample_sel, config, do_normals);
@@ -1227,7 +1256,24 @@ bool AbcSubDReader::valid() const
return m_schema.valid();
}
-void AbcSubDReader::readObjectData(Main *bmain, float time)
+bool AbcSubDReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const
+{
+ if (!Alembic::AbcGeom::ISubD::matches(alembic_header)) {
+ *err_str = "Object type mismatch, Alembic object path pointed to SubD when importing, but not any more.";
+ return false;
+ }
+
+ if (ob->type != OB_MESH) {
+ *err_str = "Object type mismatch, Alembic object path points to SubD.";
+ return false;
+ }
+
+ return true;
+}
+
+void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
{
Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
@@ -1235,7 +1281,7 @@ void AbcSubDReader::readObjectData(Main *bmain, float time)
m_object->data = mesh;
DerivedMesh *dm = CDDM_from_mesh(mesh);
- DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL, NULL);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, MOD_MESHSEQ_READ_ALL, NULL);
if (ndm != dm) {
dm->release(dm);
@@ -1243,7 +1289,6 @@ void AbcSubDReader::readObjectData(Main *bmain, float time)
DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
- const ISampleSelector sample_sel(time);
const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
Int32ArraySamplePtr indices = sample.getCreaseIndices();
Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses();
@@ -1274,9 +1319,11 @@ void AbcSubDReader::readObjectData(Main *bmain, float time)
}
}
-DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str)
+DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm,
+ const ISampleSelector &sample_sel,
+ int read_flag,
+ const char **err_str)
{
- ISampleSelector sample_sel(time);
const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
const P3fArraySamplePtr &positions = sample.getPositions();
@@ -1316,7 +1363,7 @@ DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time,
/* Only read point data when streaming meshes, unless we need to create new ones. */
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
- config.time = time;
+ config.time = sample_sel.getRequestedTime();
read_subd_sample(&settings, m_schema, sample_sel, config);
if (new_dm) {
diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h
index 64a3109232c..6bf1dde3d1d 100644
--- a/source/blender/alembic/intern/abc_mesh.h
+++ b/source/blender/alembic/intern/abc_mesh.h
@@ -99,10 +99,15 @@ public:
AbcMeshReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
bool valid() const;
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
- void readObjectData(Main *bmain, float time);
-
- DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm,
+ const Alembic::Abc::ISampleSelector &sample_sel,
+ int read_flag,
+ const char **err_str);
private:
void readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
@@ -120,9 +125,14 @@ public:
AbcSubDReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
bool valid() const;
-
- void readObjectData(Main *bmain, float time);
- DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str);
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm,
+ const Alembic::Abc::ISampleSelector &sample_sel,
+ int read_flag,
+ const char **err_str);
};
/* ************************************************************************** */
diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc
index d0b9561f679..eaef06fd6d1 100644
--- a/source/blender/alembic/intern/abc_nurbs.cc
+++ b/source/blender/alembic/intern/abc_nurbs.cc
@@ -239,7 +239,7 @@ static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots)
return true;
}
-void AbcNurbsReader::readObjectData(Main *bmain, float time)
+void AbcNurbsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
{
Curve *cu = static_cast<Curve *>(BKE_curve_add(bmain, "abc_curve", OB_SURF));
cu->actvert = CU_ACT_NONE;
@@ -253,7 +253,6 @@ void AbcNurbsReader::readObjectData(Main *bmain, float time)
nu->resolu = cu->resolu;
nu->resolv = cu->resolv;
- const ISampleSelector sample_sel(time);
const INuPatchSchema &schema = it->first;
const INuPatchSchema::Sample smp = schema.getValue(sample_sel);
diff --git a/source/blender/alembic/intern/abc_nurbs.h b/source/blender/alembic/intern/abc_nurbs.h
index 1b2e7a8391f..abe460a8988 100644
--- a/source/blender/alembic/intern/abc_nurbs.h
+++ b/source/blender/alembic/intern/abc_nurbs.h
@@ -54,7 +54,7 @@ public:
bool valid() const;
- void readObjectData(Main *bmain, float time);
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
private:
void getNurbsPatches(const Alembic::Abc::IObject &obj);
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index a5b8af542fc..04f6da48711 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -91,7 +91,7 @@ Imath::Box3d AbcObjectWriter::bounds()
if (!bb) {
if (this->m_object->type != OB_CAMERA) {
- std::cerr << "Boundbox is null!\n";
+ ABC_LOG(m_settings.logger) << "Bounding box is null!\n";
}
return Imath::Box3d();
@@ -127,6 +127,7 @@ AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings
, m_min_time(std::numeric_limits<chrono_t>::max())
, m_max_time(std::numeric_limits<chrono_t>::min())
, m_refcount(0)
+ , parent_reader(NULL)
{
m_name = object.getFullName();
std::vector<std::string> parts;
@@ -214,7 +215,15 @@ Imath::M44d get_matrix(const IXformSchema &schema, const float time)
return s0.getMatrix();
}
-void AbcObjectReader::readObjectMatrix(const float time)
+DerivedMesh *AbcObjectReader::read_derivedmesh(DerivedMesh *dm,
+ const Alembic::Abc::ISampleSelector &UNUSED(sample_sel),
+ int UNUSED(read_flag),
+ const char **UNUSED(err_str))
+{
+ return dm;
+}
+
+void AbcObjectReader::setupObjectTransform(const float time)
{
bool is_constant = false;
@@ -236,49 +245,88 @@ void AbcObjectReader::readObjectMatrix(const float time)
}
}
-void AbcObjectReader::read_matrix(float mat[4][4], const float time, const float scale, bool &is_constant)
+Alembic::AbcGeom::IXform AbcObjectReader::xform()
{
- IXform ixform;
- bool has_alembic_parent = false;
-
/* Check that we have an empty object (locator, bone head/tail...). */
if (IXform::matches(m_iobject.getMetaData())) {
- ixform = IXform(m_iobject, Alembic::AbcGeom::kWrapExisting);
-
- /* See comment below. */
- has_alembic_parent = m_iobject.getParent().getParent().valid();
+ return IXform(m_iobject, Alembic::AbcGeom::kWrapExisting);
}
- /* Check that we have an object with actual data. */
- else if (IXform::matches(m_iobject.getParent().getMetaData())) {
- ixform = IXform(m_iobject.getParent(), Alembic::AbcGeom::kWrapExisting);
-
- /* This is a bit hackish, but we need to make sure that extra
- * transformations added to the matrix (rotation/scale) are only applied
- * to root objects. The way objects and their hierarchy are created will
- * need to be revisited at some point but for now this seems to do the
- * trick.
- *
- * Explanation of the trick:
- * The first getParent() will return this object's transformation matrix.
- * The second getParent() will get the parent of the transform, but this
- * might be the archive root ('/') which is valid, so we go passed it to
- * make sure that there is no parent.
- */
- has_alembic_parent = m_iobject.getParent().getParent().getParent().valid();
+
+ /* Check that we have an object with actual data, in which case the
+ * parent Alembic object should contain the transform. */
+ IObject abc_parent = m_iobject.getParent();
+
+ /* The archive's top object can be recognised by not having a parent. */
+ if (abc_parent.getParent()
+ && IXform::matches(abc_parent.getMetaData())) {
+ return IXform(abc_parent, Alembic::AbcGeom::kWrapExisting);
}
+
/* Should not happen. */
- else {
+ std::cerr << "AbcObjectReader::xform(): "
+ << "unable to find IXform for Alembic object '"
+ << m_iobject.getFullName() << "'\n";
+ BLI_assert(false);
+
+ return IXform();
+}
+
+void AbcObjectReader::read_matrix(float r_mat[4][4], const float time,
+ const float scale, bool &is_constant)
+{
+ IXform ixform = xform();
+ if (!ixform) {
return;
}
- const IXformSchema &schema(ixform.getSchema());
-
+ const IXformSchema & schema(ixform.getSchema());
if (!schema.valid()) {
+ std::cerr << "Alembic object " << ixform.getFullName()
+ << " has an invalid schema." << std::endl;
return;
}
+ bool has_alembic_parent;
+ IObject ixform_parent = ixform.getParent();
+ if (!ixform_parent.getParent()) {
+ /* The archive top object certainly is not a transform itself, so handle
+ * it as "no parent". */
+ has_alembic_parent = false;
+ }
+ else {
+ has_alembic_parent = ixform_parent && schema.getInheritsXforms();
+
+ if (has_alembic_parent && m_object->parent == NULL) {
+ /* TODO Sybren: This happened in some files. I think I solved it,
+ * but I'll leave this check in here anyway until we've tested it
+ * more thoroughly. Better than crashing on a null parent anyway. */
+ std::cerr << "Alembic object " << m_iobject.getFullName()
+ << " with transform " << ixform.getFullName()
+ << " has an Alembic parent but no parent Blender object."
+ << std::endl;
+ has_alembic_parent = false;
+ }
+ }
+
const Imath::M44d matrix = get_matrix(schema, time);
- convert_matrix(matrix, m_object, mat, scale, has_alembic_parent);
+ convert_matrix(matrix, m_object, r_mat);
+
+ if (has_alembic_parent) {
+ /* In this case, the matrix in Alembic is in local coordinates, so
+ * convert to world matrix. To prevent us from reading and accumulating
+ * all parent matrices in the Alembic file, we assume that the Blender
+ * parent object is already updated for the current timekey, and use its
+ * world matrix. */
+ BLI_assert(m_object->parent);
+ mul_m4_m4m4(r_mat, m_object->parent->obmat, r_mat);
+ }
+ else {
+ /* Only apply scaling to root objects, parenting will propagate it. */
+ float scale_mat[4][4];
+ scale_m4_fl(scale_mat, scale);
+ scale_mat[3][3] = scale; /* scale translations too */
+ mul_m4_m4m4(r_mat, r_mat, scale_mat);
+ }
is_constant = schema.isConstant();
}
@@ -322,4 +370,5 @@ void AbcObjectReader::incref()
void AbcObjectReader::decref()
{
--m_refcount;
+ BLI_assert(m_refcount >= 0);
}
diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h
index 0f733e67d3f..1462f93a422 100644
--- a/source/blender/alembic/intern/abc_object.h
+++ b/source/blender/alembic/intern/abc_object.h
@@ -117,15 +117,7 @@ struct ImportSettings {
template <typename Schema>
static bool has_animations(Schema &schema, ImportSettings *settings)
{
- if (settings->is_sequence) {
- return true;
- }
-
- if (!schema.isConstant()) {
- return true;
- }
-
- return false;
+ return settings->is_sequence || !schema.isConstant();
}
/* ************************************************************************** */
@@ -152,28 +144,44 @@ protected:
int m_refcount;
public:
+ AbcObjectReader *parent_reader;
+
+public:
explicit AbcObjectReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
virtual ~AbcObjectReader();
const Alembic::Abc::IObject &iobject() const;
+ typedef std::vector<AbcObjectReader *> ptr_vector;
+
+ /**
+ * Returns the transform of this object. This can be the Alembic object
+ * itself (in case of an Empty) or it can be the parent Alembic object.
+ */
+ virtual Alembic::AbcGeom::IXform xform();
+
Object *object() const;
void object(Object *ob);
+ const std::string & name() const { return m_name; }
+ const std::string & object_name() const { return m_object_name; }
+ const std::string & data_name() const { return m_data_name; }
+
virtual bool valid() const = 0;
+ virtual bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const = 0;
- virtual void readObjectData(Main *bmain, float time) = 0;
+ virtual void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) = 0;
- virtual DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str)
- {
- (void)time;
- (void)read_flag;
- (void)err_str;
- return dm;
- }
+ virtual DerivedMesh *read_derivedmesh(DerivedMesh *dm,
+ const Alembic::Abc::ISampleSelector &sample_sel,
+ int read_flag,
+ const char **err_str);
- void readObjectMatrix(const float time);
+ /** Reads the object matrix and sets up an object transform if animated. */
+ void setupObjectTransform(const float time);
void addCacheModifier();
@@ -184,7 +192,8 @@ public:
void incref();
void decref();
- void read_matrix(float mat[4][4], const float time, const float scale, bool &is_constant);
+ void read_matrix(float r_mat[4][4], const float time,
+ const float scale, bool &is_constant);
};
Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time);
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc
index fc84759b1d9..80567cd6bf0 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_points.cc
@@ -151,12 +151,29 @@ bool AbcPointsReader::valid() const
return m_schema.valid();
}
-void AbcPointsReader::readObjectData(Main *bmain, float time)
+bool AbcPointsReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const
+{
+ if (!Alembic::AbcGeom::IPoints::matches(alembic_header)) {
+ *err_str = "Object type mismatch, Alembic object path pointed to Points when importing, but not any more.";
+ return false;
+ }
+
+ if (ob->type != OB_MESH) {
+ *err_str = "Object type mismatch, Alembic object path points to Points.";
+ return false;
+ }
+
+ return true;
+}
+
+void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
{
Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
DerivedMesh *dm = CDDM_from_mesh(mesh);
- DerivedMesh *ndm = this->read_derivedmesh(dm, time, 0, NULL);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, 0, NULL);
if (ndm != dm) {
dm->release(dm);
@@ -178,8 +195,7 @@ void AbcPointsReader::readObjectData(Main *bmain, float time)
void read_points_sample(const IPointsSchema &schema,
const ISampleSelector &selector,
- CDStreamConfig &config,
- float time)
+ CDStreamConfig &config)
{
Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
@@ -189,7 +205,7 @@ void read_points_sample(const IPointsSchema &schema,
N3fArraySamplePtr vnormals;
if (has_property(prop, "N")) {
- const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(time);
+ const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(selector.getRequestedTime());
const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", itime);
if (normals_prop) {
@@ -200,9 +216,11 @@ void read_points_sample(const IPointsSchema &schema,
read_mverts(config.mvert, positions, vnormals);
}
-DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char ** /*err_str*/)
+DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm,
+ const ISampleSelector &sample_sel,
+ int /*read_flag*/,
+ const char ** /*err_str*/)
{
- ISampleSelector sample_sel(time);
const IPointsSchema::Sample sample = m_schema.getValue(sample_sel);
const P3fArraySamplePtr &positions = sample.getPositions();
@@ -214,7 +232,7 @@ DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time
}
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
- read_points_sample(m_schema, sample_sel, config, time);
+ read_points_sample(m_schema, sample_sel, config);
return new_dm ? new_dm : dm;
}
diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h
index cb68dbca4d5..369a802d763 100644
--- a/source/blender/alembic/intern/abc_points.h
+++ b/source/blender/alembic/intern/abc_points.h
@@ -58,15 +58,20 @@ public:
AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
bool valid() const;
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
- void readObjectData(Main *bmain, float time);
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
- DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm,
+ const Alembic::Abc::ISampleSelector &sample_sel,
+ int read_flag,
+ const char **err_str);
};
void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
const Alembic::AbcGeom::ISampleSelector &selector,
- CDStreamConfig &config,
- float time);
+ CDStreamConfig &config);
#endif /* __ABC_POINTS_H__ */
diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc
index 2c6ef09326c..5392387663f 100644
--- a/source/blender/alembic/intern/abc_transform.cc
+++ b/source/blender/alembic/intern/abc_transform.cc
@@ -36,6 +36,7 @@ extern "C" {
using Alembic::AbcGeom::OObject;
using Alembic::AbcGeom::OXform;
+using Alembic::Abc::ISampleSelector;
/* ************************************************************************** */
@@ -62,9 +63,9 @@ AbcTransformWriter::AbcTransformWriter(Object *ob,
unsigned int time_sampling,
ExportSettings &settings)
: AbcObjectWriter(NULL, ob, time_sampling, settings, parent)
+ , m_proxy_from(NULL)
{
m_is_animated = hasAnimation(m_object);
- m_parent = NULL;
if (!m_is_animated) {
time_sampling = 0;
@@ -72,6 +73,9 @@ AbcTransformWriter::AbcTransformWriter(Object *ob,
m_xform = OXform(abc_parent, get_id_name(m_object), time_sampling);
m_schema = m_xform.getSchema();
+
+ /* Blender objects can't have a parent without inheriting the transform. */
+ m_inherits_xform = parent != NULL;
}
void AbcTransformWriter::do_write()
@@ -86,27 +90,30 @@ void AbcTransformWriter::do_write()
return;
}
- float mat[4][4];
- create_transform_matrix(m_object, mat);
+ float yup_mat[4][4];
+ create_transform_matrix(m_object, yup_mat,
+ m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD,
+ m_proxy_from);
/* Only apply rotation to root camera, parenting will propagate it. */
- if (m_object->type == OB_CAMERA && !has_parent_camera(m_object)) {
+ if (m_object->type == OB_CAMERA && (!m_inherits_xform || !has_parent_camera(m_object))) {
float rot_mat[4][4];
axis_angle_to_mat4_single(rot_mat, 'X', -M_PI_2);
- mul_m4_m4m4(mat, mat, rot_mat);
+ mul_m4_m4m4(yup_mat, yup_mat, rot_mat);
}
- if (!m_object->parent) {
+ if (!m_object->parent || !m_inherits_xform) {
/* Only apply scaling to root objects, parenting will propagate it. */
float scale_mat[4][4];
scale_m4_fl(scale_mat, m_settings.global_scale);
- mul_m4_m4m4(mat, mat, scale_mat);
- mul_v3_fl(mat[3], m_settings.global_scale);
+ scale_mat[3][3] = m_settings.global_scale; /* also scale translation */
+ mul_m4_m4m4(yup_mat, yup_mat, scale_mat);
+ yup_mat[3][3] /= m_settings.global_scale; /* normalise the homogeneous component */
}
- m_matrix = convert_matrix(mat);
-
+ m_matrix = convert_matrix(yup_mat);
m_sample.setMatrix(m_matrix);
+ m_sample.setInheritsXforms(m_inherits_xform);
m_schema.set(m_sample);
}
@@ -133,6 +140,10 @@ bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const
AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
+ /* Empties have no data. It makes the import of Alembic files easier to
+ * understand when we name the empty after its name in Alembic. */
+ m_object_name = object.getName();
+
Alembic::AbcGeom::IXform xform(object, Alembic::AbcGeom::kWrapExisting);
m_schema = xform.getSchema();
@@ -144,8 +155,26 @@ bool AbcEmptyReader::valid() const
return m_schema.valid();
}
-void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/)
+bool AbcEmptyReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const
+{
+ if (!Alembic::AbcGeom::IXform::matches(alembic_header)) {
+ *err_str = "Object type mismatch, Alembic object path pointed to XForm when importing, but not any more.";
+ return false;
+ }
+
+ if (ob->type != OB_EMPTY) {
+ *err_str = "Object type mismatch, Alembic object path points to XForm.";
+ return false;
+ }
+
+ return true;
+}
+
+void AbcEmptyReader::readObjectData(Main *bmain, const ISampleSelector &UNUSED(sample_sel))
{
- m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_data_name.c_str());
+ m_object = BKE_object_add_only_object(bmain, OB_EMPTY,
+ m_object_name.c_str());
m_object->data = NULL;
}
diff --git a/source/blender/alembic/intern/abc_transform.h b/source/blender/alembic/intern/abc_transform.h
index 6a3aae216f2..753a4247e9f 100644
--- a/source/blender/alembic/intern/abc_transform.h
+++ b/source/blender/alembic/intern/abc_transform.h
@@ -37,8 +37,11 @@ class AbcTransformWriter : public AbcObjectWriter {
Alembic::Abc::M44d m_matrix;
bool m_is_animated;
- Object *m_parent;
bool m_visible;
+ bool m_inherits_xform;
+
+public:
+ Object *m_proxy_from;
public:
AbcTransformWriter(Object *ob,
@@ -49,7 +52,6 @@ public:
Alembic::AbcGeom::OXform &alembicXform() { return m_xform;}
virtual Imath::Box3d bounds();
- void setParent(Object *p) { m_parent = p; }
private:
virtual void do_write();
@@ -66,8 +68,11 @@ public:
AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
bool valid() const;
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
- void readObjectData(Main *bmain, float time);
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
};
#endif /* __ABC_TRANSFORM_H__ */
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index 50fa43a3491..26eb7620fb1 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -41,7 +41,7 @@ extern "C" {
#include "PIL_time.h"
}
-std::string get_id_name(Object *ob)
+std::string get_id_name(const Object * const ob)
{
if (!ob) {
return "";
@@ -50,7 +50,7 @@ std::string get_id_name(Object *ob)
return get_id_name(&ob->id);
}
-std::string get_id_name(ID *id)
+std::string get_id_name(const ID * const id)
{
std::string name(id->name + 2);
std::replace(name.begin(), name.end(), ' ', '_');
@@ -60,7 +60,7 @@ std::string get_id_name(ID *id)
return name;
}
-std::string get_object_dag_path_name(Object *ob, Object *dupli_parent)
+std::string get_object_dag_path_name(const Object * const ob, Object *dupli_parent)
{
std::string name = get_id_name(ob);
@@ -132,15 +132,28 @@ void split(const std::string &s, const char delim, std::vector<std::string> &tok
}
}
-/* Create a rotation matrix for each axis from euler angles.
- * Euler angles are swaped to change coordinate system. */
-static void create_rotation_matrix(
+void create_swapped_rotation_matrix(
float rot_x_mat[3][3], float rot_y_mat[3][3],
- float rot_z_mat[3][3], const float euler[3], const bool to_yup)
+ float rot_z_mat[3][3], const float euler[3],
+ AbcAxisSwapMode mode)
{
const float rx = euler[0];
- const float ry = (to_yup) ? euler[2] : -euler[2];
- const float rz = (to_yup) ? -euler[1] : euler[1];
+ float ry;
+ float rz;
+
+ /* Apply transformation */
+ switch (mode) {
+ case ABC_ZUP_FROM_YUP:
+ ry = -euler[2];
+ rz = euler[1];
+ break;
+ case ABC_YUP_FROM_ZUP:
+ ry = euler[2];
+ rz = -euler[1];
+ break;
+ default:
+ BLI_assert(false);
+ }
unit_m3(rot_x_mat);
unit_m3(rot_y_mat);
@@ -162,58 +175,70 @@ static void create_rotation_matrix(
rot_z_mat[1][1] = cos(rz);
}
-/* Recompute transform matrix of object in new coordinate system
- * (from Y-Up to Z-Up). */
-void create_transform_matrix(float r_mat[4][4])
+/* Convert matrix from Z=up to Y=up or vice versa. Use yup_mat = zup_mat for in-place conversion. */
+void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode)
{
- float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], transform_mat[4][4];
+ float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4];
float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
- float loc[3], scale[3], euler[3];
+ float src_trans[3], dst_scale[3], src_scale[3], euler[3];
- zero_v3(loc);
- zero_v3(scale);
+ zero_v3(src_trans);
+ zero_v3(dst_scale);
+ zero_v3(src_scale);
zero_v3(euler);
- unit_m3(rot);
- unit_m3(rot_mat);
- unit_m4(scale_mat);
- unit_m4(transform_mat);
- unit_m4(invmat);
+ unit_m3(src_rot);
+ unit_m3(dst_rot);
+ unit_m4(dst_scale_mat);
- /* Compute rotation matrix. */
+ /* We assume there is no sheer component and no homogeneous scaling component. */
+ BLI_assert(fabs(src_mat[0][3]) < 2 * FLT_EPSILON);
+ BLI_assert(fabs(src_mat[1][3]) < 2 * FLT_EPSILON);
+ BLI_assert(fabs(src_mat[2][3]) < 2 * FLT_EPSILON);
+ BLI_assert(fabs(src_mat[3][3] - 1.0f) < 2 * FLT_EPSILON);
- /* Extract location, rotation, and scale from matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, r_mat);
+ /* Extract translation, rotation, and scale form matrix. */
+ mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat);
/* Get euler angles from rotation matrix. */
- mat3_to_eulO(euler, ROT_MODE_XYZ, rot);
+ mat3_to_eulO(euler, ROT_MODE_XZY, src_rot);
/* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, false);
+ create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode);
/* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
+ mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat);
+ mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat);
+ mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat);
- /* Add rotation matrix to transformation matrix. */
- copy_m4_m3(transform_mat, rot_mat);
+ mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot);
- /* Add translation to transformation matrix. */
- copy_zup_from_yup(transform_mat[3], loc);
+ /* Start construction of dst_mat from rotation matrix */
+ unit_m4(dst_mat);
+ copy_m4_m3(dst_mat, dst_rot);
- /* Create scale matrix. */
- scale_mat[0][0] = scale[0];
- scale_mat[1][1] = scale[2];
- scale_mat[2][2] = scale[1];
+ /* Apply translation */
+ switch (mode) {
+ case ABC_ZUP_FROM_YUP:
+ copy_zup_from_yup(dst_mat[3], src_trans);
+ break;
+ case ABC_YUP_FROM_ZUP:
+ copy_yup_from_zup(dst_mat[3], src_trans);
+ break;
+ default:
+ BLI_assert(false);
+ }
- /* Add scale to transformation matrix. */
- mul_m4_m4m4(transform_mat, transform_mat, scale_mat);
+ /* Apply scale matrix. Swaps y and z, but does not
+ * negate like translation does. */
+ dst_scale[0] = src_scale[0];
+ dst_scale[1] = src_scale[2];
+ dst_scale[2] = src_scale[1];
- copy_m4_m4(r_mat, transform_mat);
+ size_to_mat4(dst_scale_mat, dst_scale);
+ mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat);
}
-void convert_matrix(const Imath::M44d &xform, Object *ob,
- float r_mat[4][4], float scale, bool has_alembic_parent)
+void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4])
{
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
@@ -227,207 +252,32 @@ void convert_matrix(const Imath::M44d &xform, Object *ob,
mul_m4_m4m4(r_mat, r_mat, cam_to_yup);
}
- create_transform_matrix(r_mat);
-
- if (ob->parent) {
- mul_m4_m4m4(r_mat, ob->parent->obmat, r_mat);
- }
- /* TODO(kevin) */
- else if (!has_alembic_parent) {
- /* Only apply scaling to root objects, parenting will propagate it. */
- float scale_mat[4][4];
- scale_m4_fl(scale_mat, scale);
- mul_m4_m4m4(r_mat, r_mat, scale_mat);
- mul_v3_fl(r_mat[3], scale);
- }
+ copy_m44_axis_swap(r_mat, r_mat, ABC_ZUP_FROM_YUP);
}
-/* Recompute transform matrix of object in new coordinate system (from Z-Up to Y-Up). */
-void create_transform_matrix(Object *obj, float transform_mat[4][4])
+/* Recompute transform matrix of object in new coordinate system
+ * (from Z-Up to Y-Up). */
+void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode,
+ Object *proxy_from)
{
- float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], mat[4][4];
- float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3];
- float loc[3], scale[3], euler[3];
-
- zero_v3(loc);
- zero_v3(scale);
- zero_v3(euler);
- unit_m3(rot);
- unit_m3(rot_mat);
- unit_m4(scale_mat);
- unit_m4(transform_mat);
- unit_m4(invmat);
- unit_m4(mat);
-
- /* get local matrix. */
- if (obj->parent) {
- invert_m4_m4(invmat, obj->parent->obmat);
- mul_m4_m4m4(mat, invmat, obj->obmat);
+ float zup_mat[4][4];
+
+ /* get local or world matrix. */
+ if (mode == ABC_MATRIX_LOCAL && obj->parent) {
+ /* Note that this produces another matrix than the local matrix, due to
+ * constraints and modifiers as well as the obj->parentinv matrix. */
+ invert_m4_m4(obj->parent->imat, obj->parent->obmat);
+ mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat);
}
else {
- copy_m4_m4(mat, obj->obmat);
+ copy_m4_m4(zup_mat, obj->obmat);
}
- /* Compute rotation matrix. */
- switch (obj->rotmode) {
- case ROT_MODE_AXISANGLE:
- {
- /* Get euler angles from axis angle rotation. */
- axis_angle_to_eulO(euler, ROT_MODE_XYZ, obj->rotAxis, obj->rotAngle);
-
- /* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
-
- /* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
-
- /* Extract location and scale from matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- break;
- }
- case ROT_MODE_QUAT:
- {
- float q[4];
- copy_v4_v4(q, obj->quat);
-
- /* Swap axis. */
- q[2] = obj->quat[3];
- q[3] = -obj->quat[2];
-
- /* Compute rotation matrix from quaternion. */
- quat_to_mat3(rot_mat, q);
-
- /* Extract location and scale from matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- break;
- }
- case ROT_MODE_XYZ:
- {
- /* Extract location, rotation, and scale form matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- /* Get euler angles from rotation matrix. */
- mat3_to_eulO(euler, ROT_MODE_XYZ, rot);
-
- /* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
-
- /* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
-
- break;
- }
- case ROT_MODE_XZY:
- {
- /* Extract location, rotation, and scale form matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- /* Get euler angles from rotation matrix. */
- mat3_to_eulO(euler, ROT_MODE_XZY, rot);
-
- /* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
-
- /* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
-
- break;
- }
- case ROT_MODE_YXZ:
- {
- /* Extract location, rotation, and scale form matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- /* Get euler angles from rotation matrix. */
- mat3_to_eulO(euler, ROT_MODE_YXZ, rot);
-
- /* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
-
- /* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
-
- break;
- }
- case ROT_MODE_YZX:
- {
- /* Extract location, rotation, and scale form matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- /* Get euler angles from rotation matrix. */
- mat3_to_eulO(euler, ROT_MODE_YZX, rot);
-
- /* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
-
- /* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
-
- break;
- }
- case ROT_MODE_ZXY:
- {
- /* Extract location, rotation, and scale form matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- /* Get euler angles from rotation matrix. */
- mat3_to_eulO(euler, ROT_MODE_ZXY, rot);
-
- /* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
-
- /* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
-
- break;
- }
- case ROT_MODE_ZYX:
- {
- /* Extract location, rotation, and scale form matrix. */
- mat4_to_loc_rot_size(loc, rot, scale, mat);
-
- /* Get euler angles from rotation matrix. */
- mat3_to_eulO(euler, ROT_MODE_ZYX, rot);
-
- /* Create X, Y, Z rotation matrices from euler angles. */
- create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true);
-
- /* Concatenate rotation matrices. */
- mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat);
- mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat);
-
- break;
- }
+ if (proxy_from) {
+ mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat);
}
- /* Add rotation matrix to transformation matrix. */
- copy_m4_m3(transform_mat, rot_mat);
-
- /* Add translation to transformation matrix. */
- copy_yup_from_zup(transform_mat[3], loc);
-
- /* Create scale matrix. */
- scale_mat[0][0] = scale[0];
- scale_mat[1][1] = scale[2];
- scale_mat[2][2] = scale[1];
-
- /* Add scale to transformation matrix. */
- mul_m4_m4m4(transform_mat, transform_mat, scale_mat);
+ copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
}
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
@@ -520,7 +370,10 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe
reader = new AbcCurveReader(object, settings);
}
else {
- assert(false);
+ std::cerr << "Alembic: unknown how to handle objects of schema "
+ << md.get("schemaObjTitle")
+ << ", skipping object "
+ << object.getFullName() << std::endl;
}
return reader;
@@ -537,3 +390,32 @@ ScopeTimer::~ScopeTimer()
{
fprintf(stderr, "%s: %fs\n", m_message, PIL_check_seconds_timer() - m_start);
}
+
+/* ********************** */
+
+bool SimpleLogger::empty()
+{
+ return ((size_t)m_stream.tellp()) == 0ul;
+}
+
+std::string SimpleLogger::str() const
+{
+ return m_stream.str();
+}
+
+void SimpleLogger::clear()
+{
+ m_stream.clear();
+ m_stream.str("");
+}
+
+std::ostringstream &SimpleLogger::stream()
+{
+ return m_stream;
+}
+
+std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger)
+{
+ os << logger.str();
+ return os;
+}
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 85ba4d5c9c7..2526958111a 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -32,6 +32,11 @@
# define ABC_INLINE static inline
#endif
+/**
+ * \brief The CacheReader struct is only used for anonymous pointers,
+ * to interface between C and C++ code. This library only creates
+ * pointers to AbcObjectReader (or subclasses thereof).
+ */
struct CacheReader {
int unused;
};
@@ -44,16 +49,21 @@ struct ImportSettings;
struct ID;
struct Object;
-std::string get_id_name(ID *id);
-std::string get_id_name(Object *ob);
-std::string get_object_dag_path_name(Object *ob, Object *dupli_parent);
+std::string get_id_name(const ID * const id);
+std::string get_id_name(const Object * const ob);
+std::string get_object_dag_path_name(const Object * const ob, Object *dupli_parent);
bool object_selected(Object *ob);
bool parent_selected(Object *ob);
Imath::M44d convert_matrix(float mat[4][4]);
-void create_transform_matrix(float r_mat[4][4]);
-void create_transform_matrix(Object *obj, float transform_mat[4][4]);
+
+typedef enum {
+ ABC_MATRIX_WORLD = 1,
+ ABC_MATRIX_LOCAL = 2,
+} AbcMatrixMode;
+void create_transform_matrix(Object *obj, float r_transform_mat[4][4],
+ AbcMatrixMode mode, Object *proxy_from);
void split(const std::string &s, const char delim, std::vector<std::string> &tokens);
@@ -64,8 +74,7 @@ bool begins_with(const TContainer &input, const TContainer &match)
&& std::equal(match.begin(), match.end(), input.begin());
}
-void convert_matrix(const Imath::M44d &xform, Object *ob,
- float r_mat[4][4], float scale, bool has_alembic_parent = false);
+void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4]);
template <typename Schema>
void get_min_max_time_ex(const Schema &schema, chrono_t &min, chrono_t &max)
@@ -118,34 +127,54 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe
ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
{
+ const float old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
- zup[2] = yup[1];
+ zup[2] = old_yup1;
}
ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
{
+ const short old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
zup[1] = -yup[2];
- zup[2] = yup[1];
+ zup[2] = old_yup1;
}
/* Copy from Z-up to Y-up. */
ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
{
+ const float old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
- yup[2] = -zup[1];
+ yup[2] = -old_zup1;
}
ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
{
+ const short old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
yup[1] = zup[2];
- yup[2] = -zup[1];
+ yup[2] = -old_zup1;
}
+/* Names are given in (dst, src) order, just like
+ * the parameters of copy_m44_axis_swap() */
+typedef enum {
+ ABC_ZUP_FROM_YUP = 1,
+ ABC_YUP_FROM_ZUP = 2,
+} AbcAxisSwapMode;
+
+/* Create a rotation matrix for each axis from euler angles.
+ * Euler angles are swaped to change coordinate system. */
+void create_swapped_rotation_matrix(
+ float rot_x_mat[3][3], float rot_y_mat[3][3],
+ float rot_z_mat[3][3], const float euler[3],
+ AbcAxisSwapMode mode);
+
+void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode);
+
/* *************************** */
#undef ABC_DEBUG_TIME
@@ -165,4 +194,48 @@ public:
# define SCOPE_TIMER(message)
#endif
+/* *************************** */
+
+/**
+ * Utility class whose purpose is to more easily log related informations. An
+ * instance of the SimpleLogger can be created in any context, and will hold a
+ * copy of all the strings passed to its output stream.
+ *
+ * Different instances of the class may be accessed from different threads,
+ * although accessing the same instance from different threads will lead to race
+ * conditions.
+ */
+class SimpleLogger {
+ std::ostringstream m_stream;
+
+public:
+ /**
+ * Check whether or not the SimpleLogger's stream is empty.
+ */
+ bool empty();
+
+ /**
+ * Return a copy of the string contained in the SimpleLogger's stream.
+ */
+ std::string str() const;
+
+ /**
+ * Remove the bits set on the SimpleLogger's stream and clear its string.
+ */
+ void clear();
+
+ /**
+ * Return a reference to the SimpleLogger's stream, in order to e.g. push
+ * content into it.
+ */
+ std::ostringstream &stream();
+};
+
+#define ABC_LOG(logger) logger.stream()
+
+/**
+ * Pass the content of the logger's stream to the specified std::ostream.
+ */
+std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger);
+
#endif /* __ABC_UTIL_H__ */
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index dc5146a26e0..be454050098 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -21,6 +21,7 @@
*/
#include "../ABC_alembic.h"
+#include <boost/foreach.hpp>
#include <Alembic/AbcMaterial/IMaterial.h>
@@ -120,91 +121,62 @@ ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveReader *archive)
/* NOTE: this function is similar to visit_objects below, need to keep them in
* sync. */
-static void gather_objects_paths(const IObject &object, ListBase *object_paths)
+static bool gather_objects_paths(const IObject &object, ListBase *object_paths)
{
if (!object.valid()) {
- return;
+ return false;
}
- for (int i = 0; i < object.getNumChildren(); ++i) {
- IObject child = object.getChild(i);
- if (!child.valid()) {
- continue;
- }
+ size_t children_claiming_this_object = 0;
+ size_t num_children = object.getNumChildren();
- bool get_path = false;
+ for (size_t i = 0; i < num_children; ++i) {
+ bool child_claims_this_object = gather_objects_paths(object.getChild(i), object_paths);
+ children_claiming_this_object += child_claims_this_object ? 1 : 0;
+ }
- const MetaData &md = child.getMetaData();
+ const MetaData &md = object.getMetaData();
+ bool get_path = false;
+ bool parent_is_part_of_this_object = false;
- if (IXform::matches(md)) {
- /* Check whether or not this object is a Maya locator, which is
- * similar to empties used as parent object in Blender. */
- if (has_property(child.getProperties(), "locator")) {
- get_path = true;
- }
- else {
- /* Avoid creating an empty object if the child of this transform
- * is not a transform (that is an empty). */
- if (child.getNumChildren() == 1) {
- if (IXform::matches(child.getChild(0).getMetaData())) {
- get_path = true;
- }
-#if 0
- else {
- std::cerr << "Skipping " << child.getFullName() << '\n';
- }
-#endif
- }
- else {
- get_path = true;
- }
- }
- }
- else if (IPolyMesh::matches(md)) {
- get_path = true;
- }
- else if (ISubD::matches(md)) {
- get_path = true;
- }
- else if (INuPatch::matches(md)) {
-#ifdef USE_NURBS
- get_path = true;
-#endif
- }
- else if (ICamera::matches(md)) {
- get_path = true;
- }
- else if (IPoints::matches(md)) {
- get_path = true;
- }
- else if (IMaterial::matches(md)) {
- /* Pass for now. */
- }
- else if (ILight::matches(md)) {
- /* Pass for now. */
- }
- else if (IFaceSet::matches(md)) {
- /* Pass, those are handled in the mesh reader. */
- }
- else if (ICurves::matches(md)) {
+ if (!object.getParent()) {
+ /* The root itself is not an object we should import. */
+ }
+ else if (IXform::matches(md)) {
+ if (has_property(object.getProperties(), "locator")) {
get_path = true;
}
else {
- assert(false);
+ get_path = children_claiming_this_object == 0;
}
- if (get_path) {
- AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(
- MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath"));
-
- BLI_strncpy(abc_path->path, child.getFullName().c_str(), PATH_MAX);
+ /* Transforms are never "data" for their parent. */
+ parent_is_part_of_this_object = false;
+ }
+ else {
+ /* These types are "data" for their parent. */
+ get_path =
+ IPolyMesh::matches(md) ||
+ ISubD::matches(md) ||
+#ifdef USE_NURBS
+ INuPatch::matches(md) ||
+#endif
+ ICamera::matches(md) ||
+ IPoints::matches(md) ||
+ ICurves::matches(md);
+ parent_is_part_of_this_object = get_path;
+ }
- BLI_addtail(object_paths, abc_path);
- }
+ if (get_path) {
+ void *abc_path_void = MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath");
+ AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(abc_path_void);
- gather_objects_paths(child, object_paths);
+ BLI_strncpy(abc_path->path, object.getFullName().c_str(), sizeof(abc_path->path));
+ BLI_addtail(object_paths, abc_path);
}
+
+ return parent_is_part_of_this_object;
}
AbcArchiveHandle *ABC_create_handle(const char *filename, ListBase *object_paths)
@@ -266,6 +238,7 @@ struct ExportJobData {
float *progress;
bool was_canceled;
+ bool export_ok;
};
static void export_startjob(void *customdata, short *stop, short *do_update, float *progress)
@@ -299,12 +272,14 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain,
scene, scene->lay);
}
+
+ data->export_ok = !data->was_canceled;
}
catch (const std::exception &e) {
- std::cerr << "Abc Export error: " << e.what() << '\n';
+ ABC_LOG(data->settings.logger) << "Abc Export error: " << e.what() << '\n';
}
catch (...) {
- std::cerr << "Abc Export error\n";
+ ABC_LOG(data->settings.logger) << "Abc Export: unknown error...\n";
}
}
@@ -316,26 +291,49 @@ static void export_endjob(void *customdata)
BLI_delete(data->filename, false, false);
}
+ if (!data->settings.logger.empty()) {
+ std::cerr << data->settings.logger;
+ WM_report(RPT_ERROR, "Errors occured during the export, look in the console to know more...");
+ }
+
G.is_rendering = false;
BKE_spacedata_draw_locks(false);
}
-void ABC_export(
+bool ABC_export(
Scene *scene,
bContext *C,
const char *filepath,
- const struct AlembicExportParams *params)
+ const struct AlembicExportParams *params,
+ bool as_background_job)
{
ExportJobData *job = static_cast<ExportJobData *>(MEM_mallocN(sizeof(ExportJobData), "ExportJobData"));
job->scene = scene;
job->bmain = CTX_data_main(C);
+ job->export_ok = false;
BLI_strncpy(job->filename, filepath, 1024);
+ /* Alright, alright, alright....
+ *
+ * ExportJobData contains an ExportSettings containing a SimpleLogger.
+ *
+ * Since ExportJobData is a C-style struct dynamically allocated with
+ * MEM_mallocN (see above), its construtor is never called, therefore the
+ * ExportSettings constructor is not called which implies that the
+ * SimpleLogger one is not called either. SimpleLogger in turn does not call
+ * the constructor of its data members which ultimately means that its
+ * std::ostringstream member has a NULL pointer. To be able to properly use
+ * the stream's operator<<, the pointer needs to be set, therefore we have
+ * to properly construct everything. And this is done using the placement
+ * new operator as here below. It seems hackish, but I'm too lazy to
+ * do bigger refactor and maybe there is a better way which does not involve
+ * hardcore refactoring. */
+ new (&job->settings) ExportSettings();
job->settings.scene = job->scene;
job->settings.frame_start = params->frame_start;
job->settings.frame_end = params->frame_end;
- job->settings.frame_step_xform = params->frame_step_xform;
- job->settings.frame_step_shape = params->frame_step_shape;
+ job->settings.frame_samples_xform = params->frame_samples_xform;
+ job->settings.frame_samples_shape = params->frame_samples_shape;
job->settings.shutter_open = params->shutter_open;
job->settings.shutter_close = params->shutter_close;
job->settings.selected_only = params->selected_only;
@@ -343,6 +341,8 @@ void ABC_export(
job->settings.export_normals = params->normals;
job->settings.export_uvs = params->uvs;
job->settings.export_vcols = params->vcolors;
+ job->settings.export_hair = params->export_hair;
+ job->settings.export_particles = params->export_particles;
job->settings.apply_subdiv = params->apply_subdiv;
job->settings.flatten_hierarchy = params->flatten_hierarchy;
job->settings.visible_layers_only = params->visible_layers_only;
@@ -359,136 +359,248 @@ void ABC_export(
std::swap(job->settings.frame_start, job->settings.frame_end);
}
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
- CTX_wm_window(C),
- job->scene,
- "Alembic Export",
- WM_JOB_PROGRESS,
- WM_JOB_TYPE_ALEMBIC);
+ bool export_ok = false;
+ if (as_background_job) {
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ job->scene,
+ "Alembic Export",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_ALEMBIC);
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, job, MEM_freeN);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
+ WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+ else {
+ /* Fake a job context, so that we don't need NULL pointer checks while exporting. */
+ short stop = 0, do_update = 0;
+ float progress = 0.f;
+
+ export_startjob(job, &stop, &do_update, &progress);
+ export_endjob(job);
+ export_ok = job->export_ok;
- /* setup job */
- WM_jobs_customdata_set(wm_job, job, MEM_freeN);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
- WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob);
+ MEM_freeN(job);
+ }
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ return export_ok;
}
/* ********************** Import file ********************** */
-static void visit_object(const IObject &object,
- std::vector<AbcObjectReader *> &readers,
- GHash *parent_map,
- ImportSettings &settings)
+/**
+ * Generates an AbcObjectReader for this Alembic object and its children.
+ *
+ * \param object The Alembic IObject to visit.
+ * \param readers The created AbcObjectReader * will be appended to this vector.
+ * \param settings Import settings, not used directly but passed to the
+ * AbcObjectReader subclass constructors.
+ * \param r_assign_as_parent Return parameter, contains a list of reader
+ * pointers, whose parent pointer should still be set.
+ * This is filled when this call to visit_object() didn't create
+ * a reader that should be the parent.
+ * \return A pair of boolean and reader pointer. The boolean indicates whether
+ * this IObject claims its parent as part of the same object
+ * (for example an IPolyMesh object would claim its parent, as the mesh
+ * is interpreted as the object's data, and the parent IXform as its
+ * Blender object). The pointer is the AbcObjectReader that represents
+ * the IObject parameter.
+ *
+ * NOTE: this function is similar to gather_object_paths above, need to keep
+ * them in sync. */
+static std::pair<bool, AbcObjectReader *> visit_object(
+ const IObject &object,
+ AbcObjectReader::ptr_vector &readers,
+ ImportSettings &settings,
+ AbcObjectReader::ptr_vector &r_assign_as_parent)
{
+ const std::string & full_name = object.getFullName();
+
if (!object.valid()) {
- return;
+ std::cerr << " - "
+ << full_name
+ << ": object is invalid, skipping it and all its children.\n";
+ return std::make_pair(false, static_cast<AbcObjectReader *>(NULL));
}
- for (int i = 0; i < object.getNumChildren(); ++i) {
- IObject child = object.getChild(i);
-
- if (!child.valid()) {
- continue;
- }
-
- AbcObjectReader *reader = NULL;
+ /* The interpretation of data by the children determine the role of this
+ * object. This is especially important for Xform objects, as they can be
+ * either part of a Blender object or a Blender object (Empty) themselves.
+ */
+ size_t children_claiming_this_object = 0;
+ size_t num_children = object.getNumChildren();
+ AbcObjectReader::ptr_vector claiming_child_readers;
+ AbcObjectReader::ptr_vector nonclaiming_child_readers;
+ AbcObjectReader::ptr_vector assign_as_parent;
+ for (size_t i = 0; i < num_children; ++i) {
+ const IObject ichild = object.getChild(i);
- const MetaData &md = child.getMetaData();
+ /* TODO: When we only support C++11, use std::tie() instead. */
+ std::pair<bool, AbcObjectReader *> child_result;
+ child_result = visit_object(ichild, readers, settings, assign_as_parent);
- if (IXform::matches(md)) {
- bool create_xform = false;
+ bool child_claims_this_object = child_result.first;
+ AbcObjectReader *child_reader = child_result.second;
- /* Check whether or not this object is a Maya locator, which is
- * similar to empties used as parent object in Blender. */
- if (has_property(child.getProperties(), "locator")) {
- create_xform = true;
+ if (child_reader == NULL) {
+ BLI_assert(!child_claims_this_object);
+ }
+ else {
+ if (child_claims_this_object) {
+ claiming_child_readers.push_back(child_reader);
}
else {
- /* Avoid creating an empty object if the child of this transform
- * is not a transform (that is an empty). */
- if (child.getNumChildren() == 1) {
- if (IXform::matches(child.getChild(0).getMetaData())) {
- create_xform = true;
- }
-#if 0
- else {
- std::cerr << "Skipping " << child.getFullName() << '\n';
- }
-#endif
- }
- else {
- create_xform = true;
- }
+ nonclaiming_child_readers.push_back(child_reader);
}
+ }
- if (create_xform) {
- reader = new AbcEmptyReader(child, settings);
- }
+ children_claiming_this_object += child_claims_this_object ? 1 : 0;
+ }
+ BLI_assert(children_claiming_this_object == claiming_child_readers.size());
+
+ AbcObjectReader *reader = NULL;
+ const MetaData &md = object.getMetaData();
+ bool parent_is_part_of_this_object = false;
+
+ if (!object.getParent()) {
+ /* The root itself is not an object we should import. */
+ }
+ else if (IXform::matches(md)) {
+ bool create_empty;
+
+ /* An xform can either be a Blender Object (if it contains a mesh, for
+ * example), but it can also be an Empty. Its correct translation to
+ * Blender's data model depends on its children. */
+
+ /* Check whether or not this object is a Maya locator, which is
+ * similar to empties used as parent object in Blender. */
+ if (has_property(object.getProperties(), "locator")) {
+ create_empty = true;
}
- else if (IPolyMesh::matches(md)) {
- reader = new AbcMeshReader(child, settings);
+ else {
+ create_empty = claiming_child_readers.empty();
}
- else if (ISubD::matches(md)) {
- reader = new AbcSubDReader(child, settings);
+
+ if (create_empty) {
+ reader = new AbcEmptyReader(object, settings);
}
- else if (INuPatch::matches(md)) {
+ }
+ else if (IPolyMesh::matches(md)) {
+ reader = new AbcMeshReader(object, settings);
+ parent_is_part_of_this_object = true;
+ }
+ else if (ISubD::matches(md)) {
+ reader = new AbcSubDReader(object, settings);
+ parent_is_part_of_this_object = true;
+ }
+ else if (INuPatch::matches(md)) {
#ifdef USE_NURBS
- /* TODO(kevin): importing cyclic NURBS from other software crashes
- * at the moment. This is due to the fact that NURBS in other
- * software have duplicated points which causes buffer overflows in
- * Blender. Need to figure out exactly how these points are
- * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV).
- * Until this is fixed, disabling NURBS reading. */
- reader = new AbcNurbsReader(child, settings);
+ /* TODO(kevin): importing cyclic NURBS from other software crashes
+ * at the moment. This is due to the fact that NURBS in other
+ * software have duplicated points which causes buffer overflows in
+ * Blender. Need to figure out exactly how these points are
+ * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV).
+ * Until this is fixed, disabling NURBS reading. */
+ reader = new AbcNurbsReader(object, settings);
+ parent_is_part_of_this_object = true;
#endif
+ }
+ else if (ICamera::matches(md)) {
+ reader = new AbcCameraReader(object, settings);
+ parent_is_part_of_this_object = true;
+ }
+ else if (IPoints::matches(md)) {
+ reader = new AbcPointsReader(object, settings);
+ parent_is_part_of_this_object = true;
+ }
+ else if (IMaterial::matches(md)) {
+ /* Pass for now. */
+ }
+ else if (ILight::matches(md)) {
+ /* Pass for now. */
+ }
+ else if (IFaceSet::matches(md)) {
+ /* Pass, those are handled in the mesh reader. */
+ }
+ else if (ICurves::matches(md)) {
+ reader = new AbcCurveReader(object, settings);
+ parent_is_part_of_this_object = true;
+ }
+ else {
+ std::cerr << "Alembic object " << full_name
+ << " is of unsupported schema type '"
+ << object.getMetaData().get("schemaObjTitle") << "'"
+ << std::endl;
+ }
+
+ if (reader) {
+ /* We have created a reader, which should imply that this object is
+ * not claimed as part of any child Alembic object. */
+ BLI_assert(claiming_child_readers.empty());
+
+ readers.push_back(reader);
+ reader->incref();
+
+ AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(
+ MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath"));
+ BLI_strncpy(abc_path->path, full_name.c_str(), sizeof(abc_path->path));
+ BLI_addtail(&settings.cache_file->object_paths, abc_path);
+
+ /* We can now assign this reader as parent for our children. */
+ if (nonclaiming_child_readers.size() + assign_as_parent.size() > 0) {
+ /* TODO: When we only support C++11, use for (a: b) instead. */
+ BOOST_FOREACH(AbcObjectReader *child_reader, nonclaiming_child_readers) {
+ child_reader->parent_reader = reader;
+ }
+ BOOST_FOREACH(AbcObjectReader *child_reader, assign_as_parent) {
+ child_reader->parent_reader = reader;
+ }
}
- else if (ICamera::matches(md)) {
- reader = new AbcCameraReader(child, settings);
- }
- else if (IPoints::matches(md)) {
- reader = new AbcPointsReader(child, settings);
- }
- else if (IMaterial::matches(md)) {
- /* Pass for now. */
- }
- else if (ILight::matches(md)) {
- /* Pass for now. */
- }
- else if (IFaceSet::matches(md)) {
- /* Pass, those are handled in the mesh reader. */
- }
- else if (ICurves::matches(md)) {
- reader = new AbcCurveReader(child, settings);
+ }
+ else if (object.getParent()) {
+ if (claiming_child_readers.size() > 0) {
+ /* The first claiming child will serve just fine as parent to
+ * our non-claiming children. Since all claiming children share
+ * the same XForm, it doesn't really matter which one we pick. */
+ AbcObjectReader *claiming_child = claiming_child_readers[0];
+ BOOST_FOREACH(AbcObjectReader *child_reader, nonclaiming_child_readers) {
+ child_reader->parent_reader = claiming_child;
+ }
+ BOOST_FOREACH(AbcObjectReader *child_reader, assign_as_parent) {
+ child_reader->parent_reader = claiming_child;
+ }
+ /* Claiming children should have our parent set as their parent. */
+ BOOST_FOREACH(AbcObjectReader *child_reader, claiming_child_readers) {
+ r_assign_as_parent.push_back(child_reader);
+ }
}
else {
- assert(false);
- }
-
- if (reader) {
- readers.push_back(reader);
- reader->incref();
-
- AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(
- MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath"));
-
- BLI_strncpy(abc_path->path, child.getFullName().c_str(), PATH_MAX);
-
- BLI_addtail(&settings.cache_file->object_paths, abc_path);
-
- /* Cast to `void *` explicitly to avoid compiler errors because it
- * is a `const char *` which the compiler cast to `const void *`
- * instead of the expected `void *`. */
- BLI_ghash_insert(parent_map, (void *)child.getFullName().c_str(), reader);
+ /* This object isn't claimed by any child, and didn't produce
+ * a reader. Odd situation, could be the top Alembic object, or
+ * an unsupported Alembic schema. Delegate to our parent. */
+ BOOST_FOREACH(AbcObjectReader *child_reader, claiming_child_readers) {
+ r_assign_as_parent.push_back(child_reader);
+ }
+ BOOST_FOREACH(AbcObjectReader *child_reader, nonclaiming_child_readers) {
+ r_assign_as_parent.push_back(child_reader);
+ }
+ BOOST_FOREACH(AbcObjectReader *child_reader, assign_as_parent) {
+ r_assign_as_parent.push_back(child_reader);
+ }
}
-
- visit_object(child, readers, parent_map, settings);
}
+
+ return std::make_pair(parent_is_part_of_this_object, reader);
}
enum {
ABC_NO_ERROR = 0,
ABC_ARCHIVE_FAIL,
+ ABC_UNSUPPORTED_HDF5,
};
struct ImportJobData {
@@ -498,7 +610,6 @@ struct ImportJobData {
char filename[1024];
ImportSettings settings;
- GHash *parent_map;
std::vector<AbcObjectReader *> readers;
short *stop;
@@ -507,6 +618,7 @@ struct ImportJobData {
char error_code;
bool was_cancelled;
+ bool import_ok;
};
ABC_INLINE bool is_mesh_and_strands(const IObject &object)
@@ -553,8 +665,12 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
ArchiveReader *archive = new ArchiveReader(data->filename);
if (!archive->valid()) {
- delete archive;
+#ifndef WITH_ALEMBIC_HDF5
+ data->error_code = archive->is_hdf5() ? ABC_UNSUPPORTED_HDF5 : ABC_ARCHIVE_FAIL;
+#else
data->error_code = ABC_ARCHIVE_FAIL;
+#endif
+ delete archive;
return;
}
@@ -575,11 +691,12 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
*data->do_update = true;
*data->progress = 0.05f;
- data->parent_map = BLI_ghash_str_new("alembic parent ghash");
-
/* Parse Alembic Archive. */
+ AbcObjectReader::ptr_vector assign_as_parent;
+ visit_object(archive->getTop(), data->readers, data->settings, assign_as_parent);
- visit_object(archive->getTop(), data->readers, data->parent_map, data->settings);
+ /* There shouldn't be any orphans. */
+ BLI_assert(assign_as_parent.size() == 0);
if (G.is_break) {
data->was_cancelled = true;
@@ -597,19 +714,23 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
chrono_t min_time = std::numeric_limits<chrono_t>::max();
chrono_t max_time = std::numeric_limits<chrono_t>::min();
+ ISampleSelector sample_sel(0.0f);
std::vector<AbcObjectReader *>::iterator iter;
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
AbcObjectReader *reader = *iter;
if (reader->valid()) {
- reader->readObjectData(data->bmain, 0.0f);
- reader->readObjectMatrix(0.0f);
+ reader->readObjectData(data->bmain, sample_sel);
min_time = std::min(min_time, reader->minTime());
max_time = std::max(max_time, reader->maxTime());
}
+ else {
+ std::cerr << "Object " << reader->name() << " in Alembic file "
+ << data->filename << " is invalid.\n";
+ }
- *data->progress = 0.1f + 0.6f * (++i / size);
+ *data->progress = 0.1f + 0.3f * (++i / size);
*data->do_update = true;
if (G.is_break) {
@@ -627,45 +748,31 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
CFRA = SFRA;
}
else if (min_time < max_time) {
- SFRA = static_cast<int>(min_time * FPS);
- EFRA = static_cast<int>(max_time * FPS);
+ SFRA = static_cast<int>(round(min_time * FPS));
+ EFRA = static_cast<int>(round(max_time * FPS));
CFRA = SFRA;
}
}
- /* Setup parentship. */
-
- i = 0;
+ /* Setup parenthood. */
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
const AbcObjectReader *reader = *iter;
- const AbcObjectReader *parent_reader = NULL;
- const IObject &iobject = reader->iobject();
-
- IObject parent = iobject.getParent();
-
- if (!IXform::matches(iobject.getHeader())) {
- /* In the case of an non XForm node, the parent is the transform
- * matrix of the data itself, so we get the its grand parent.
- */
+ const AbcObjectReader *parent_reader = reader->parent_reader;
+ Object *ob = reader->object();
- /* Special case with object only containing a mesh and some strands,
- * we want both objects to be parented to the same object. */
- if (!is_mesh_and_strands(parent)) {
- parent = parent.getParent();
- }
+ if (parent_reader == NULL) {
+ ob->parent = NULL;
}
-
- parent_reader = reinterpret_cast<AbcObjectReader *>(
- BLI_ghash_lookup(data->parent_map, parent.getFullName().c_str()));
-
- if (parent_reader) {
- Object *parent = parent_reader->object();
-
- if (parent != NULL && reader->object() != parent) {
- Object *ob = reader->object();
- ob->parent = parent;
- }
+ else {
+ ob->parent = parent_reader->object();
}
+ }
+
+ /* Setup transformations and constraints. */
+ i = 0;
+ for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
+ AbcObjectReader *reader = *iter;
+ reader->setupObjectTransform(0.0f);
*data->progress = 0.7f + 0.3f * (++i / size);
*data->do_update = true;
@@ -690,23 +797,25 @@ static void import_endjob(void *user_data)
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
Object *ob = (*iter)->object();
- if (ob->data) {
- BKE_libblock_free_us(data->bmain, ob->data);
- ob->data = NULL;
- }
+ /* It's possible that cancellation occured between the creation of
+ * the reader and the creation of the Blender object. */
+ if (ob == NULL) continue;
BKE_libblock_free_us(data->bmain, ob);
}
}
else {
/* Add object to scene. */
+ Base *base;
+
BKE_scene_base_deselect_all(data->scene);
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
Object *ob = (*iter)->object();
ob->lay = data->scene->lay;
- BKE_scene_base_add(data->scene, ob);
+ base = BKE_scene_base_add(data->scene, ob);
+ BKE_scene_base_select(data->scene, base);
DAG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
@@ -723,17 +832,17 @@ static void import_endjob(void *user_data)
}
}
- if (data->parent_map) {
- BLI_ghash_free(data->parent_map, NULL, NULL);
- }
-
switch (data->error_code) {
default:
case ABC_NO_ERROR:
+ data->import_ok = !data->was_cancelled;
break;
case ABC_ARCHIVE_FAIL:
WM_report(RPT_ERROR, "Could not open Alembic archive for reading! See console for detail.");
break;
+ case ABC_UNSUPPORTED_HDF5:
+ WM_report(RPT_ERROR, "Alembic archive in obsolete HDF5 format is not supported.");
+ break;
}
WM_main_add_notifier(NC_SCENE | ND_FRAME, data->scene);
@@ -745,13 +854,16 @@ static void import_freejob(void *user_data)
delete data;
}
-void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence, bool set_frame_range, int sequence_len, int offset, bool validate_meshes)
+bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence,
+ bool set_frame_range, int sequence_len, int offset,
+ bool validate_meshes, bool as_background_job)
{
/* Using new here since MEM_* funcs do not call ctor to properly initialize
* data. */
ImportJobData *job = new ImportJobData();
job->bmain = CTX_data_main(C);
job->scene = CTX_data_scene(C);
+ job->import_ok = false;
BLI_strncpy(job->filename, filepath, 1024);
job->settings.scale = scale;
@@ -760,25 +872,40 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
job->settings.sequence_len = sequence_len;
job->settings.offset = offset;
job->settings.validate_meshes = validate_meshes;
- job->parent_map = NULL;
job->error_code = ABC_NO_ERROR;
job->was_cancelled = false;
G.is_break = false;
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
- CTX_wm_window(C),
- job->scene,
- "Alembic Import",
- WM_JOB_PROGRESS,
- WM_JOB_TYPE_ALEMBIC);
+ bool import_ok = false;
+ if (as_background_job) {
+ wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ job->scene,
+ "Alembic Import",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_ALEMBIC);
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, job, import_freejob);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
+ WM_jobs_callbacks(wm_job, import_startjob, NULL, NULL, import_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+ else {
+ /* Fake a job context, so that we don't need NULL pointer checks while importing. */
+ short stop = 0, do_update = 0;
+ float progress = 0.f;
+
+ import_startjob(job, &stop, &do_update, &progress);
+ import_endjob(job);
+ import_ok = job->import_ok;
- /* setup job */
- WM_jobs_customdata_set(wm_job, job, import_freejob);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
- WM_jobs_callbacks(wm_job, import_startjob, NULL, NULL, import_endjob);
+ import_freejob(job);
+ }
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ return import_ok;
}
/* ************************************************************************** */
@@ -813,42 +940,15 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader,
}
const ObjectHeader &header = iobject.getHeader();
-
- if (IPolyMesh::matches(header)) {
- if (ob->type != OB_MESH) {
- *err_str = "Object type mismatch: object path points to a mesh!";
- return NULL;
- }
-
- return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
- }
- else if (ISubD::matches(header)) {
- if (ob->type != OB_MESH) {
- *err_str = "Object type mismatch: object path points to a subdivision mesh!";
- return NULL;
- }
-
- return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
- }
- else if (IPoints::matches(header)) {
- if (ob->type != OB_MESH) {
- *err_str = "Object type mismatch: object path points to a point cloud (requires a mesh object)!";
- return NULL;
- }
-
- return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
- }
- else if (ICurves::matches(header)) {
- if (ob->type != OB_CURVE) {
- *err_str = "Object type mismatch: object path points to a curve!";
- return NULL;
- }
-
- return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
+ if (!abc_reader->accepts_object_type(header, ob, err_str)) {
+ /* err_str is set by acceptsObjectType() */
+ return NULL;
}
- *err_str = "Unsupported object type: verify object path"; // or poke developer
- return NULL;
+ /* kFloorIndex is used to be compatible with non-interpolating
+ * properties; they use the floor. */
+ ISampleSelector sample_sel(time, ISampleSelector::kFloorIndex);
+ return abc_reader->read_derivedmesh(dm, sample_sel, read_flag, err_str);
}
/* ************************************************************************** */
@@ -863,6 +963,12 @@ void CacheReader_free(CacheReader *reader)
}
}
+void CacheReader_incref(CacheReader *reader)
+{
+ AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
+ abc_reader->incref();
+}
+
CacheReader *CacheReader_open_alembic_object(AbcArchiveHandle *handle, CacheReader *reader, Object *object, const char *object_path)
{
if (object_path[0] == '\0') {
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index aa7d539538b..bbbabfb8ba2 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -135,6 +135,7 @@ void blf_glyph_cache_clear(FontBLF *font)
while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
}
+ font->glyph_cache = NULL;
}
void blf_glyph_cache_free(GlyphCacheBLF *gc)
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 6527ba7f94f..5db0c3c9130 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -58,7 +58,7 @@ extern "C" {
struct bAction *add_empty_action(struct Main *bmain, const char name[]);
/* Allocate a copy of the given Action and all its data */
-struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src);
+struct bAction *BKE_action_copy(struct Main *bmain, const struct bAction *src);
/* Deallocate all of the Action's data, but not the Action itself */
void BKE_action_free(struct bAction *act);
@@ -150,7 +150,7 @@ void BKE_pose_free_data_ex(struct bPose *pose, bool do_id_user);
void BKE_pose_free_data(struct bPose *pose);
void BKE_pose_free(struct bPose *pose);
void BKE_pose_free_ex(struct bPose *pose, bool do_id_user);
-void BKE_pose_copy_data(struct bPose **dst, struct bPose *src, const bool copy_constraints);
+void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints);
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index a67e903877a..420ae4bb12d 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -89,12 +89,6 @@ typedef enum eAnimData_MergeCopy_Modes {
void BKE_animdata_merge_copy(struct ID *dst_id, struct ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers);
-/* Make Local */
-void BKE_animdata_make_local(struct AnimData *adt);
-
-/* Re-Assign ID's */
-void BKE_animdata_relink(struct AnimData *adt);
-
/* ************************************* */
/* KeyingSets API */
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index 077fe2a629c..ac8f861fa56 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -27,11 +27,15 @@
/* note on naming: typical _get() suffix is omitted here,
* since its the main purpose of the API. */
const char *BKE_appdir_folder_default(void);
+const char *BKE_appdir_folder_id_ex(const int folder_id, const char *subfolder, char *path, size_t path_len);
const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder);
const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder);
const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder);
const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check);
+bool BKE_appdir_app_template_any(void);
+bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len);
+
/* Initialize path to program executable */
void BKE_appdir_program_path_init(const char *argv0);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 78d6f6c7cb9..6bfc8c918d6 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -77,7 +77,7 @@ int BKE_armature_bonelist_count(struct ListBase *lb);
void BKE_armature_bonelist_free(struct ListBase *lb);
void BKE_armature_free(struct bArmature *arm);
void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool lib_local);
-struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm);
+struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature *arm);
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
@@ -177,6 +177,7 @@ void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx,
struct bPoseChannel *pchan);
void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index d2d9c763031..d55926ffb1e 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -38,14 +38,22 @@
extern "C" {
#endif
+struct UserDef;
+
void BKE_blender_free(void);
void BKE_blender_globals_init(void);
void BKE_blender_globals_clear(void);
+void BKE_blender_version_string(
+ char *version_str, size_t maxncpy,
+ short version, short subversion, bool v_prefix, bool include_subversion);
-void BKE_blender_userdef_free(void);
+void BKE_blender_userdef_set_data(struct UserDef *userdef);
+void BKE_blender_userdef_free_data(struct UserDef *userdef);
void BKE_blender_userdef_refresh(void);
-
+
+void BKE_blender_userdef_set_app_template(struct UserDef *userdef);
+
/* set this callback when a UI is running */
void BKE_blender_callback_test_break_set(void (*func)(void));
int BKE_blender_test_break(void);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 4f4787f9da5..207631d36bd 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 278
-#define BLENDER_SUBVERSION 4
+#define BLENDER_SUBVERSION 5
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h
index 6767fce3abd..ac58451e412 100644
--- a/source/blender/blenkernel/BKE_blendfile.h
+++ b/source/blender/blenkernel/BKE_blendfile.h
@@ -33,8 +33,7 @@ struct ID;
struct Main;
struct MemFile;
struct ReportList;
-
-int BKE_blendfile_read(struct bContext *C, const char *filepath, struct ReportList *reports);
+struct UserDef;
enum {
BKE_BLENDFILE_READ_FAIL = 0, /* no load */
@@ -42,15 +41,24 @@ enum {
BKE_BLENDFILE_READ_OK_USERPREFS = 2, /* OK, and with new user settings */
};
+int BKE_blendfile_read(
+ struct bContext *C, const char *filepath,
+ struct ReportList *reports, int skip_flag);
bool BKE_blendfile_read_from_memory(
- struct bContext *C, const void *filebuf,
- int filelength, struct ReportList *reports, bool update_defaults);
+ struct bContext *C, const void *filebuf, int filelength,
+ struct ReportList *reports, int skip_flag, bool update_defaults);
bool BKE_blendfile_read_from_memfile(
struct bContext *C, struct MemFile *memfile,
+ struct ReportList *reports, int skip_flag);
+void BKE_blendfile_read_make_empty(struct bContext *C);
+
+struct UserDef *BKE_blendfile_userdef_read(
+ const char *filepath, struct ReportList *reports);
+struct UserDef *BKE_blendfile_userdef_read_from_memory(
+ const void *filebuf, int filelength,
struct ReportList *reports);
-int BKE_blendfile_read_userdef(const char *filepath, struct ReportList *reports);
-int BKE_blendfile_write_userdef(const char *filepath, struct ReportList *reports);
+int BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports);
/* partial blend file writing */
diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h
index 582cd0cef8d..24f19951efe 100644
--- a/source/blender/blenkernel/BKE_boids.h
+++ b/source/blender/blenkernel/BKE_boids.h
@@ -61,6 +61,6 @@ BoidRule *boid_new_rule(int type);
BoidState *boid_new_state(BoidSettings *boids);
BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state);
void boid_free_settings(BoidSettings *boids);
-BoidSettings *boid_copy_settings(BoidSettings *boids);
+BoidSettings *boid_copy_settings(const BoidSettings *boids);
BoidState *boid_get_current_state(BoidSettings *boids);
#endif
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 8bd4bdf89e1..42e4e73f2d5 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -44,7 +44,7 @@ void BKE_brush_system_exit(void);
void BKE_brush_init(struct Brush *brush);
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
-struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush);
+struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush);
void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local);
void BKE_brush_unlink(struct Main *bmain, struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index 0d4ed2083b1..f1e643c4a19 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -47,7 +47,7 @@ void BKE_cachefile_init(struct CacheFile *cache_file);
void BKE_cachefile_free(struct CacheFile *cache_file);
-struct CacheFile *BKE_cachefile_copy(struct Main *bmain, struct CacheFile *cache_file);
+struct CacheFile *BKE_cachefile_copy(struct Main *bmain, const struct CacheFile *cache_file);
void BKE_cachefile_make_local(struct Main *bmain, struct CacheFile *cache_file, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 31a732cf7e5..b2f22aacb28 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -52,7 +52,7 @@ struct GPUFXSettings;
void BKE_camera_init(struct Camera *cam);
void *BKE_camera_add(struct Main *bmain, const char *name);
-struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam);
+struct Camera *BKE_camera_copy(struct Main *bmain, const struct Camera *cam);
void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool lib_local);
void BKE_camera_free(struct Camera *ca);
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 36330242f18..6c517bd02df 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -136,9 +136,6 @@ typedef struct ClothSpring {
float restlen; /* The original length of the spring. */
int type; /* types defined in BKE_cloth.h ("springType") */
int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */
- float dfdx[3][3];
- float dfdv[3][3];
- float f[3];
float stiffness; /* stiffness factor from the vertex groups */
float editrestlen;
@@ -240,9 +237,6 @@ void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
// needed for button_object.c
void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr );
-// needed for cloth.c
-int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type);
-
void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]);
////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 5b4f5910821..f68c4a2757b 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -46,8 +46,8 @@ void curvemapping_set_defaults(struct CurveMapping *cumap, int to
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
void curvemapping_free_data(struct CurveMapping *cumap);
void curvemapping_free(struct CurveMapping *cumap);
-void curvemapping_copy_data(struct CurveMapping *target, struct CurveMapping *cumap);
-struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap);
+void curvemapping_copy_data(struct CurveMapping *target, const struct CurveMapping *cumap);
+struct CurveMapping *curvemapping_copy(const struct CurveMapping *cumap);
void curvemapping_set_black_white_ex(const float black[3], const float white[3], float r_bwmul[3]);
void curvemapping_set_black_white(struct CurveMapping *cumap, const float black[3], const float white[3]);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index e111bd0e16b..0d382c8a49c 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -78,7 +78,7 @@ void BKE_curve_free(struct Curve *cu);
void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
-struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu);
+struct Curve *BKE_curve_copy(struct Main *bmain, const struct Curve *cu);
void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool lib_local);
short BKE_curve_type_get(struct Curve *cu);
void BKE_curve_type_test(struct Object *ob);
@@ -142,7 +142,7 @@ int BKE_nurbList_verts_count(struct ListBase *nurb);
int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb);
void BKE_nurbList_free(struct ListBase *lb);
-void BKE_nurbList_duplicate(struct ListBase *lb1, struct ListBase *lb2);
+void BKE_nurbList_duplicate(struct ListBase *lb1, const struct ListBase *lb2);
void BKE_nurbList_handles_set(struct ListBase *editnurb, const char code);
void BKE_nurbList_handles_recalculate(struct ListBase *editnurb, const bool calc_length, const char flag);
@@ -150,7 +150,7 @@ 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);
+struct Nurb *BKE_nurb_duplicate(const struct Nurb *nu);
struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv);
void BKE_nurb_test2D(struct Nurb *nu);
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index 3ce08a14177..a20c5a4240c 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -44,8 +44,8 @@ struct MLoop;
struct MPoly;
struct bDeformGroup *BKE_defgroup_new(struct Object *ob, const char *name);
-void defgroup_copy_list(struct ListBase *lb1, struct ListBase *lb2);
-struct bDeformGroup *defgroup_duplicate(struct bDeformGroup *ingroup);
+void defgroup_copy_list(struct ListBase *lb1, const struct ListBase *lb2);
+struct bDeformGroup *defgroup_duplicate(const struct bDeformGroup *ingroup);
struct bDeformGroup *defgroup_find_name(struct Object *ob, const char *name);
int *defgroup_flip_map(struct Object *ob, int *flip_map_len, const bool use_default);
int *defgroup_flip_map_single(struct Object *ob, int *flip_map_len, const bool use_default, int defgroup);
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 3a45097efc5..b38f1299763 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -92,7 +92,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt);
/* ---------------------- */
void fcurve_free_driver(struct FCurve *fcu);
-struct ChannelDriver *fcurve_copy_driver(struct ChannelDriver *driver);
+struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list);
@@ -138,7 +138,7 @@ typedef struct FModifierTypeInfo {
/* free any data that is allocated separately (optional) */
void (*free_data)(struct FModifier *fcm);
/* copy any special data that is allocated separately (optional) */
- void (*copy_data)(struct FModifier *fcm, struct FModifier *src);
+ void (*copy_data)(struct FModifier *fcm, const struct FModifier *src);
/* set settings for data that will be used for FCuModifier.data (memory already allocated using MEM_callocN) */
void (*new_data)(void *mdata);
/* verifies that the modifier settings are valid */
@@ -183,14 +183,14 @@ typedef enum eFMI_Requirement_Flags {
} eFMI_Requirement_Flags;
/* Function Prototypes for FModifierTypeInfo's */
-const FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm);
-const FModifierTypeInfo *get_fmodifier_typeinfo(int type);
+const FModifierTypeInfo *fmodifier_get_typeinfo(const struct FModifier *fcm);
+const FModifierTypeInfo *get_fmodifier_typeinfo(const int type);
/* ---------------------- */
struct FModifier *add_fmodifier(ListBase *modifiers, int type);
-struct FModifier *copy_fmodifier(struct FModifier *src);
-void copy_fmodifiers(ListBase *dst, ListBase *src);
+struct FModifier *copy_fmodifier(const struct FModifier *src);
+void copy_fmodifiers(ListBase *dst, const ListBase *src);
bool remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
void free_fmodifiers(ListBase *modifiers);
@@ -216,7 +216,7 @@ int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array, float frame, int
/* -------- Data Management -------- */
void free_fcurve(struct FCurve *fcu);
-struct FCurve *copy_fcurve(struct FCurve *fcu);
+struct FCurve *copy_fcurve(const struct FCurve *fcu);
void free_fcurves(ListBase *list);
void copy_fcurves(ListBase *dst, ListBase *src);
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index 6775639125f..e7ae0f606e7 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -60,8 +60,9 @@ typedef struct EditFont {
struct CharInfo *textbufinfo;
/* array of rectangles & rotation */
- EditFontSelBox *selboxes;
float textcurs[4][2];
+ EditFontSelBox *selboxes;
+ int selboxes_len;
/* positional vars relative to the textbuf, textbufinfo (not utf8 bytes)
* a copy of these is kept in Curve, but use these in editmode */
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 4bb2b950901..830518906ab 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -189,11 +189,6 @@ enum {
# error Either __BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined.
#endif
-/* there is really no good place for this */
-#if defined(FREE_WINDOWS) && ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 6)))
-# error "Mingw requires GCC 4.6 minimum"
-#endif
-
#define L_ENDIAN 1
#define B_ENDIAN 0
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 3378f4acc60..bdd28baf137 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -60,7 +60,7 @@ struct bGPdata *BKE_gpencil_data_addnew(const char name[]);
struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src);
struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src);
-struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, struct bGPdata *gpd, bool internal_copy);
+struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy);
void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 09a069ee36f..684251c9561 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -42,7 +42,7 @@ struct Scene;
void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
-struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
+struct Group *BKE_group_copy(struct Main *bmain, const struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 6944c5ccd28..39e6b145755 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -88,7 +88,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv);
void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size);
/* get the preview from any pointer */
-struct PreviewImage **BKE_previewimg_id_get_p(struct ID *id);
+struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id);
/* free the preview image belonging to the id */
void BKE_previewimg_id_free(struct ID *id);
@@ -97,9 +97,9 @@ void BKE_previewimg_id_free(struct ID *id);
struct PreviewImage *BKE_previewimg_create(void);
/* create a copy of the preview image */
-struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv);
+struct PreviewImage *BKE_previewimg_copy(const struct PreviewImage *prv);
-void BKE_previewimg_id_copy(struct ID *new_id, struct ID *old_id);
+void BKE_previewimg_id_copy(struct ID *new_id, const struct ID *old_id);
/* retrieve existing or create new preview image */
struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id);
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 5b10d7ebc06..ab8728faedb 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -60,8 +60,6 @@ typedef union IDPropertyTemplate {
IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
IDProperty *IDP_CopyIDPArray(const 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) ATTR_NONNULL();
struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -81,8 +79,8 @@ void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) ATTR_N
void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL();
/*-------- ID Type -------*/
-void IDP_LinkID(struct IDProperty *prop, ID *id);
-void IDP_UnlinkID(struct IDProperty *prop);
+
+typedef void(*IDPWalkFunc)(void *userData, IDProperty *idp);
/*-------- Group Functions -------*/
@@ -112,11 +110,12 @@ bool IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) AT
struct IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void IDP_FreeProperty_ex(struct IDProperty *prop, const bool do_id_user);
void IDP_FreeProperty(struct IDProperty *prop);
void IDP_ClearProperty(IDProperty *prop);
-void IDP_UnlinkProperty(struct IDProperty *prop);
+void IDP_RelinkProperty(struct IDProperty *prop);
#define IDP_Int(prop) ((prop)->data.val)
#define IDP_Array(prop) ((prop)->data.pointer)
@@ -134,11 +133,15 @@ void IDP_UnlinkProperty(struct IDProperty *prop);
# define IDP_IDPArray(prop) _Generic((prop), \
IDProperty *: ((IDProperty *) (prop)->data.pointer), \
const IDProperty *: ((const IDProperty *) (prop)->data.pointer))
+# define IDP_Id(prop) _Generic((prop), \
+ IDProperty *: ((ID *) (prop)->data.pointer), \
+ const IDProperty *: ((const ID *) (prop)->data.pointer))
#else
# define IDP_Float(prop) (*(float *)&(prop)->data.val)
# define IDP_Double(prop) (*(double *)&(prop)->data.val)
# define IDP_String(prop) ((char *) (prop)->data.pointer)
# define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer)
+# define IDP_Id(prop) ((ID *) (prop)->data.pointer)
#endif
#ifndef NDEBUG
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 132c73209d1..e155b0719cc 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -250,7 +250,7 @@ void BKE_image_packfiles_from_mem(struct ReportList *reports, struct Image *ima,
void BKE_image_print_memlist(void);
/* empty image block, of similar type and filename */
-struct Image *BKE_image_copy(struct Main *bmain, struct Image *ima);
+struct Image *BKE_image_copy(struct Main *bmain, const struct Image *ima);
/* merge source into dest, and free source */
void BKE_image_merge(struct Image *dest, struct Image *source);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index e590ff148d7..94e8a24fbc5 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -51,7 +51,7 @@ extern "C" {
void BKE_key_free(struct Key *sc);
void BKE_key_free_nolib(struct Key *key);
struct Key *BKE_key_add(struct ID *id);
-struct Key *BKE_key_copy(struct Main *bmain, struct Key *key);
+struct Key *BKE_key_copy(struct Main *bmain, const struct Key *key);
struct Key *BKE_key_copy_nolib(struct Key *key);
void BKE_key_sort(struct Key *key);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index 4d53850c572..713ca80fb1a 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -44,7 +44,7 @@ struct Scene;
void BKE_lamp_init(struct Lamp *la);
struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
-struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
+struct Lamp *BKE_lamp_copy(struct Main *bmain, const struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local);
void BKE_lamp_free(struct Lamp *la);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 226c82da295..ec1cf79832d 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -47,7 +47,7 @@ struct MDeformVert;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
void BKE_lattice_init(struct Lattice *lt);
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
-struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt);
+struct Lattice *BKE_lattice_copy(struct Main *bmain, const struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);
void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 72ae2cf4efa..258dcc84449 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -50,11 +50,12 @@ struct bContext;
struct PointerRNA;
struct PropertyRNA;
+size_t BKE_libblock_get_alloc_info(short type, const char **name);
void *BKE_libblock_alloc_notest(short type);
void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BKE_libblock_init_empty(struct ID *id);
-void *BKE_libblock_copy(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL();
+void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BKE_libblock_copy_nolib(const struct ID *id, const bool do_action) ATTR_NONNULL();
void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL();
@@ -64,9 +65,10 @@ struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_
/* library_remap.c (keep here since they're general functions) */
void BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL();
+void BKE_libblock_free_datablock(struct ID *id) ATTR_NONNULL();
void BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) ATTR_NONNULL();
void BKE_libblock_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
-void BKE_libblock_free_data(struct Main *bmain, struct ID *id) ATTR_NONNULL();
+void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL();
void BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
@@ -84,10 +86,10 @@ void BKE_id_clear_newpoin(struct ID *id);
void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_in_mainlist, const bool lib_local);
bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
-bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
+bool id_copy(struct Main *bmain, const struct ID *id, struct ID **newid, bool test);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
void BKE_id_expand_local(struct Main *bmain, struct ID *id);
-void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id);
+void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id);
bool new_id(struct ListBase *lb, struct ID *id, const char *name);
void id_clear_lib_data(struct Main *bmain, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index 1258e2fa72e..d6e7d98f371 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -51,6 +51,11 @@ enum {
* This means callback shall not *do* anything, only use this as informative data if it needs it. */
IDWALK_CB_PRIVATE = (1 << 3),
+ /** That ID is not really used by its owner, it's just an internal hint/helper.
+ * This addresses Their Highest Ugliness the 'from' pointers: Object->from_proxy and Key->from.
+ * How to handle that kind of cases totally depends on what caller code is doing... */
+ IDWALK_CB_LOOPBACK = (1 << 4),
+
/**
* Adjusts #ID.us reference-count.
* \note keep in sync with 'newlibadr_us' use in readfile.c
@@ -78,6 +83,8 @@ enum {
IDWALK_NOP = 0,
IDWALK_READONLY = (1 << 0),
IDWALK_RECURSE = (1 << 1), /* Also implies IDWALK_READONLY. */
+
+ IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */
};
/* Loop over all of the ID's this datablock links to. */
@@ -87,7 +94,7 @@ void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const
int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
-bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used);
+bool BKE_library_id_can_use_idtype(struct ID *id_owner, const short id_type_used);
bool BKE_library_ID_is_locally_used(struct Main *bmain, void *idv);
bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h
index 53d438a0fdd..fd37fd762f4 100644
--- a/source/blender/blenkernel/BKE_library_remap.h
+++ b/source/blender/blenkernel/BKE_library_remap.h
@@ -46,6 +46,11 @@ enum {
/* This tells the callback func to force setting IDs using target one with a 'never NULL' pointer to NULL.
* WARNING! Use with extreme care, this will leave database in broken state and can cause crashes very easily! */
ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
+ /* Do not consider proxy/_group pointers of local objects as indirect usages...
+ * Our oh-so-beloved proxies again... Do not consider data used by local proxy object as indirect usage.
+ * This is needed e.g. in reload scenario, since we have to ensure remapping of Armature data of local proxy
+ * is also performed. Usual nightmare... */
+ ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
};
/* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index af9bf58ce77..c7b323d0f6e 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -52,7 +52,7 @@ struct bContext;
void BKE_linestyle_init(struct FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name);
void BKE_linestyle_free(FreestyleLineStyle *linestyle);
-FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle);
+FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle);
void BKE_linestyle_make_local(struct Main *bmain, struct FreestyleLineStyle *linestyle, const bool lib_local);
@@ -63,10 +63,10 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl
LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type);
LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type);
-LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
-LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m);
+LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m);
+LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m);
+LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m);
int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 3349bffac85..0735d2d97a1 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -77,14 +77,14 @@ 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);
+struct MaskSpline *BKE_mask_spline_copy(const struct MaskSpline *spline);
void BKE_mask_point_free(struct MaskSplinePoint *point);
void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay);
void BKE_mask_layer_rename(struct Mask *mask, struct MaskLayer *masklay, char *oldname, char *newname);
-struct MaskLayer *BKE_mask_layer_copy(struct MaskLayer *layer);
-void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, struct ListBase *masklayers);
+struct MaskLayer *BKE_mask_layer_copy(const struct MaskLayer *layer);
+void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, const struct ListBase *masklayers);
/* splines */
struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay);
@@ -123,7 +123,7 @@ void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const eMask
/* general */
struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
struct Mask *BKE_mask_copy_nolib(struct Mask *mask);
-struct Mask *BKE_mask_copy(struct Main *bmain, struct Mask *mask);
+struct Mask *BKE_mask_copy(struct Main *bmain, const struct Mask *mask);
void BKE_mask_make_local(struct Main *bmain, struct Mask *mask, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 8ae5c2b3c45..7da962dd6d6 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -54,7 +54,7 @@ void BKE_material_init(struct Material *ma);
void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
-struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma);
+struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma);
struct Material *localize_material(struct Material *ma);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 64320a20281..c00a0743ebb 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -41,7 +41,7 @@ struct MetaElem;
void BKE_mball_free(struct MetaBall *mb);
void BKE_mball_init(struct MetaBall *mb);
struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
-struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb);
+struct MetaBall *BKE_mball_copy(struct Main *bmain, const struct MetaBall *mb);
void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool lib_local);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index b83bec5a302..b55b8b2dd3c 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -87,7 +87,7 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
void BKE_mesh_free(struct Mesh *me);
void BKE_mesh_init(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
-struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me);
+struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
@@ -110,7 +110,8 @@ int BKE_mesh_nurbs_displist_to_mdata(
struct MEdge **r_alledge, int *r_totedge,
struct MLoop **r_allloop, struct MPoly **r_allpoly,
struct MLoopUV **r_alluv, int *r_totloop, int *r_totpoly);
-void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv);
+void BKE_mesh_from_nurbs_displist(
+ struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name);
void BKE_mesh_from_nurbs(struct Object *ob);
void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test);
void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index 3237c146bc5..69fdad5ef7b 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -41,7 +41,7 @@ struct MovieDistortion;
void BKE_movieclip_free(struct MovieClip *clip);
-struct MovieClip *BKE_movieclip_copy(struct Main *bmain, struct MovieClip *clip);
+struct MovieClip *BKE_movieclip_copy(struct Main *bmain, const struct MovieClip *clip);
void BKE_movieclip_make_local(struct Main *bmain, struct MovieClip *clip, const bool lib_local);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 546f0d97c2b..d5279c5b0ce 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -49,7 +49,7 @@
#include "RNA_types.h"
/* not very important, but the stack solver likes to know a maximum */
-#define MAX_SOCKET 64
+#define MAX_SOCKET 512
struct bContext;
struct bNode;
@@ -335,8 +335,8 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree(struct bNodeTree *ntree);
-struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
-struct bNodeTree *ntreeCopyTree(struct Main *bmain, struct bNodeTree *ntree);
+struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
+struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntree);
/* node->id user count */
void ntreeUserIncrefID(struct bNodeTree *ntree);
void ntreeUserDecrefID(struct bNodeTree *ntree);
@@ -785,6 +785,7 @@ struct ShadeResult;
#define SH_NODE_OUTPUT_LINESTYLE 190
#define SH_NODE_UVALONGSTROKE 191
#define SH_NODE_TEX_POINTDENSITY 192
+#define SH_NODE_BSDF_PRINCIPLED 193
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
@@ -972,7 +973,8 @@ void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct
void ntreeCompositTagRender(struct Scene *sce);
int ntreeCompositTagAnimated(struct bNodeTree *ntree);
void ntreeCompositTagGenerators(struct bNodeTree *ntree);
-void ntreeCompositForceHidden(struct bNodeTree *ntree);
+void ntreeCompositUpdateRLayers(struct bNodeTree *ntree);
+void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
void ntreeCompositClearTags(struct bNodeTree *ntree);
struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node,
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 89adbc4338f..0a5035f9a9b 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -54,7 +54,7 @@ void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struc
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches);
-struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
+struct BulletSoftBody *copy_bulletsoftbody(const struct BulletSoftBody *sb);
struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys);
void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src);
@@ -105,8 +105,8 @@ bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches);
-struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob);
+struct Object *BKE_object_copy_ex(struct Main *bmain, const struct Object *ob, bool copy_caches);
+struct Object *BKE_object_copy(struct Main *bmain, const struct Object *ob);
void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local);
void BKE_object_make_local_ex(struct Main *bmain, struct Object *ob, const bool lib_local, const bool clear_proxy);
bool BKE_object_is_libdata(struct Object *ob);
@@ -189,10 +189,6 @@ void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx,
struct Object *ob);
void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob);
-void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob,
- struct ModifierData *md);
void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
@@ -200,6 +196,11 @@ void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
+void BKE_object_eval_cloth(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *object);
+
+
void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 0a3cc950f32..821dc211591 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -99,7 +99,7 @@ void BKE_paint_set_overlay_override(enum OverlayFlags flag);
/* palettes */
void BKE_palette_free(struct Palette *palette);
struct Palette *BKE_palette_add(struct Main *bmain, const char *name);
-struct Palette *BKE_palette_copy(struct Main *bmain, struct Palette *palette);
+struct Palette *BKE_palette_copy(struct Main *bmain, const struct Palette *palette);
void BKE_palette_make_local(struct Main *bmain, struct Palette *palette, const bool lib_local);
struct PaletteColor *BKE_palette_color_add(struct Palette *palette);
bool BKE_palette_is_empty(const struct Palette *palette);
@@ -109,7 +109,7 @@ void BKE_palette_clear(struct Palette *palette);
/* paint curves */
struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name);
void BKE_paint_curve_free(struct PaintCurve *pc);
-struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, struct PaintCurve *pc);
+struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, const struct PaintCurve *pc);
void BKE_paint_curve_make_local(struct Main *bmain, struct PaintCurve *pc, const bool lib_local);
void BKE_paint_init(struct Scene *sce, PaintMode mode, const char col[3]);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 2b6a84a2f87..f9948ba500a 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -324,7 +324,7 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P
struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name);
void object_remove_particle_system(struct Scene *scene, struct Object *ob);
struct ParticleSettings *psys_new_settings(const char *name, struct Main *main);
-struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, struct ParticleSettings *part);
+struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, const struct ParticleSettings *part);
void BKE_particlesettings_make_local(struct Main *bmain, struct ParticleSettings *part, const bool lib_local);
void psys_reset(struct ParticleSystem *psys, int mode);
diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h
index 99e60757f15..c787e8e8ed1 100644
--- a/source/blender/blenkernel/BKE_property.h
+++ b/source/blender/blenkernel/BKE_property.h
@@ -37,8 +37,8 @@ struct Object;
void BKE_bproperty_free(struct bProperty *prop);
void BKE_bproperty_free_list(struct ListBase *lb);
-struct bProperty *BKE_bproperty_copy(struct bProperty *prop);
-void BKE_bproperty_copy_list(struct ListBase *lbn, struct ListBase *lbo);
+struct bProperty *BKE_bproperty_copy(const struct bProperty *prop);
+void BKE_bproperty_copy_list(struct ListBase *lbn, const struct ListBase *lbo);
void BKE_bproperty_init(struct bProperty *prop);
struct bProperty *BKE_bproperty_new(int type);
void BKE_bproperty_unique(struct bProperty *first, struct bProperty *prop, int force);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 443c3b2b5b2..c72f067a111 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -49,8 +49,8 @@ void BKE_rigidbody_free_constraint(struct Object *ob);
/* ...... */
-struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
-struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
+struct RigidBodyOb *BKE_rigidbody_copy_object(const struct Object *ob);
+struct RigidBodyCon *BKE_rigidbody_copy_constraint(const struct Object *ob);
/* Callback format for performing operations on ID-pointers for rigidbody world. */
typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag);
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index 1579a0c7bb3..10cddd7b454 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -53,15 +53,15 @@ void free_actuators(struct ListBase *lb);
void free_sensor(struct bSensor *sens);
void free_sensors(struct ListBase *lb);
struct bSensor *copy_sensor(struct bSensor *sens);
-void copy_sensors(struct ListBase *lbn, struct ListBase *lbo);
+void copy_sensors(struct ListBase *lbn, const struct ListBase *lbo);
void init_sensor(struct bSensor *sens);
struct bSensor *new_sensor(int type);
struct bController *copy_controller(struct bController *cont);
-void copy_controllers(struct ListBase *lbn, struct ListBase *lbo);
+void copy_controllers(struct ListBase *lbn, const struct ListBase *lbo);
void init_controller(struct bController *cont);
struct bController *new_controller(int type);
struct bActuator *copy_actuator(struct bActuator *act);
-void copy_actuators(struct ListBase *lbn, struct ListBase *lbo);
+void copy_actuators(struct ListBase *lbn, const struct ListBase *lbo);
void init_actuator(struct bActuator *act);
struct bActuator *new_actuator(int type);
void clear_sca_new_poins_ob(struct Object *ob);
@@ -70,7 +70,7 @@ void set_sca_new_poins_ob(struct Object *ob);
void set_sca_new_poins(void);
void BKE_sca_logic_links_remap(struct Main *bmain, struct Object *ob_old, struct Object *ob_new);
-void BKE_sca_logic_copy(struct Object *ob_new, struct Object *ob);
+void BKE_sca_logic_copy(struct Object *ob_new, const struct Object *ob);
void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up);
void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up);
diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h
index b91b64c4b74..907558f9203 100644
--- a/source/blender/blenkernel/BKE_speaker.h
+++ b/source/blender/blenkernel/BKE_speaker.h
@@ -33,7 +33,7 @@ struct Speaker;
void BKE_speaker_init(struct Speaker *spk);
void *BKE_speaker_add(struct Main *bmain, const char *name);
-struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk);
+struct Speaker *BKE_speaker_copy(struct Main *bmain, const struct Speaker *spk);
void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool lib_local);
void BKE_speaker_free(struct Speaker *spk);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index 081b7589af6..c8fb483cdf2 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -52,7 +52,7 @@ bool BKE_text_reload(struct Text *text);
struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const char *relpath,
const bool is_internal);
struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath);
-struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta);
+struct Text *BKE_text_copy (struct Main *bmain, const struct Text *ta);
void BKE_text_make_local (struct Main *bmain, struct Text *text, const bool lib_local);
void BKE_text_clear (struct Text *text);
void BKE_text_write (struct Text *text, const char *str);
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 9a60eb29957..190fdeafaec 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -70,7 +70,7 @@ void colorband_update_sort(struct ColorBand *coba);
void BKE_texture_free(struct Tex *tex);
void BKE_texture_default(struct Tex *tex);
-struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex);
+struct Tex *BKE_texture_copy(struct Main *bmain, const struct Tex *tex);
struct Tex *BKE_texture_add(struct Main *bmain, const char *name);
struct Tex *BKE_texture_localize(struct Tex *tex);
void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool lib_local);
@@ -114,13 +114,13 @@ void BKE_texture_colormapping_default(struct ColorMapping *color
void BKE_texture_envmap_free_data(struct EnvMap *env);
void BKE_texture_envmap_free(struct EnvMap *env);
struct EnvMap *BKE_texture_envmap_add(void);
-struct EnvMap *BKE_texture_envmap_copy(struct EnvMap *env);
+struct EnvMap *BKE_texture_envmap_copy(const struct EnvMap *env);
void BKE_texture_pointdensity_init_data(struct PointDensity *pd);
void BKE_texture_pointdensity_free_data(struct PointDensity *pd);
void BKE_texture_pointdensity_free(struct PointDensity *pd);
struct PointDensity *BKE_texture_pointdensity_add(void);
-struct PointDensity *BKE_texture_pointdensity_copy(struct PointDensity *pd);
+struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd);
void BKE_texture_voxeldata_free_data(struct VoxelData *vd);
void BKE_texture_voxeldata_free(struct VoxelData *vd);
@@ -129,7 +129,7 @@ struct VoxelData *BKE_texture_voxeldata_copy(struct VoxelData *vd);
void BKE_texture_ocean_free(struct OceanTex *ot);
struct OceanTex *BKE_texture_ocean_add(void);
-struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot);
+struct OceanTex *BKE_texture_ocean_copy(const struct OceanTex *ot);
bool BKE_texture_dependsOnTime(const struct Tex *texture);
bool BKE_texture_is_image_user(const struct Tex *tex);
@@ -144,6 +144,8 @@ void BKE_texture_get_value(
const struct Scene *scene, struct Tex *texture,
float *tex_co, struct TexResult *texres, bool use_color_management);
+void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 30873567297..b48be382073 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -52,7 +52,7 @@ struct rcti;
/* **** Common functions **** */
void BKE_tracking_free(struct MovieTracking *tracking);
-void BKE_tracking_copy(struct MovieTracking *tracking_dst, struct MovieTracking *tracking_src);
+void BKE_tracking_copy(struct MovieTracking *tracking_dst, const struct MovieTracking *tracking_src);
void BKE_tracking_settings_init(struct MovieTracking *tracking);
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index 23bf9ec3d22..18ae61f7653 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -39,7 +39,7 @@ struct World;
void BKE_world_free(struct World *sc);
void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
-struct World *BKE_world_copy(struct Main *bmain, struct World *wrld);
+struct World *BKE_world_copy(struct Main *bmain, const struct World *wrld);
struct World *localize_world(struct World *wrld);
void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 160adcc3988..eba5814d897 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2123,6 +2123,8 @@ static void mesh_calc_modifiers(
DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL);
append_mask |= CD_MASK_PREVIEW_MLOOPCOL;
}
+
+ dm->deformedOnly = false;
}
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
@@ -2463,6 +2465,8 @@ static void editbmesh_calc_modifiers(
deformedVerts = NULL;
}
}
+
+ dm->deformedOnly = false;
}
/* In case of active preview modifier, make sure preview mask remains for following modifiers. */
@@ -2912,9 +2916,6 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em, CustomDa
/* get derived mesh from an object, using editbmesh if available. */
DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
-
if (for_render) {
/* TODO(sergey): use proper derived render here in the future. */
return ob->derivedFinal;
@@ -2922,9 +2923,13 @@ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
/* only return the editmesh if its from this object because
* we don't a mesh from another object's modifier stack: T43122 */
- if (em && (em->ob == ob)) {
- DerivedMesh *dm = em->derivedFinal;
- return dm;
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em && (em->ob == ob)) {
+ DerivedMesh *dm = em->derivedFinal;
+ return dm;
+ }
}
return ob->derivedFinal;
@@ -3317,7 +3322,8 @@ void DM_calc_loop_tangents_step_0(
const CustomData *loopData, bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME], int tangent_names_count,
bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
- char *ract_uv_name, char *rren_uv_name, char *rtangent_mask) {
+ char *ract_uv_name, char *rren_uv_name, char *rtangent_mask)
+{
/* Active uv in viewport */
int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
*ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
@@ -3455,7 +3461,7 @@ void DM_calc_loop_tangents(
* have to check this is valid...
*/
mesh2tangent->precomputedLoopNormals = dm->getLoopDataArray(dm, CD_NORMAL);
- mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+ mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->polyData, CD_NORMAL);
mesh2tangent->orco = NULL;
mesh2tangent->mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 1e33fe4ab46..885ea36d404 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -120,7 +120,7 @@ void BKE_action_free(bAction *act)
/* .................................. */
-bAction *BKE_action_copy(Main *bmain, bAction *src)
+bAction *BKE_action_copy(Main *bmain, const bAction *src)
{
bAction *dst = NULL;
bActionGroup *dgrp, *sgrp;
@@ -523,7 +523,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose)
*
* \param dst Should be freed already, makes entire duplicate.
*/
-void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints)
+void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constraints)
{
bPose *outPose;
bPoseChannel *pchan;
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 0b637355ecf..bcc0d1aeacb 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -397,73 +397,6 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a
}
}
-/* Make Local -------------------------------------------- */
-
-static void make_local_strips(ListBase *strips)
-{
- NlaStrip *strip;
-
- for (strip = strips->first; strip; strip = strip->next) {
- if (strip->act) BKE_action_make_local(G.main, strip->act, false);
- if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target, false);
-
- make_local_strips(&strip->strips);
- }
-}
-
-/* Use local copy instead of linked copy of various ID-blocks */
-void BKE_animdata_make_local(AnimData *adt)
-{
- NlaTrack *nlt;
-
- /* Actions - Active and Temp */
- if (adt->action) BKE_action_make_local(G.main, adt->action, false);
- if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact, false);
- /* Remaps */
- if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target, false);
-
- /* Drivers */
- /* TODO: need to remap the ID-targets too? */
-
- /* NLA Data */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next)
- make_local_strips(&nlt->strips);
-}
-
-
-/* When duplicating data (i.e. objects), drivers referring to the original data will
- * get updated to point to the duplicated data (if drivers belong to the new data)
- */
-void BKE_animdata_relink(AnimData *adt)
-{
- /* sanity check */
- if (adt == NULL)
- return;
-
- /* drivers */
- if (adt->drivers.first) {
- FCurve *fcu;
-
- /* check each driver against all the base paths to see if any should go */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
-
- /* driver variables */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* only change the used targets, since the others will need fixing manually anyway */
- DRIVER_TARGETS_USED_LOOPER(dvar)
- {
- if (dtar->id && dtar->id->newid) {
- dtar->id = dtar->id->newid;
- }
- }
- DRIVER_TARGETS_LOOPER_END
- }
- }
- }
-}
-
/* Sub-ID Regrouping ------------------------------------------- */
/**
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index f2f0a92d8b3..43fd47981b1 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -114,18 +114,26 @@ static char *blender_version_decimal(const int ver)
* Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
* returning true if result points to a directory.
*/
-static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
+static bool test_path(
+ char *targetpath, size_t targetpath_len,
+ const char *path_base, const char *path_sep, const char *folder_name)
{
char tmppath[FILE_MAX];
- if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
- else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
+ if (path_sep) {
+ BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
+ }
+ else {
+ BLI_strncpy(tmppath, path_base, sizeof(tmppath));
+ }
/* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */
- if (folder_name)
- BLI_make_file_string("/", targetpath, tmppath, folder_name);
- else
- BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
+ if (folder_name) {
+ BLI_join_dirfile(targetpath, targetpath_len, tmppath, folder_name);
+ }
+ else {
+ BLI_strncpy(targetpath, tmppath, targetpath_len);
+ }
/* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
* if folder_name is specified but not otherwise? */
@@ -179,7 +187,9 @@ static bool test_env_path(char *path, const char *envvar)
* \param ver To construct name of version-specific directory within bprogdir
* \return true if such a directory exists.
*/
-static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
+static bool get_path_local(
+ char *targetpath, size_t targetpath_len,
+ const char *folder_name, const char *subfolder_name, const int ver)
{
char relfolder[FILE_MAX];
@@ -201,11 +211,12 @@ static bool get_path_local(char *targetpath, const char *folder_name, const char
/* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
#ifdef __APPLE__
- static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
+ /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
+ static char osx_resourses[FILE_MAX];
sprintf(osx_resourses, "%s../Resources", bprogdir);
- return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder);
+ return test_path(targetpath, targetpath_len, osx_resourses, blender_version_decimal(ver), relfolder);
#else
- return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
+ return test_path(targetpath, targetpath_len, bprogdir, blender_version_decimal(ver), relfolder);
#endif
}
@@ -219,7 +230,7 @@ static bool is_portable_install(void)
const int ver = BLENDER_VERSION;
char path[FILE_MAX];
- return get_path_local(path, "config", NULL, ver);
+ return get_path_local(path, sizeof(path), "config", NULL, ver);
}
/**
@@ -233,20 +244,22 @@ static bool is_portable_install(void)
* \param ver Blender version, used to construct a subdirectory name
* \return true if it was able to construct such a path.
*/
-static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+static bool get_path_user(
+ char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name,
+ const char *envvar, const int ver)
{
char user_path[FILE_MAX];
const char *user_base_path;
/* for portable install, user path is always local */
- if (is_portable_install())
- return get_path_local(targetpath, folder_name, subfolder_name, ver);
-
+ if (is_portable_install()) {
+ return get_path_local(targetpath, targetpath_len, folder_name, subfolder_name, ver);
+ }
user_path[0] = '\0';
if (test_env_path(user_path, envvar)) {
if (subfolder_name) {
- return test_path(targetpath, user_path, NULL, subfolder_name);
+ return test_path(targetpath, targetpath_len, user_path, NULL, subfolder_name);
}
else {
BLI_strncpy(targetpath, user_path, FILE_MAX);
@@ -266,10 +279,10 @@ static bool get_path_user(char *targetpath, const char *folder_name, const char
#endif
if (subfolder_name) {
- return test_path(targetpath, user_path, folder_name, subfolder_name);
+ return test_path(targetpath, targetpath_len, user_path, folder_name, subfolder_name);
}
else {
- return test_path(targetpath, user_path, NULL, folder_name);
+ return test_path(targetpath, targetpath_len, user_path, NULL, folder_name);
}
}
@@ -283,7 +296,9 @@ static bool get_path_user(char *targetpath, const char *folder_name, const char
* \param ver Blender version, used to construct a subdirectory name
* \return true if it was able to construct such a path.
*/
-static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+static bool get_path_system(
+ char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name,
+ const char *envvar, const int ver)
{
char system_path[FILE_MAX];
const char *system_base_path;
@@ -307,13 +322,13 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha
/* try CWD/release/folder_name */
if (BLI_current_working_dir(cwd, sizeof(cwd))) {
- if (test_path(targetpath, cwd, "release", relfolder)) {
+ if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) {
return true;
}
}
/* try EXECUTABLE_DIR/release/folder_name */
- if (test_path(targetpath, bprogdir, "release", relfolder))
+ if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder))
return true;
/* end developer overrides */
@@ -324,7 +339,7 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha
if (test_env_path(system_path, envvar)) {
if (subfolder_name) {
- return test_path(targetpath, system_path, NULL, subfolder_name);
+ return test_path(targetpath, targetpath_len, system_path, NULL, subfolder_name);
}
else {
BLI_strncpy(targetpath, system_path, FILE_MAX);
@@ -345,57 +360,63 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha
if (subfolder_name) {
/* try $BLENDERPATH/folder_name/subfolder_name */
- return test_path(targetpath, system_path, folder_name, subfolder_name);
+ return test_path(targetpath, targetpath_len, system_path, folder_name, subfolder_name);
}
else {
/* try $BLENDERPATH/folder_name */
- return test_path(targetpath, system_path, NULL, folder_name);
+ return test_path(targetpath, targetpath_len, system_path, NULL, folder_name);
}
}
-/* get a folder out of the 'folder_id' presets for paths */
-/* returns the path if found, NULL string if not */
-const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
+/**
+ * Get a folder out of the 'folder_id' presets for paths.
+ * returns the path if found, NULL string if not
+ *
+ * \param subfolder: The name of a directory to check for,
+ * this may contain path separators but must resolve to a directory, checked with #BLI_is_dir.
+ */
+const char *BKE_appdir_folder_id_ex(
+ const int folder_id, const char *subfolder,
+ char *path, size_t path_len)
{
const int ver = BLENDER_VERSION;
- static char path[FILE_MAX] = "";
-
+
switch (folder_id) {
case BLENDER_DATAFILES: /* general case */
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
return NULL;
case BLENDER_USER_DATAFILES:
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
return NULL;
case BLENDER_SYSTEM_DATAFILES:
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
return NULL;
case BLENDER_USER_AUTOSAVE:
- if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_user(path, path_len, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
return NULL;
case BLENDER_USER_CONFIG:
- if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
+ if (get_path_user(path, path_len, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
return NULL;
case BLENDER_USER_SCRIPTS:
- if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
+ if (get_path_user(path, path_len, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
return NULL;
case BLENDER_SYSTEM_SCRIPTS:
- if (get_path_local(path, "scripts", subfolder, ver)) break;
- if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
+ if (get_path_local(path, path_len, "scripts", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
return NULL;
case BLENDER_SYSTEM_PYTHON:
- if (get_path_local(path, "python", subfolder, ver)) break;
- if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
+ if (get_path_local(path, path_len, "python", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
return NULL;
default:
@@ -406,6 +427,13 @@ const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
return path;
}
+const char *BKE_appdir_folder_id(
+ const int folder_id, const char *subfolder)
+{
+ static char path[FILE_MAX] = "";
+ return BKE_appdir_folder_id_ex(folder_id, subfolder, path, sizeof(path));
+}
+
/**
* Returns the path to a folder in the user area without checking that it actually exists first.
*/
@@ -416,16 +444,16 @@ const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *su
switch (folder_id) {
case BLENDER_USER_DATAFILES:
- get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
+ get_path_user(path, sizeof(path), "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
break;
case BLENDER_USER_CONFIG:
- get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
+ get_path_user(path, sizeof(path), "config", subfolder, "BLENDER_USER_CONFIG", ver);
break;
case BLENDER_USER_AUTOSAVE:
- get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
+ get_path_user(path, sizeof(path), "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
break;
case BLENDER_USER_SCRIPTS:
- get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
+ get_path_user(path, sizeof(path), "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
break;
default:
BLI_assert(0);
@@ -469,13 +497,13 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con
bool ok;
switch (folder_id) {
case BLENDER_RESOURCE_PATH_USER:
- ok = get_path_user(path, NULL, NULL, NULL, ver);
+ ok = get_path_user(path, sizeof(path), NULL, NULL, NULL, ver);
break;
case BLENDER_RESOURCE_PATH_LOCAL:
- ok = get_path_local(path, NULL, NULL, ver);
+ ok = get_path_local(path, sizeof(path), NULL, NULL, ver);
break;
case BLENDER_RESOURCE_PATH_SYSTEM:
- ok = get_path_system(path, NULL, NULL, NULL, ver);
+ ok = get_path_system(path, sizeof(path), NULL, NULL, NULL, ver);
break;
default:
path[0] = '\0'; /* in case do_check is false */
@@ -655,6 +683,48 @@ bool BKE_appdir_program_python_search(
return is_found;
}
+static const char *app_template_directory_search[2] = {
+ "startup" SEP_STR "bl_app_templates_user",
+ "startup" SEP_STR "bl_app_templates_system",
+};
+
+static const int app_template_directory_id[2] = {
+ BLENDER_USER_SCRIPTS,
+ BLENDER_SYSTEM_SCRIPTS,
+};
+
+/**
+ * Return true if templates exist
+ */
+bool BKE_appdir_app_template_any(void)
+{
+ char temp_dir[FILE_MAX];
+ for (int i = 0; i < 2; i++) {
+ if (BKE_appdir_folder_id_ex(
+ app_template_directory_id[i], app_template_directory_search[i],
+ temp_dir, sizeof(temp_dir)))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len)
+{
+ for (int i = 0; i < 2; i++) {
+ char subdir[FILE_MAX];
+ BLI_join_dirfile(subdir, sizeof(subdir), app_template_directory_search[i], app_template);
+ if (BKE_appdir_folder_id_ex(
+ app_template_directory_id[i], subdir,
+ path, path_len))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* Gets the temp directory when blender first runs.
* If the default path is not found, use try $TEMP
@@ -713,7 +783,8 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c
BLI_add_slash(fullname);
#ifdef WIN32
if (userdir && userdir != fullname) {
- BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
+ /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
+ BLI_strncpy(userdir, fullname, maxlen);
}
#endif
}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 02cc31e5977..35b6fe113bd 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -150,7 +150,7 @@ void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local)
BKE_id_make_local_generic(bmain, &arm->id, true, lib_local);
}
-static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone **newActBone)
+static void copy_bonechildren(Bone *newBone, const Bone *oldBone, const Bone *actBone, Bone **newActBone)
{
Bone *curBone, *newChildBone;
@@ -172,7 +172,7 @@ static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone
}
}
-bArmature *BKE_armature_copy(Main *bmain, bArmature *arm)
+bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm)
{
bArmature *newArm;
Bone *oldBone, *newBone;
@@ -982,6 +982,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
return;
}
+ if ((armOb->pose->flag & POSE_RECALC) != 0) {
+ printf("ERROR! Trying to evaluate influence of armature '%s' which needs Pose recalc!", armOb->id.name);
+ BLI_assert(0);
+ }
+
invert_m4_m4(obinv, target->obmat);
copy_m4_m4(premat, target->obmat);
mul_m4_m4m4(postmat, obinv, armOb->obmat);
@@ -1980,6 +1985,8 @@ void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
if (counter > 1 && sort_bones) {
DAG_pose_sort(ob);
}
+#else
+ UNUSED_VARS(sort_bones);
#endif
ob->pose->flag &= ~POSE_RECALC;
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 3bc81a69c86..a4714041edf 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -628,10 +628,10 @@ void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx),
}
void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
Object *ob,
bPoseChannel *pchan)
{
- Scene *scene = G.main->scene.first;
DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
bArmature *arm = (bArmature *)ob->data;
if (arm->flag & ARM_RESTPOS) {
@@ -702,4 +702,8 @@ void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
}
+ /* Rest of operations are NO-OP in depsgraph, so can clear
+ * flag now.
+ */
+ ob->recalc &= ~OB_RECALC_ALL;
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index afd60102453..ceb641073e0 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -100,6 +100,18 @@ void BKE_blender_free(void)
free_nodesystem();
}
+void BKE_blender_version_string(char *version_str, size_t maxncpy, short version, short subversion, bool v_prefix, bool include_subversion)
+{
+ const char *prefix = v_prefix ? "v" : "";
+
+ if (include_subversion && subversion > 0) {
+ BLI_snprintf(version_str, maxncpy, "%s%d.%02d.%d", prefix, version / 100, version % 100, subversion);
+ }
+ else {
+ BLI_snprintf(version_str, maxncpy, "%s%d.%02d", prefix, version / 100, version % 100);
+ }
+}
+
void BKE_blender_globals_init(void)
{
memset(&G, 0, sizeof(Global));
@@ -110,10 +122,7 @@ void BKE_blender_globals_init(void)
strcpy(G.ima, "//");
- if (BLENDER_SUBVERSION)
- BLI_snprintf(versionstr, sizeof(versionstr), "v%d.%02d.%d", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION);
- else
- BLI_snprintf(versionstr, sizeof(versionstr), "v%d.%02d", BLENDER_VERSION / 100, BLENDER_VERSION % 100);
+ BKE_blender_version_string(versionstr, sizeof(versionstr), BLENDER_VERSION, BLENDER_SUBVERSION, true, true);
#ifndef WITH_PYTHON_SECURITY /* default */
G.f |= G_SCRIPT_AUTOEXEC;
@@ -141,20 +150,18 @@ static void keymap_item_free(wmKeyMapItem *kmi)
MEM_freeN(kmi->ptr);
}
-/**
- * When loading a new userdef from file,
- * or when exiting Blender.
- */
-void BKE_blender_userdef_free(void)
+void BKE_blender_userdef_set_data(UserDef *userdef)
{
- wmKeyMap *km;
- wmKeyMapItem *kmi;
- wmKeyMapDiffItem *kmdi;
- bAddon *addon, *addon_next;
- uiFont *font;
-
- for (km = U.user_keymaps.first; km; km = km->next) {
- for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
+ /* only here free userdef themes... */
+ BKE_blender_userdef_free_data(&U);
+ U = *userdef;
+}
+
+static void userdef_free_keymaps(UserDef *userdef)
+{
+ for (wmKeyMap *km = userdef->user_keymaps.first, *km_next; km; km = km_next) {
+ km_next = km->next;
+ for (wmKeyMapDiffItem *kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
if (kmdi->add_item) {
keymap_item_free(kmdi->add_item);
MEM_freeN(kmdi->add_item);
@@ -165,14 +172,21 @@ void BKE_blender_userdef_free(void)
}
}
- for (kmi = km->items.first; kmi; kmi = kmi->next)
+ for (wmKeyMapItem *kmi = km->items.first; kmi; kmi = kmi->next) {
keymap_item_free(kmi);
+ }
BLI_freelistN(&km->diff_items);
BLI_freelistN(&km->items);
+
+ MEM_freeN(km);
}
-
- for (addon = U.addons.first; addon; addon = addon_next) {
+ BLI_listbase_clear(&userdef->user_keymaps);
+}
+
+static void userdef_free_addons(UserDef *userdef)
+{
+ for (bAddon *addon = userdef->addons.first, *addon_next; addon; addon = addon_next) {
addon_next = addon->next;
if (addon->prop) {
IDP_FreeProperty(addon->prop);
@@ -180,19 +194,35 @@ void BKE_blender_userdef_free(void)
}
MEM_freeN(addon);
}
+ BLI_listbase_clear(&userdef->addons);
+}
- for (font = U.uifonts.first; font; font = font->next) {
+/**
+ * When loading a new userdef from file,
+ * or when exiting Blender.
+ */
+void BKE_blender_userdef_free_data(UserDef *userdef)
+{
+#define U _invalid_access_ /* ensure no accidental global access */
+#ifdef U /* quiet warning */
+#endif
+
+ userdef_free_keymaps(userdef);
+ userdef_free_addons(userdef);
+
+ for (uiFont *font = userdef->uifonts.first; font; font = font->next) {
BLF_unload_id(font->blf_id);
}
BLF_default_set(-1);
- BLI_freelistN(&U.autoexec_paths);
+ BLI_freelistN(&userdef->autoexec_paths);
+
+ BLI_freelistN(&userdef->uistyles);
+ BLI_freelistN(&userdef->uifonts);
+ BLI_freelistN(&userdef->themes);
- BLI_freelistN(&U.uistyles);
- BLI_freelistN(&U.uifonts);
- BLI_freelistN(&U.themes);
- BLI_freelistN(&U.user_keymaps);
+#undef U
}
/**
@@ -208,6 +238,44 @@ void BKE_blender_userdef_refresh(void)
}
+/**
+ * Write U from userdef.
+ * This function defines which settings a template will override for the user preferences.
+ */
+void BKE_blender_userdef_set_app_template(UserDef *userdef)
+{
+ /* TODO:
+ * - keymaps
+ * - various minor settings (add as needed).
+ */
+
+#define LIST_OVERRIDE(id) { \
+ BLI_freelistN(&U.id); \
+ BLI_movelisttolist(&U.id, &userdef->id); \
+} ((void)0)
+
+#define MEMCPY_OVERRIDE(id) \
+ memcpy(U.id, userdef->id, sizeof(U.id));
+
+ /* for some types we need custom free functions */
+ userdef_free_addons(&U);
+ userdef_free_keymaps(&U);
+
+ LIST_OVERRIDE(uistyles);
+ LIST_OVERRIDE(uifonts);
+ LIST_OVERRIDE(themes);
+ LIST_OVERRIDE(addons);
+ LIST_OVERRIDE(user_keymaps);
+
+ MEMCPY_OVERRIDE(light);
+
+ MEMCPY_OVERRIDE(font_path_ui);
+ MEMCPY_OVERRIDE(font_path_ui_mono);
+
+#undef LIST_OVERRIDE
+#undef MEMCPY_OVERRIDE
+}
+
/* ***************** testing for break ************* */
static void (*blender_test_break_cb)(void) = NULL;
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index bc98d6f6805..e3a5edb2049 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -108,9 +108,9 @@ static int read_undosave(bContext *C, UndoElem *uel)
G.fileflags |= G_FILE_NO_UI;
if (UNDO_DISK)
- success = (BKE_blendfile_read(C, uel->str, NULL) != BKE_BLENDFILE_READ_FAIL);
+ success = (BKE_blendfile_read(C, uel->str, NULL, 0) != BKE_BLENDFILE_READ_FAIL);
else
- success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL);
+ success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL, 0);
/* restore */
BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */
@@ -389,7 +389,7 @@ bool BKE_undo_save_file(const char *filename)
Main *BKE_undo_get_main(Scene **r_scene)
{
Main *mainp = NULL;
- BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL);
+ BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL, BLO_READ_SKIP_NONE);
if (bfd) {
mainp = bfd->main;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 54f709a1e5b..05ea7983b8e 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -227,7 +227,7 @@ static void setup_app_data(
if (bfd->user) {
/* only here free userdef themes... */
- BKE_blender_userdef_free();
+ BKE_blender_userdef_free_data(&U);
U = *bfd->user;
@@ -349,17 +349,23 @@ static int handle_subversion_warning(Main *main, ReportList *reports)
return 1;
}
-int BKE_blendfile_read(bContext *C, const char *filepath, ReportList *reports)
+int BKE_blendfile_read(
+ bContext *C, const char *filepath,
+ ReportList *reports, int skip_flags)
{
BlendFileData *bfd;
int retval = BKE_BLENDFILE_READ_OK;
- if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) /* don't print user-pref loading */
- printf("read blend: %s\n", filepath);
+ /* don't print user-pref loading */
+ if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) {
+ printf("Read blend: %s\n", filepath);
+ }
- bfd = BLO_read_from_file(filepath, reports);
+ bfd = BLO_read_from_file(filepath, reports, skip_flags);
if (bfd) {
- if (bfd->user) retval = BKE_BLENDFILE_READ_OK_USERPREFS;
+ if (bfd->user) {
+ retval = BKE_BLENDFILE_READ_OK_USERPREFS;
+ }
if (0 == handle_subversion_warning(bfd->main, reports)) {
BKE_main_free(bfd->main);
@@ -379,11 +385,11 @@ int BKE_blendfile_read(bContext *C, const char *filepath, ReportList *reports)
bool BKE_blendfile_read_from_memory(
bContext *C, const void *filebuf, int filelength,
- ReportList *reports, bool update_defaults)
+ ReportList *reports, int skip_flags, bool update_defaults)
{
BlendFileData *bfd;
- bfd = BLO_read_from_memory(filebuf, filelength, reports);
+ bfd = BLO_read_from_memory(filebuf, filelength, reports, skip_flags);
if (bfd) {
if (update_defaults)
BLO_update_defaults_startup_blend(bfd->main);
@@ -399,17 +405,17 @@ bool BKE_blendfile_read_from_memory(
/* memfile is the undo buffer */
bool BKE_blendfile_read_from_memfile(
bContext *C, struct MemFile *memfile,
- ReportList *reports)
+ ReportList *reports, int skip_flags)
{
BlendFileData *bfd;
- bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports);
+ bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports, skip_flags);
if (bfd) {
/* remove the unused screens and wm */
while (bfd->main->wm.first)
- BKE_libblock_free_ex(bfd->main, bfd->main->wm.first, true, true);
+ BKE_libblock_free(bfd->main, bfd->main->wm.first);
while (bfd->main->screen.first)
- BKE_libblock_free_ex(bfd->main, bfd->main->screen.first, true, true);
+ BKE_libblock_free(bfd->main, bfd->main->screen.first);
setup_app_data(C, bfd, "<memory1>", reports);
}
@@ -420,32 +426,76 @@ bool BKE_blendfile_read_from_memfile(
return (bfd != NULL);
}
+/**
+ * Utility to make a file 'empty' used for startup to optionally give an empty file.
+ * Handy for tests.
+ */
+void BKE_blendfile_read_make_empty(bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+
+ ListBase *lbarray[MAX_LIBARRAY];
+ ID *id;
+ int a;
+
+ a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ id = lbarray[a]->first;
+ if (id != NULL) {
+ if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM)) {
+ continue;
+ }
+ while ((id = lbarray[a]->first)) {
+ BKE_libblock_delete(bmain, id);
+ }
+ }
+ }
+}
+
/* only read the userdef from a .blend */
-int BKE_blendfile_read_userdef(const char *filepath, ReportList *reports)
+UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports)
{
BlendFileData *bfd;
- int retval = BKE_BLENDFILE_READ_FAIL;
+ UserDef *userdef = NULL;
- bfd = BLO_read_from_file(filepath, reports);
+ bfd = BLO_read_from_file(filepath, reports, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF);
if (bfd) {
if (bfd->user) {
- retval = BKE_BLENDFILE_READ_OK_USERPREFS;
+ userdef = bfd->user;
+ }
+ BKE_main_free(bfd->main);
+ MEM_freeN(bfd);
+ }
- /* only here free userdef themes... */
- BKE_blender_userdef_free();
+ return userdef;
+}
- U = *bfd->user;
- MEM_freeN(bfd->user);
+
+UserDef *BKE_blendfile_userdef_read_from_memory(
+ const void *filebuf, int filelength,
+ ReportList *reports)
+{
+ BlendFileData *bfd;
+ UserDef *userdef = NULL;
+
+ bfd = BLO_read_from_memory(filebuf, filelength, reports, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF);
+ if (bfd) {
+ if (bfd->user) {
+ userdef = bfd->user;
}
BKE_main_free(bfd->main);
MEM_freeN(bfd);
}
+ else {
+ BKE_reports_prepend(reports, "Loading failed: ");
+ }
- return retval;
+ return userdef;
}
+
/* only write the userdef in a .blend */
-int BKE_blendfile_write_userdef(const char *filepath, ReportList *reports)
+int BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
{
Main *mainb = MEM_callocN(sizeof(Main), "empty main");
int retval = 0;
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index b4bc83bf94c..7ca4e07076d 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -1581,7 +1581,7 @@ void boid_free_settings(BoidSettings *boids)
MEM_freeN(boids);
}
}
-BoidSettings *boid_copy_settings(BoidSettings *boids)
+BoidSettings *boid_copy_settings(const BoidSettings *boids)
{
BoidSettings *nboids = NULL;
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 487b8ffa2b5..f210c6aa7f3 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -243,7 +243,7 @@ static bool missing_files_find__recursive(
continue; /* cant stat, don't bother with this file, could print debug info here */
if (S_ISREG(status.st_mode)) { /* is file */
- if (STREQLEN(filename, de->d_name, FILE_MAX)) { /* name matches */
+ if (BLI_path_ncmp(filename, de->d_name, FILE_MAX) == 0) { /* name matches */
/* open the file to read its size */
size = status.st_size;
if ((size > 0) && (size > *r_filesize)) { /* find the biggest file */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 57b707a31d3..aae323a5056 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -172,7 +172,7 @@ struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode)
return NULL;
}
-Brush *BKE_brush_copy(Main *bmain, Brush *brush)
+Brush *BKE_brush_copy(Main *bmain, const Brush *brush)
{
Brush *brushn;
@@ -195,7 +195,7 @@ Brush *BKE_brush_copy(Main *bmain, Brush *brush)
brushn->curve = curvemapping_copy(brush->curve);
/* enable fake user by default */
- id_fake_user_set(&brush->id);
+ id_fake_user_set(&brushn->id);
BKE_id_copy_ensure_local(bmain, &brush->id, &brushn->id);
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index c0e4ef37a93..c1fad4f80c8 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -917,10 +917,10 @@ BVHTree *bvhtree_from_mesh_faces(
/**
* Builds a bvh tree where nodes are the given tessellated faces (note: does not copy given mfaces!).
- * \param vert_allocated if true, vert freeing will be done when freeing data.
- * \param face_allocated if true, face freeing will be done when freeing data.
+ * \param vert_allocated: if true, vert freeing will be done when freeing data.
+ * \param face_allocated: if true, face freeing will be done when freeing data.
* \param faces_mask: if not null, true elements give which faces to add to BVH tree.
- * \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
+ * \param faces_num_active: if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_faces_ex(
BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated,
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 3dce08eb756..17d482a5d1b 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -82,6 +82,7 @@ void BKE_cachefile_init(CacheFile *cache_file)
cache_file->is_sequence = false;
cache_file->scale = 1.0f;
cache_file->handle_mutex = BLI_mutex_alloc();
+ BLI_listbase_clear(&cache_file->object_paths);
}
/** Free (or release) any data used by this cachefile (does not free the cachefile itself). */
@@ -99,12 +100,12 @@ void BKE_cachefile_free(CacheFile *cache_file)
BLI_freelistN(&cache_file->object_paths);
}
-CacheFile *BKE_cachefile_copy(Main *bmain, CacheFile *cache_file)
+CacheFile *BKE_cachefile_copy(Main *bmain, const CacheFile *cache_file)
{
CacheFile *new_cache_file = BKE_libblock_copy(bmain, &cache_file->id);
new_cache_file->handle = NULL;
- BLI_listbase_clear(&cache_file->object_paths);
+ BLI_listbase_clear(&new_cache_file->object_paths);
BKE_id_copy_ensure_local(bmain, &cache_file->id, &new_cache_file->id);
@@ -220,7 +221,6 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
}
#endif
mcmd->reader = NULL;
- mcmd->object_path[0] = '\0';
}
}
@@ -238,7 +238,6 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
}
#endif
data->reader = NULL;
- data->object_path[0] = '\0';
}
}
}
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 9cb553aa27b..915c08674a4 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -93,7 +93,7 @@ void *BKE_camera_add(Main *bmain, const char *name)
return cam;
}
-Camera *BKE_camera_copy(Main *bmain, Camera *cam)
+Camera *BKE_camera_copy(Main *bmain, const Camera *cam)
{
Camera *camn;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 7042b46330b..46a067ea0bc 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -2992,9 +2992,12 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
STACK_DECLARE(mvert);
STACK_DECLARE(oldv);
- MEdge *med, *medge = MEM_mallocN(sizeof(*medge) * totedge, __func__);
- int *olde = MEM_mallocN(sizeof(*olde) * totedge, __func__);
- int *newe = MEM_mallocN(sizeof(*newe) * totedge, __func__);
+ /* Note: create (totedge + totloop) elements because partially invalid polys due to merge may require
+ * generating new edges, and while in 99% cases we'll still end with less final edges than totedge,
+ * cases can be forged that would end requiring more... */
+ MEdge *med, *medge = MEM_mallocN(sizeof(*medge) * (totedge + totloop), __func__);
+ int *olde = MEM_mallocN(sizeof(*olde) * (totedge + totloop), __func__);
+ int *newe = MEM_mallocN(sizeof(*newe) * (totedge + totloop), __func__);
STACK_DECLARE(medge);
STACK_DECLARE(olde);
@@ -3028,7 +3031,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
STACK_INIT(mloop, totloop);
STACK_INIT(mpoly, totpoly);
- /* fill newl with destination vertex indices */
+ /* fill newv with destination vertex indices */
mv = cddm->mvert;
c = 0;
for (i = 0; i < totvert; i++, mv++) {
@@ -3117,83 +3120,80 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
mp = cddm->mpoly;
+ mv = cddm->mvert;
for (i = 0; i < totpoly; i++, mp++) {
MPoly *mp_new;
ml = cddm->mloop + mp->loopstart;
/* check faces with all vertices merged */
- {
- bool all_vertices_merged = true;
+ bool all_vertices_merged = true;
- for (j = 0; j < mp->totloop; j++, ml++) {
- if (vtargetmap[ml->v] == -1) {
- all_vertices_merged = false;
- break;
- }
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ if (vtargetmap[ml->v] == -1) {
+ all_vertices_merged = false;
+ /* This will be used to check for poly using several time the same vert. */
+ mv[ml->v].flag &= ~ME_VERT_TMP_TAG;
}
+ else {
+ /* This will be used to check for poly using several time the same vert. */
+ mv[vtargetmap[ml->v]].flag &= ~ME_VERT_TMP_TAG;
+ }
+ }
- if (UNLIKELY(all_vertices_merged)) {
- if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) {
- /* In this mode, all vertices merged is enough to dump face */
- continue;
+ if (UNLIKELY(all_vertices_merged)) {
+ if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) {
+ /* In this mode, all vertices merged is enough to dump face */
+ continue;
+ }
+ else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) {
+ /* Additional condition for face dump: target vertices must make up an identical face */
+ /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */
+ /* (2) second step is thorough but more costly poly compare */
+ int i_poly, v_target;
+ bool found = false;
+ PolyKey pkey;
+
+ /* Use poly_gset for fast (although not 100% certain) identification of same poly */
+ /* First, make up a poly_summary structure */
+ ml = cddm->mloop + mp->loopstart;
+ pkey.hash_sum = pkey.hash_xor = 0;
+ pkey.totloops = 0;
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */
+ pkey.hash_sum += v_target;
+ pkey.hash_xor ^= v_target;
+ pkey.totloops++;
}
- else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) {
- /* Additional condition for face dump: target vertices must make up an identical face */
- /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */
- /* (2) second step is thorough but more costly poly compare */
- int i_poly, v_target, v_prev;
- bool found = false;
- PolyKey pkey;
-
- /* Use poly_gset for fast (although not 100% certain) identification of same poly */
- /* First, make up a poly_summary structure */
+ if (BLI_gset_haskey(poly_gset, &pkey)) {
+
+ /* There might be a poly that matches this one.
+ * We could just leave it there and say there is, and do a "continue".
+ * ... but we are checking whether there is an exact poly match.
+ * It's not so costly in terms of CPU since it's very rare, just a lot of complex code.
+ */
+
+ /* Consider current loop again */
ml = cddm->mloop + mp->loopstart;
- pkey.hash_sum = pkey.hash_xor = 0;
- pkey.totloops = 0;
- v_prev = vtargetmap[(ml + mp->totloop -1)->v]; /* since it loops around, the prev of first is the last */
- for (j = 0; j < mp->totloop; j++, ml++) {
- v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */
- if (v_target == v_prev) {
- /* consecutive vertices in loop map to the same target: discard */
- /* but what about last to first ? */
- continue;
+ /* Consider the target of the loop's first vert */
+ v_target = vtargetmap[ml->v];
+ /* Now see if v_target belongs to a poly that shares all vertices with source poly,
+ * in same order, or reverse order */
+
+ for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) {
+ MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly);
+
+ if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) ||
+ cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1))
+ {
+ found = true;
+ break;
}
- pkey.hash_sum += v_target;
- pkey.hash_xor ^= v_target;
- pkey.totloops++;
- v_prev = v_target;
}
- if (BLI_gset_haskey(poly_gset, &pkey)) {
-
- /* There might be a poly that matches this one.
- * We could just leave it there and say there is, and do a "continue".
- * ... but we are checking whether there is an exact poly match.
- * It's not so costly in terms of CPU since it's very rare, just a lot of complex code.
- */
-
- /* Consider current loop again */
- ml = cddm->mloop + mp->loopstart;
- /* Consider the target of the loop's first vert */
- v_target = vtargetmap[ml->v];
- /* Now see if v_target belongs to a poly that shares all vertices with source poly,
- * in same order, or reverse order */
-
- for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) {
- MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly);
-
- if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) ||
- cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1))
- {
- found = true;
- break;
- }
- }
- if (found) {
- /* Current poly's vertices are mapped to a poly that is strictly identical */
- /* Current poly is dumped */
- continue;
- }
+ if (found) {
+ /* Current poly's vertices are mapped to a poly that is strictly identical */
+ /* Current poly is dumped */
+ continue;
}
}
}
@@ -3207,32 +3207,121 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
ml = cddm->mloop + mp->loopstart;
c = 0;
+ MLoop *last_valid_ml = NULL;
+ MLoop *first_valid_ml = NULL;
+ bool need_edge_from_last_valid_ml = false;
+ bool need_edge_to_first_valid_ml = false;
+ int created_edges = 0;
for (j = 0; j < mp->totloop; j++, ml++) {
- unsigned int v1, v2;
+ const uint mlv = (vtargetmap[ml->v] != -1) ? vtargetmap[ml->v] : ml->v;
+#ifndef NDEBUG
+ {
+ MLoop *next_ml = cddm->mloop + mp->loopstart + ((j + 1) % mp->totloop);
+ uint next_mlv = (vtargetmap[next_ml->v] != -1) ? vtargetmap[next_ml->v] : next_ml->v;
+ med = cddm->medge + ml->e;
+ uint v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
+ uint v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
+ BLI_assert((mlv == v1 && next_mlv == v2) || (mlv == v2 && next_mlv == v1));
+ }
+#endif
+ /* A loop is only valid if its matching edge is, and it's not reusing a vertex already used by this poly. */
+ if (LIKELY((newe[ml->e] != -1) && ((mv[mlv].flag & ME_VERT_TMP_TAG) == 0))) {
+ mv[mlv].flag |= ME_VERT_TMP_TAG;
+
+ if (UNLIKELY(last_valid_ml != NULL && need_edge_from_last_valid_ml)) {
+ /* We need to create a new edge between last valid loop and this one! */
+ void **val_p;
+
+ uint v1 = (vtargetmap[last_valid_ml->v] != -1) ? vtargetmap[last_valid_ml->v] : last_valid_ml->v;
+ uint v2 = mlv;
+ BLI_assert(v1 != v2);
+ if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) {
+ last_valid_ml->e = GET_INT_FROM_POINTER(*val_p);
+ }
+ else {
+ const int new_eidx = STACK_SIZE(medge);
+ STACK_PUSH(olde, olde[last_valid_ml->e]);
+ STACK_PUSH(medge, cddm->medge[last_valid_ml->e]);
+ medge[new_eidx].v1 = last_valid_ml->v;
+ medge[new_eidx].v2 = ml->v;
+ /* DO NOT change newe mapping, could break actual values due to some deleted original edges. */
+ *val_p = SET_INT_IN_POINTER(new_eidx);
+ created_edges++;
+
+ last_valid_ml->e = new_eidx;
+ }
+ need_edge_from_last_valid_ml = false;
+ }
- med = cddm->medge + ml->e;
- v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1;
- v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2;
- if (LIKELY(v1 != v2)) {
#ifdef USE_LOOPS
newl[j + mp->loopstart] = STACK_SIZE(mloop);
#endif
STACK_PUSH(oldl, j + mp->loopstart);
- STACK_PUSH(mloop, *ml);
+ last_valid_ml = STACK_PUSH_RET_PTR(mloop);
+ *last_valid_ml = *ml;
+ if (first_valid_ml == NULL) {
+ first_valid_ml = last_valid_ml;
+ }
c++;
+
+ /* We absolutely HAVE to handle edge index remapping here, otherwise potential newly created edges
+ * in that part of code make remapping later totally unreliable. */
+ BLI_assert(newe[ml->e] != -1);
+ last_valid_ml->e = newe[ml->e];
+ }
+ else {
+ if (last_valid_ml != NULL) {
+ need_edge_from_last_valid_ml = true;
+ }
+ else {
+ need_edge_to_first_valid_ml = true;
+ }
}
}
+ if (UNLIKELY(last_valid_ml != NULL && !ELEM(first_valid_ml, NULL, last_valid_ml) &&
+ (need_edge_to_first_valid_ml || need_edge_from_last_valid_ml)))
+ {
+ /* We need to create a new edge between last valid loop and first valid one! */
+ void **val_p;
+
+ uint v1 = (vtargetmap[last_valid_ml->v] != -1) ? vtargetmap[last_valid_ml->v] : last_valid_ml->v;
+ uint v2 = (vtargetmap[first_valid_ml->v] != -1) ? vtargetmap[first_valid_ml->v] : first_valid_ml->v;
+ BLI_assert(v1 != v2);
+ if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) {
+ last_valid_ml->e = GET_INT_FROM_POINTER(*val_p);
+ }
+ else {
+ const int new_eidx = STACK_SIZE(medge);
+ STACK_PUSH(olde, olde[last_valid_ml->e]);
+ STACK_PUSH(medge, cddm->medge[last_valid_ml->e]);
+ medge[new_eidx].v1 = last_valid_ml->v;
+ medge[new_eidx].v2 = first_valid_ml->v;
+ /* DO NOT change newe mapping, could break actual values due to some deleted original edges. */
+ *val_p = SET_INT_IN_POINTER(new_eidx);
+ created_edges++;
+
+ last_valid_ml->e = new_eidx;
+ }
+ need_edge_to_first_valid_ml = need_edge_from_last_valid_ml = false;
+ }
if (UNLIKELY(c == 0)) {
+ BLI_assert(created_edges == 0);
continue;
}
else if (UNLIKELY(c < 3)) {
STACK_DISCARD(oldl, c);
STACK_DISCARD(mloop, c);
+ if (created_edges > 0) {
+ for (j = STACK_SIZE(medge) - created_edges; j < STACK_SIZE(medge); j++) {
+ BLI_edgehash_remove(ehash, medge[j].v1, medge[j].v2, NULL);
+ }
+ STACK_DISCARD(olde, created_edges);
+ STACK_DISCARD(medge, created_edges);
+ }
continue;
}
-
mp_new = STACK_PUSH_RET_PTR(mpoly);
*mp_new = *mp;
mp_new->totloop = c;
@@ -3257,10 +3346,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
/*update edge indices and copy customdata*/
med = medge;
for (i = 0; i < cddm2->dm.numEdgeData; i++, med++) {
- if (newv[med->v1] != -1)
- med->v1 = newv[med->v1];
- if (newv[med->v2] != -1)
- med->v2 = newv[med->v2];
+ BLI_assert(newv[med->v1] != -1);
+ med->v1 = newv[med->v1];
+ BLI_assert(newv[med->v2] != -1);
+ med->v2 = newv[med->v2];
/* Can happen in case vtargetmap contains some double chains, we do not support that. */
BLI_assert(med->v1 != med->v2);
@@ -3271,11 +3360,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int
/*update loop indices and copy customdata*/
ml = mloop;
for (i = 0; i < cddm2->dm.numLoopData; i++, ml++) {
- if (newe[ml->e] != -1)
- ml->e = newe[ml->e];
- if (newv[ml->v] != -1)
- ml->v = newv[ml->v];
-
+ /* Edge remapping has already be done in main loop handling part above. */
+ BLI_assert(newv[ml->v] != -1);
+ ml->v = newv[ml->v];
+
CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
}
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 28ef3f6f248..ee0fde1ea61 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -869,12 +869,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
return 0;
}
- for ( i = 0; i < dm->getNumVerts(dm); i++) {
- if ((!(cloth->verts[i].flags & CLOTH_VERT_FLAG_PINNED)) && (cloth->verts[i].goal > ALMOST_ZERO)) {
- cloth_add_spring (clmd, i, i, 0.0, CLOTH_SPRING_TYPE_GOAL);
- }
- }
-
// init our solver
BPH_cloth_solver_init(ob, clmd);
@@ -944,37 +938,6 @@ BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1)
}
}
-// be careful: implicit solver has to be resettet when using this one!
-// --> only for implicit handling of this spring!
-int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type)
-{
- Cloth *cloth = clmd->clothObject;
- ClothSpring *spring = NULL;
-
- if (cloth) {
- // TODO: look if this spring is already there
-
- spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
-
- if (!spring)
- return 0;
-
- spring->ij = indexA;
- spring->kl = indexB;
- spring->restlen = restlength;
- spring->type = spring_type;
- spring->flags = 0;
- spring->stiffness = 0;
-
- cloth->numsprings++;
-
- BLI_linklist_prepend ( &cloth->springs, spring );
-
- return 1;
- }
- return 0;
-}
-
static void cloth_free_edgelist(LinkNodePair *edgelist, unsigned int mvert_num)
{
if (edgelist) {
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index b3a0895d063..ee0f904c3a6 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -130,7 +130,7 @@ void curvemapping_free(CurveMapping *cumap)
}
}
-void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
+void curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
{
int a;
@@ -146,7 +146,7 @@ void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
}
}
-CurveMapping *curvemapping_copy(CurveMapping *cumap)
+CurveMapping *curvemapping_copy(const CurveMapping *cumap)
{
if (cumap) {
CurveMapping *cumapn = MEM_dupallocN(cumap);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 58ad171ee20..07a6b304dff 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -790,7 +790,7 @@ static void default_get_tarmat(bConstraint *con, bConstraintOb *UNUSED(cob), bCo
ct = ctn; \
} \
} (void)0
-
+
/* --------- ChildOf Constraint ------------ */
static void childof_new_data(void *cdata)
@@ -4387,19 +4387,17 @@ static void transformcache_copy(bConstraint *con, bConstraint *srccon)
BLI_strncpy(dst->object_path, src->object_path, sizeof(dst->object_path));
dst->cache_file = src->cache_file;
- if (dst->cache_file) {
- id_us_plus(&dst->cache_file->id);
+#ifdef WITH_ALEMBIC
+ if (dst->reader) {
+ CacheReader_incref(dst->reader);
}
+#endif
}
static void transformcache_free(bConstraint *con)
{
bTransformCacheConstraint *data = con->data;
- if (data->cache_file) {
- id_us_min(&data->cache_file->id);
- }
-
if (data->reader) {
#ifdef WITH_ALEMBIC
CacheReader_free(data->reader);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 439abb1d593..8b32109cf2b 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -187,7 +187,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
return cu;
}
-Curve *BKE_curve_copy(Main *bmain, Curve *cu)
+Curve *BKE_curve_copy(Main *bmain, const Curve *cu)
{
Curve *cun;
int a;
@@ -468,7 +468,7 @@ void BKE_nurbList_free(ListBase *lb)
BLI_listbase_clear(lb);
}
-Nurb *BKE_nurb_duplicate(Nurb *nu)
+Nurb *BKE_nurb_duplicate(const Nurb *nu)
{
Nurb *newnu;
int len;
@@ -532,7 +532,7 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
return newnu;
}
-void BKE_nurbList_duplicate(ListBase *lb1, ListBase *lb2)
+void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2)
{
Nurb *nu, *nun;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index c9f0b8ec9ca..0939d35ed8d 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -33,14 +33,10 @@
/** \file blender/blenkernel/intern/customdata.c
* \ingroup bke
*/
-
-
-#include <math.h>
-#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
+#include "DNA_customdata_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_ID.h"
@@ -62,20 +58,16 @@
#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
-#include "data_transfer_intern.h"
-
#include "bmesh.h"
-#include <math.h>
-#include <string.h>
+/* only for customdata_data_transfer_interp_normal_normals */
+#include "data_transfer_intern.h"
/* number of layers to add when growing a CustomData object */
#define CUSTOMDATA_GROW 5
/* ensure typemap size is ok */
-BLI_STATIC_ASSERT(sizeof(((CustomData *)NULL)->typemap) /
- sizeof(((CustomData *)NULL)->typemap[0]) == CD_NUMTYPES,
- "size mismatch");
+BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)NULL)->typemap) == CD_NUMTYPES, "size mismatch");
/********************* Layer type information **********************/
@@ -805,18 +797,15 @@ static void layerInterp_mloopcol(
const float *sub_weights, int count, void *dest)
{
MLoopCol *mc = dest;
- int i;
- const float *sub_weight;
struct {
float a;
float r;
float g;
float b;
- } col;
- col.a = col.r = col.g = col.b = 0;
+ } col = {0};
- sub_weight = sub_weights;
- for (i = 0; i < count; ++i) {
+ const float *sub_weight = sub_weights;
+ for (int i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1;
const MLoopCol *src = sources[i];
if (sub_weights) {
@@ -833,19 +822,16 @@ static void layerInterp_mloopcol(
col.a += src->a * weight;
}
}
-
+
+
/* Subdivide smooth or fractal can cause problems without clamping
* although weights should also not cause this situation */
- CLAMP(col.a, 0.0f, 255.0f);
- CLAMP(col.r, 0.0f, 255.0f);
- CLAMP(col.g, 0.0f, 255.0f);
- CLAMP(col.b, 0.0f, 255.0f);
- /* delay writing to the destination incase dest is in sources */
- mc->r = (int)col.r;
- mc->g = (int)col.g;
- mc->b = (int)col.b;
- mc->a = (int)col.a;
+ /* also delay writing to the destination incase dest is in sources */
+ mc->r = CLAMPIS(iroundf(col.r), 0, 255);
+ mc->g = CLAMPIS(iroundf(col.g), 0, 255);
+ mc->b = CLAMPIS(iroundf(col.b), 0, 255);
+ mc->a = CLAMPIS(iroundf(col.a), 0, 255);
}
static int layerMaxNum_mloopcol(void)
@@ -1068,15 +1054,10 @@ static void layerInterp_mcol(
/* Subdivide smooth or fractal can cause problems without clamping
* although weights should also not cause this situation */
- CLAMP(col[j].a, 0.0f, 255.0f);
- CLAMP(col[j].r, 0.0f, 255.0f);
- CLAMP(col[j].g, 0.0f, 255.0f);
- CLAMP(col[j].b, 0.0f, 255.0f);
-
- mc[j].a = (int)col[j].a;
- mc[j].r = (int)col[j].r;
- mc[j].g = (int)col[j].g;
- mc[j].b = (int)col[j].b;
+ mc[j].a = CLAMPIS(iroundf(col[j].a), 0, 255);
+ mc[j].r = CLAMPIS(iroundf(col[j].r), 0, 255);
+ mc[j].g = CLAMPIS(iroundf(col[j].g), 0, 255);
+ mc[j].b = CLAMPIS(iroundf(col[j].b), 0, 255);
}
}
@@ -1963,11 +1944,15 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype,
bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
{
- const int n = index - CustomData_get_layer_index(data, type);
+ const int index_first = CustomData_get_layer_index(data, type);
+ const int n = index - index_first;
int i;
-
- if (index < 0)
+
+ BLI_assert(index >= index_first);
+ if ((index_first == -1) || (n < 0)) {
return false;
+ }
+ BLI_assert(data->layers[index].type == type);
customData_free_layer__internal(&data->layers[index], totelem);
@@ -2012,8 +1997,10 @@ bool CustomData_free_layer_active(CustomData *data, int type, int totelem)
void CustomData_free_layers(CustomData *data, int type, int totelem)
{
- while (CustomData_has_layer(data, type))
- CustomData_free_layer_active(data, type, totelem);
+ const int index = CustomData_get_layer_index(data, type);
+ while (CustomData_free_layer(data, type, totelem, index)) {
+ /* pass */
+ }
}
bool CustomData_has_layer(const CustomData *data, int type)
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 13b1aab5e1c..69baaf5e58a 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -76,7 +76,7 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
return defgroup;
}
-void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
+void defgroup_copy_list(ListBase *outbase, const ListBase *inbase)
{
bDeformGroup *defgroup, *defgroupn;
@@ -88,7 +88,7 @@ void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
}
}
-bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
+bDeformGroup *defgroup_duplicate(const bDeformGroup *ingroup)
{
bDeformGroup *outgroup;
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 678dc92a5f2..019e0df1623 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -3053,7 +3053,7 @@ void DAG_id_type_tag(Main *bmain, short idtype)
DAG_id_type_tag(bmain, ID_SCE);
}
- bmain->id_tag_update[BKE_idcode_to_index(idtype)] = 1;
+ atomic_fetch_and_or_uint8((uint8_t *)&bmain->id_tag_update[BKE_idcode_to_index(idtype)], 1);
}
int DAG_id_type_tagged(Main *bmain, short idtype)
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index f8a9d57f579..2a300cbe47b 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -167,10 +167,12 @@ void BKE_displist_normals_add(ListBase *lb)
if (dl->nors == NULL) {
dl->nors = MEM_callocN(sizeof(float) * 3, "dlnors");
- if (dl->verts[2] < 0.0f)
+ if (dl->flag & DL_BACK_CURVE) {
dl->nors[2] = -1.0f;
- else
+ }
+ else {
dl->nors[2] = 1.0f;
+ }
}
}
else if (dl->type == DL_SURF) {
@@ -469,6 +471,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
while (cont) {
+ int dl_flag_accum = 0;
cont = 0;
totvert = 0;
nextcol = 0;
@@ -514,6 +517,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
nextcol = 1;
}
}
+ dl_flag_accum |= dl->flag;
}
dl = dl->next;
}
@@ -526,6 +530,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj
if (tot) {
dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
dlnew->type = DL_INDEX3;
+ dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE));
dlnew->col = colnr;
dlnew->nr = totvert;
dlnew->parts = tot;
@@ -603,6 +608,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
dlnew->nr = dl->parts;
dlnew->parts = 1;
dlnew->type = DL_POLY;
+ dlnew->flag = DL_BACK_CURVE;
dlnew->col = dl->col;
dlnew->charidx = dl->charidx;
@@ -623,6 +629,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
dlnew->nr = dl->parts;
dlnew->parts = 1;
dlnew->type = DL_POLY;
+ dlnew->flag = DL_FRONT_CURVE;
dlnew->col = dl->col;
dlnew->charidx = dl->charidx;
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index c525e75b825..1db69d23607 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -1897,8 +1897,8 @@ static DerivedMesh *dynamicPaint_Modifier_apply(
/* apply weights into a vertex group, if doesnt exists add a new layer */
if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) {
- dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC,
- NULL, sData->total_points, surface->output_name);
+ dvert = CustomData_add_layer(&result->vertData, CD_MDEFORMVERT, CD_CALLOC,
+ NULL, sData->total_points);
}
if (defgrp_index != -1 && dvert) {
int i;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 2fffa0dea28..4a45bf1534c 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -149,6 +149,8 @@ static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm)
const float (*vertexCos)[3];
vertexCos = bmdm->vertexCos;
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos);
}
@@ -2053,20 +2055,25 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
/* layers are store per face for editmesh, we convert to a temporary
* data layer array in the derivedmesh when these are requested */
if (type == CD_MTFACE || type == CD_MCOL) {
- const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL;
- int index;
const char *bmdata;
char *data;
- index = CustomData_get_layer_index(&bm->pdata, type_from);
+ bool has_type_source = false;
+
+ if (type == CD_MTFACE) {
+ has_type_source = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
+ }
+ else {
+ has_type_source = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
+ }
- if (index != -1) {
+ if (has_type_source) {
/* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
BMLoop *(*looptris)[3] = bmdm->em->looptris;
const int size = CustomData_sizeof(type);
int i, j;
DM_add_tessface_layer(dm, type, CD_CALLOC, NULL);
- index = CustomData_get_layer_index(&dm->faceData, type);
+ const int index = CustomData_get_layer_index(&dm->faceData, type);
dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
data = datalayer = DM_get_tessface_data_layer(dm, type);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 4eee24b378f..38f5c00941c 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -986,19 +986,19 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected
*/
void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse)
{
-/*
- * Modifies the force on a particle according to its
- * relation with the effector object
- * Different kind of effectors include:
- * Forcefields: Gravity-like attractor
- * (force power is related to the inverse of distance to the power of a falloff value)
- * Vortex fields: swirling effectors
- * (particles rotate around Z-axis of the object. otherwise, same relation as)
- * (Forcefields, but this is not done through a force/acceleration)
- * Guide: particles on a path
- * (particles are guided along a curve bezier or old nurbs)
- * (is independent of other effectors)
- */
+ /*
+ * Modifies the force on a particle according to its
+ * relation with the effector object
+ * Different kind of effectors include:
+ * Forcefields: Gravity-like attractor
+ * (force power is related to the inverse of distance to the power of a falloff value)
+ * Vortex fields: swirling effectors
+ * (particles rotate around Z-axis of the object. otherwise, same relation as)
+ * (Forcefields, but this is not done through a force/acceleration)
+ * Guide: particles on a path
+ * (particles are guided along a curve bezier or old nurbs)
+ * (is independent of other effectors)
+ */
EffectorCache *eff;
EffectorData efd;
int p=0, tot = 1, step = 1;
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 7dbc43e0a32..db6c533ab57 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -126,7 +126,7 @@ void free_fcurves(ListBase *list)
/* ---------------------- Copy --------------------------- */
/* duplicate an F-Curve */
-FCurve *copy_fcurve(FCurve *fcu)
+FCurve *copy_fcurve(const FCurve *fcu)
{
FCurve *fcu_d;
@@ -1805,7 +1805,7 @@ void fcurve_free_driver(FCurve *fcu)
}
/* This makes a copy of the given driver */
-ChannelDriver *fcurve_copy_driver(ChannelDriver *driver)
+ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver)
{
ChannelDriver *ndriver;
@@ -1945,7 +1945,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const fl
BLI_mutex_unlock(&python_driver_lock);
}
#else /* WITH_PYTHON*/
- (void)evaltime;
+ UNUSED_VARS(anim_rna, evaltime);
#endif /* WITH_PYTHON*/
break;
}
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 2c301c04100..f1732ee7a9a 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -116,7 +116,7 @@ static void fcm_generator_free(FModifier *fcm)
MEM_freeN(data->coefficients);
}
-static void fcm_generator_copy(FModifier *fcm, FModifier *src)
+static void fcm_generator_copy(FModifier *fcm, const FModifier *src)
{
FMod_Generator *gen = (FMod_Generator *)fcm->data;
FMod_Generator *ogen = (FMod_Generator *)src->data;
@@ -386,7 +386,7 @@ static void fcm_envelope_free(FModifier *fcm)
MEM_freeN(env->data);
}
-static void fcm_envelope_copy(FModifier *fcm, FModifier *src)
+static void fcm_envelope_copy(FModifier *fcm, const FModifier *src)
{
FMod_Envelope *env = (FMod_Envelope *)fcm->data;
FMod_Envelope *oenv = (FMod_Envelope *)src->data;
@@ -877,7 +877,7 @@ static void fcm_python_new_data(void *mdata)
data->prop->type = IDP_GROUP;
}
-static void fcm_python_copy(FModifier *fcm, FModifier *src)
+static void fcm_python_copy(FModifier *fcm, const FModifier *src)
{
FMod_Python *pymod = (FMod_Python *)fcm->data;
FMod_Python *opymod = (FMod_Python *)src->data;
@@ -1040,7 +1040,7 @@ static void fmods_init_typeinfo(void)
/* This function should be used for getting the appropriate type-info when only
* a F-Curve modifier type is known
*/
-const FModifierTypeInfo *get_fmodifier_typeinfo(int type)
+const FModifierTypeInfo *get_fmodifier_typeinfo(const int type)
{
/* initialize the type-info list? */
if (FMI_INIT) {
@@ -1065,7 +1065,7 @@ const FModifierTypeInfo *get_fmodifier_typeinfo(int type)
/* This function should always be used to get the appropriate type-info, as it
* has checks which prevent segfaults in some weird cases.
*/
-const FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm)
+const FModifierTypeInfo *fmodifier_get_typeinfo(const FModifier *fcm)
{
/* only return typeinfo for valid modifiers */
if (fcm)
@@ -1117,7 +1117,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type)
}
/* Make a copy of the specified F-Modifier */
-FModifier *copy_fmodifier(FModifier *src)
+FModifier *copy_fmodifier(const FModifier *src)
{
const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src);
FModifier *dst;
@@ -1142,7 +1142,7 @@ FModifier *copy_fmodifier(FModifier *src)
}
/* Duplicate all of the F-Modifiers in the Modifier stacks */
-void copy_fmodifiers(ListBase *dst, ListBase *src)
+void copy_fmodifiers(ListBase *dst, const ListBase *src)
{
FModifier *fcm, *srcfcm;
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 580842fe176..401fed74c52 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -695,10 +695,14 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
if (ef->selboxes)
MEM_freeN(ef->selboxes);
- if (BKE_vfont_select_get(ob, &selstart, &selend))
- ef->selboxes = MEM_callocN((selend - selstart + 1) * sizeof(EditFontSelBox), "font selboxes");
- else
+ if (BKE_vfont_select_get(ob, &selstart, &selend)) {
+ ef->selboxes_len = (selend - selstart) + 1;
+ ef->selboxes = MEM_callocN(ef->selboxes_len * sizeof(EditFontSelBox), "font selboxes");
+ }
+ else {
+ ef->selboxes_len = 0;
ef->selboxes = NULL;
+ }
selboxes = ef->selboxes;
}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 30fc8915d46..758438bb051 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -754,7 +754,7 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
}
/* make a copy of a given gpencil datablock */
-bGPdata *BKE_gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_copy)
+bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
{
const bGPDlayer *gpl_src;
bGPDlayer *gpl_dst;
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 9b011dbb003..932f41ac4ba 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -80,6 +80,8 @@ Group *BKE_group_add(Main *bmain, const char *name)
Group *group;
group = BKE_libblock_alloc(bmain, ID_GR, name);
+ id_us_min(&group->id);
+ id_us_ensure_real(&group->id);
group->layer = (1 << 20) - 1;
group->preview = NULL;
@@ -87,7 +89,7 @@ Group *BKE_group_add(Main *bmain, const char *name)
return group;
}
-Group *BKE_group_copy(Main *bmain, Group *group)
+Group *BKE_group_copy(Main *bmain, const Group *group)
{
Group *groupn;
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 7669c4ba112..bccf9307912 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -204,7 +204,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv)
}
}
-PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
+PreviewImage *BKE_previewimg_copy(const PreviewImage *prv)
{
PreviewImage *prv_img = NULL;
int i;
@@ -222,7 +222,7 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
}
/** Duplicate preview image from \a id and clear icon_id, to be used by datablock copy functions. */
-void BKE_previewimg_id_copy(ID *new_id, ID *old_id)
+void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
{
PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id);
PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id);
@@ -239,7 +239,7 @@ void BKE_previewimg_id_copy(ID *new_id, ID *old_id)
}
}
-PreviewImage **BKE_previewimg_id_get_p(ID *id)
+PreviewImage **BKE_previewimg_id_get_p(const ID *id)
{
switch (GS(id->name)) {
#define ID_PRV_CASE(id_code, id_struct) case id_code: { return &((id_struct *)id)->preview; } ((void)0)
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index b2641b110f8..e98181be444 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -117,31 +117,35 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array)
return narray;
}
-void IDP_FreeIDPArray(IDProperty *prop)
+static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user)
{
int i;
BLI_assert(prop->type == IDP_IDPARRAY);
for (i = 0; i < prop->len; i++)
- IDP_FreeProperty(GETPROP(prop, i));
+ IDP_FreeProperty_ex(GETPROP(prop, i), do_id_user);
if (prop->data.pointer)
MEM_freeN(prop->data.pointer);
}
-/*shallow copies item*/
+/* shallow copies item */
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
{
IDProperty *old;
BLI_assert(prop->type == IDP_IDPARRAY);
+ if (index >= prop->len || index < 0)
+ return;
+
old = GETPROP(prop, index);
- if (index >= prop->len || index < 0) return;
- if (item != old) IDP_FreeProperty(old);
-
- memcpy(GETPROP(prop, index), item, sizeof(IDProperty));
+ if (item != old) {
+ IDP_FreeProperty(old);
+
+ memcpy(old, item, sizeof(IDProperty));
+ }
}
IDProperty *IDP_GetIndexArray(IDProperty *prop, int index)
@@ -433,22 +437,24 @@ void IDP_FreeString(IDProperty *prop)
/* -------------------------------------------------------------------- */
-/* ID Type (not in use yet) */
+/* ID Type */
-/** \name IDProperty ID API (unused)
+/** \name IDProperty ID API
* \{ */
-void IDP_LinkID(IDProperty *prop, ID *id)
-{
- if (prop->data.pointer)
- id_us_min(((ID *)prop->data.pointer));
- prop->data.pointer = id;
- id_us_plus(id);
-}
-void IDP_UnlinkID(IDProperty *prop)
+static IDProperty *IDP_CopyID(const IDProperty *prop)
{
- id_us_min(((ID *)prop->data.pointer));
+ IDProperty *newp;
+
+ BLI_assert(prop->type == IDP_ID);
+ newp = idp_generic_copy(prop);
+
+ newp->data.pointer = prop->data.pointer;
+ id_us_plus(IDP_Id(newp));
+
+ return newp;
}
+
/** \} */
@@ -499,14 +505,9 @@ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
break;
default:
{
- IDProperty *tmp = other;
- IDProperty *copy = IDP_CopyProperty(prop);
-
- BLI_insertlinkafter(&dest->data.group, other, copy);
- BLI_remlink(&dest->data.group, tmp);
-
- IDP_FreeProperty(tmp);
- MEM_freeN(tmp);
+ BLI_insertlinkreplace(&dest->data.group, other, IDP_CopyProperty(prop));
+ IDP_FreeProperty(other);
+ MEM_freeN(other);
break;
}
}
@@ -526,11 +527,9 @@ void IDP_SyncGroupTypes(IDProperty *dst, const IDProperty *src, const bool do_ar
if ((prop_dst->type != prop_src->type || prop_dst->subtype != prop_src->subtype) ||
(do_arraylen && ELEM(prop_dst->type, IDP_ARRAY, IDP_IDPARRAY) && (prop_src->len != prop_dst->len)))
{
- IDP_FreeFromGroup(dst, prop_dst);
- prop_dst = IDP_CopyProperty(prop_src);
-
- dst->len++;
- BLI_insertlinkbefore(&dst->data.group, prop_dst_next, prop_dst);
+ BLI_insertlinkreplace(&dst->data.group, prop_dst, IDP_CopyProperty(prop_src));
+ IDP_FreeProperty(prop_dst);
+ MEM_freeN(prop_dst);
}
else if (prop_dst->type == IDP_GROUP) {
IDP_SyncGroupTypes(prop_dst, prop_src, do_arraylen);
@@ -555,11 +554,7 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
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)) {
- IDProperty *copy = IDP_CopyProperty(prop);
-
- BLI_insertlinkafter(&dest->data.group, loop, copy);
-
- BLI_remlink(&dest->data.group, loop);
+ BLI_insertlinkreplace(&dest->data.group, loop, IDP_CopyProperty(prop));
IDP_FreeProperty(loop);
MEM_freeN(loop);
break;
@@ -586,9 +581,7 @@ void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop
BLI_assert(prop_exist == IDP_GetPropertyFromGroup(group, prop->name));
if ((prop_exist = IDP_GetPropertyFromGroup(group, prop->name))) {
- BLI_insertlinkafter(&group->data.group, prop_exist, prop);
-
- BLI_remlink(&group->data.group, prop_exist);
+ BLI_insertlinkreplace(&group->data.group, prop_exist, prop);
IDP_FreeProperty(prop_exist);
MEM_freeN(prop_exist);
}
@@ -719,13 +712,13 @@ IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, con
* This is because all ID Property freeing functions free only direct data (not the ID Property
* struct itself), but for Groups the child properties *are* considered
* direct data. */
-static void IDP_FreeGroup(IDProperty *prop)
+static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user)
{
IDProperty *loop;
BLI_assert(prop->type == IDP_GROUP);
for (loop = prop->data.group.first; loop; loop = loop->next) {
- IDP_FreeProperty(loop);
+ IDP_FreeProperty_ex(loop, do_id_user);
}
BLI_freelistN(&prop->data.group);
}
@@ -742,12 +735,51 @@ IDProperty *IDP_CopyProperty(const IDProperty *prop)
switch (prop->type) {
case IDP_GROUP: return IDP_CopyGroup(prop);
case IDP_STRING: return IDP_CopyString(prop);
+ case IDP_ID: return IDP_CopyID(prop);
case IDP_ARRAY: return IDP_CopyArray(prop);
case IDP_IDPARRAY: return IDP_CopyIDPArray(prop);
default: return idp_generic_copy(prop);
}
}
+/* Updates ID pointers after an object has been copied */
+/* TODO Nuke this once its only user has been correctly converted to use generic ID management from BKE_library! */
+void IDP_RelinkProperty(struct IDProperty *prop)
+{
+ if (!prop)
+ return;
+
+ switch (prop->type) {
+ case IDP_GROUP:
+ {
+ for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) {
+ IDP_RelinkProperty(loop);
+ }
+ break;
+ }
+ case IDP_IDPARRAY:
+ {
+ IDProperty *idp_array = IDP_Array(prop);
+ for (int i = 0; i < prop->len; i++) {
+ IDP_RelinkProperty(&idp_array[i]);
+ }
+ break;
+ }
+ case IDP_ID:
+ {
+ ID *id = IDP_Id(prop);
+ if (id && id->newid) {
+ id_us_min(IDP_Id(prop));
+ prop->data.pointer = id->newid;
+ id_us_plus(IDP_Id(prop));
+ }
+ break;
+ }
+ default:
+ break; /* Nothing to do for other IDProp types. */
+ }
+}
+
/**
* Get the Group property that contains the id properties for ID id. Set create_if_needed
* to create the Group property and attach it to id if it doesn't exist; otherwise
@@ -844,6 +876,8 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
return false;
return true;
}
+ case IDP_ID:
+ return (IDP_Id(prop1) == IDP_Id(prop2));
default:
/* should never get here */
BLI_assert(0);
@@ -867,17 +901,19 @@ bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
* The union is simple to use; see the top of this header file for its definition.
* An example of using this function:
*
- * IDPropertyTemplate val;
- * IDProperty *group, *idgroup, *color;
- * group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template.
+ * \code{.c}
+ * IDPropertyTemplate val;
+ * IDProperty *group, *idgroup, *color;
+ * group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template.
*
- * val.array.len = 4
- * val.array.type = IDP_FLOAT;
- * color = IDP_New(IDP_ARRAY, val, "color1");
+ * val.array.len = 4
+ * val.array.type = IDP_FLOAT;
+ * color = IDP_New(IDP_ARRAY, val, "color1");
*
- * idgroup = IDP_GetProperties(some_id, 1);
- * IDP_AddToGroup(idgroup, color);
- * IDP_AddToGroup(idgroup, group);
+ * idgroup = IDP_GetProperties(some_id, 1);
+ * IDP_AddToGroup(idgroup, color);
+ * IDP_AddToGroup(idgroup, group);
+ * \endcode
*
* Note that you MUST either attach the id property to an id property group with
* IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
@@ -897,7 +933,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
*(float *)&prop->data.val = val->f;
break;
case IDP_DOUBLE:
- prop = MEM_callocN(sizeof(IDProperty), "IDProperty float");
+ prop = MEM_callocN(sizeof(IDProperty), "IDProperty double");
*(double *)&prop->data.val = val->d;
break;
case IDP_ARRAY:
@@ -917,6 +953,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
prop->len = prop->totallen = val->array.len;
break;
}
+ printf("%s: bad array type.\n", __func__);
return NULL;
}
case IDP_STRING:
@@ -963,6 +1000,14 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
/* heh I think all needed values are set properly by calloc anyway :) */
break;
}
+ case IDP_ID:
+ {
+ prop = MEM_callocN(sizeof(IDProperty), "IDProperty datablock");
+ prop->data.pointer = (void *)val->id;
+ prop->type = IDP_ID;
+ id_us_plus(IDP_Id(prop));
+ break;
+ }
default:
{
prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
@@ -977,11 +1022,10 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
}
/**
- * \note this will free all child properties of list arrays and groups!
- * Also, note that this does NOT unlink anything! Plus it doesn't free
- * the actual struct IDProperty struct either.
+ * \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
+ * But it does not free the actual IDProperty struct itself.
*/
-void IDP_FreeProperty(IDProperty *prop)
+void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user)
{
switch (prop->type) {
case IDP_ARRAY:
@@ -991,14 +1035,24 @@ void IDP_FreeProperty(IDProperty *prop)
IDP_FreeString(prop);
break;
case IDP_GROUP:
- IDP_FreeGroup(prop);
+ IDP_FreeGroup(prop, do_id_user);
break;
case IDP_IDPARRAY:
- IDP_FreeIDPArray(prop);
+ IDP_FreeIDPArray(prop, do_id_user);
+ break;
+ case IDP_ID:
+ if (do_id_user) {
+ id_us_min(IDP_Id(prop));
+ }
break;
}
}
+void IDP_FreeProperty(IDProperty *prop)
+{
+ IDP_FreeProperty_ex(prop, true);
+}
+
void IDP_ClearProperty(IDProperty *prop)
{
IDP_FreeProperty(prop);
@@ -1006,18 +1060,4 @@ void IDP_ClearProperty(IDProperty *prop)
prop->len = prop->totallen = 0;
}
-/**
- * Unlinks any struct IDProperty<->ID linkage that might be going on.
- *
- * \note currently unused
- */
-void IDP_UnlinkProperty(IDProperty *prop)
-{
- switch (prop->type) {
- case IDP_ID:
- IDP_UnlinkID(prop);
- break;
- }
-}
-
/** \} */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 318f6480aaf..abe08def197 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -62,6 +62,7 @@
#include "BLI_blenlib.h"
#include "BLI_math_vector.h"
+#include "BLI_mempool.h"
#include "BLI_threads.h"
#include "BLI_timecode.h" /* for stamp timecode format */
#include "BLI_utildefines.h"
@@ -433,7 +434,7 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
}
/* empty image block, of similar type and filename */
-Image *BKE_image_copy(Main *bmain, Image *ima)
+Image *BKE_image_copy(Main *bmain, const Image *ima)
{
Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type);
@@ -1238,7 +1239,7 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file)
switch (imtype) {
case R_IMF_IMTYPE_BMP:
if (write_file) break;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case R_IMF_IMTYPE_TARGA:
case R_IMF_IMTYPE_RAWTGA:
case R_IMF_IMTYPE_IRIS:
@@ -2216,8 +2217,10 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf)
ibuf->foptions.flag |= OPENEXR_HALF;
ibuf->foptions.flag |= (imf->exr_codec & OPENEXR_COMPRESS);
- if (!(imf->flag & R_IMF_FLAG_ZBUF))
- ibuf->zbuf_float = NULL; /* signal for exr saving */
+ if (!(imf->flag & R_IMF_FLAG_ZBUF)) {
+ /* Signal for exr saving. */
+ IMB_freezbuffloatImBuf(ibuf);
+ }
}
#endif
@@ -2737,7 +2740,6 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
}
}
-#define PASSTYPE_UNSET -1
/* return renderpass for a given pass index and active view */
/* fallback to available if there are missing passes for active view */
static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex)
@@ -2746,7 +2748,7 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const
RenderPass *rpass;
int rp_index = 0;
- int rp_passtype = PASSTYPE_UNSET;
+ const char *rp_name = "";
for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) {
if (rp_index == pass) {
@@ -2756,12 +2758,12 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const
break;
}
else {
- rp_passtype = rpass->passtype;
+ rp_name = rpass->name;
}
}
/* multiview */
- else if ((rp_passtype != PASSTYPE_UNSET) &&
- (rpass->passtype == rp_passtype) &&
+ else if (rp_name[0] &&
+ STREQ(rpass->name, rp_name) &&
(rpass->view_id == view))
{
rpass_ret = rpass;
@@ -2781,7 +2783,6 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const
return rpass_ret;
}
-#undef PASSTYPE_UNSET
/* if layer or pass changes, we need an index for the imbufs list */
/* note it is called for rendered results, but it doesnt use the index! */
@@ -2862,7 +2863,7 @@ bool BKE_image_is_stereo(Image *ima)
{
return BKE_image_is_multiview(ima) &&
(BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
- BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)));
+ BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)));
}
static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
@@ -3751,7 +3752,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
for (rpass = rl->passes.first; rpass; rpass = rpass->next)
- if (rpass->passtype == SCE_PASS_Z)
+ if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview)
rectz = rpass->rect;
}
}
@@ -4132,33 +4133,32 @@ typedef struct ImagePoolEntry {
typedef struct ImagePool {
ListBase image_buffers;
+ BLI_mempool *memory_pool;
} ImagePool;
ImagePool *BKE_image_pool_new(void)
{
ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
+ pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolEntry), 0, 128, BLI_MEMPOOL_NOP);
return pool;
}
void BKE_image_pool_free(ImagePool *pool)
{
- ImagePoolEntry *entry, *next_entry;
-
- /* use single lock to dereference all the image buffers */
+ /* Use single lock to dereference all the image buffers. */
BLI_spin_lock(&image_spin);
-
- for (entry = pool->image_buffers.first; entry; entry = next_entry) {
- next_entry = entry->next;
-
- if (entry->ibuf)
+ for (ImagePoolEntry *entry = pool->image_buffers.first;
+ entry != NULL;
+ entry = entry->next)
+ {
+ if (entry->ibuf) {
IMB_freeImBuf(entry->ibuf);
-
- MEM_freeN(entry);
+ }
}
-
BLI_spin_unlock(&image_spin);
+ BLI_mempool_destroy(pool->memory_pool);
MEM_freeN(pool);
}
@@ -4210,7 +4210,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
ibuf = image_acquire_ibuf(ima, iuser, NULL);
- entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry");
+ entry = BLI_mempool_alloc(pool->memory_pool);
entry->image = ima;
entry->frame = frame;
entry->index = index;
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 8a7c1dd2833..98b251294ae 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -151,7 +151,7 @@ Key *BKE_key_add(ID *id) /* common function */
return key;
}
-Key *BKE_key_copy(Main *bmain, Key *key)
+Key *BKE_key_copy(Main *bmain, const Key *key)
{
Key *keyn;
KeyBlock *kbn, *kb;
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 69a2067f4e6..2242ba379fb 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -116,7 +116,7 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name)
return la;
}
-Lamp *BKE_lamp_copy(Main *bmain, Lamp *la)
+Lamp *BKE_lamp_copy(Main *bmain, const Lamp *la)
{
Lamp *lan;
int a;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index b0671f33094..c9d7dddf25a 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -67,7 +67,7 @@
#include "BKE_deform.h"
-/* Workaround for cyclic depenndnecy with curves.
+/* Workaround for cyclic dependency with curves.
* In such case curve_cache might not be ready yet,
*/
#define CYCLIC_DEPENDENCY_WORKAROUND
@@ -277,7 +277,7 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name)
return lt;
}
-Lattice *BKE_lattice_copy(Main *bmain, Lattice *lt)
+Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt)
{
Lattice *ltn;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index e380b5c17e0..2ea7342ff34 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -133,6 +133,12 @@
#include "atomic_ops.h"
+//#define DEBUG_TIME
+
+#ifdef DEBUG_TIME
+# include "PIL_time_utildefines.h"
+#endif
+
/* GS reads the memory pointed at in a specific ordering.
* only use this definition, makes little and big endian systems
* work fine, in conjunction with MAKE_ID */
@@ -301,7 +307,7 @@ void BKE_id_expand_local(Main *bmain, ID *id)
/**
* Ensure new (copied) ID is fully made local.
*/
-void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id)
+void BKE_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id)
{
if (ID_IS_LINKED_DATABLOCK(old_id)) {
BKE_id_expand_local(bmain, new_id);
@@ -482,7 +488,7 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
* Invokes the appropriate copy method for the block and returns the result in
* newid, unless test. Returns true if the block can be copied.
*/
-bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
+bool id_copy(Main *bmain, const ID *id, ID **newid, bool test)
{
if (!test) {
*newid = NULL;
@@ -852,118 +858,72 @@ int set_listbasepointers(Main *main, ListBase **lb)
* **************************** */
/**
+ * Get allocation size fo a given datablock type and optionally allocation name.
+ */
+size_t BKE_libblock_get_alloc_info(short type, const char **name)
+{
+#define CASE_RETURN(id_code, type) \
+ case id_code: \
+ do { \
+ if (name != NULL) { \
+ *name = #type; \
+ } \
+ return sizeof(type); \
+ } while(0)
+
+ switch ((ID_Type)type) {
+ CASE_RETURN(ID_SCE, Scene);
+ CASE_RETURN(ID_LI, Library);
+ CASE_RETURN(ID_OB, Object);
+ CASE_RETURN(ID_ME, Mesh);
+ CASE_RETURN(ID_CU, Curve);
+ CASE_RETURN(ID_MB, MetaBall);
+ CASE_RETURN(ID_MA, Material);
+ CASE_RETURN(ID_TE, Tex);
+ CASE_RETURN(ID_IM, Image);
+ CASE_RETURN(ID_LT, Lattice);
+ CASE_RETURN(ID_LA, Lamp);
+ CASE_RETURN(ID_CA, Camera);
+ CASE_RETURN(ID_IP, Ipo);
+ CASE_RETURN(ID_KE, Key);
+ CASE_RETURN(ID_WO, World);
+ CASE_RETURN(ID_SCR, bScreen);
+ CASE_RETURN(ID_VF, VFont);
+ CASE_RETURN(ID_TXT, Text);
+ CASE_RETURN(ID_SPK, Speaker);
+ CASE_RETURN(ID_SO, bSound);
+ CASE_RETURN(ID_GR, Group);
+ CASE_RETURN(ID_AR, bArmature);
+ CASE_RETURN(ID_AC, bAction);
+ CASE_RETURN(ID_NT, bNodeTree);
+ CASE_RETURN(ID_BR, Brush);
+ CASE_RETURN(ID_PA, ParticleSettings);
+ CASE_RETURN(ID_WM, wmWindowManager);
+ CASE_RETURN(ID_GD, bGPdata);
+ CASE_RETURN(ID_MC, MovieClip);
+ CASE_RETURN(ID_MSK, Mask);
+ CASE_RETURN(ID_LS, FreestyleLineStyle);
+ CASE_RETURN(ID_PAL, Palette);
+ CASE_RETURN(ID_PC, PaintCurve);
+ CASE_RETURN(ID_CF, CacheFile);
+ }
+ return 0;
+#undef CASE_RETURN
+}
+
+/**
* Allocates and returns memory of the right size for the specified block type,
* initialized to zero.
*/
void *BKE_libblock_alloc_notest(short type)
{
- ID *id = NULL;
-
- switch ((ID_Type)type) {
- case ID_SCE:
- id = MEM_callocN(sizeof(Scene), "scene");
- break;
- case ID_LI:
- id = MEM_callocN(sizeof(Library), "library");
- break;
- case ID_OB:
- id = MEM_callocN(sizeof(Object), "object");
- break;
- case ID_ME:
- id = MEM_callocN(sizeof(Mesh), "mesh");
- break;
- case ID_CU:
- id = MEM_callocN(sizeof(Curve), "curve");
- break;
- case ID_MB:
- id = MEM_callocN(sizeof(MetaBall), "mball");
- break;
- case ID_MA:
- id = MEM_callocN(sizeof(Material), "mat");
- break;
- case ID_TE:
- id = MEM_callocN(sizeof(Tex), "tex");
- break;
- case ID_IM:
- id = MEM_callocN(sizeof(Image), "image");
- break;
- case ID_LT:
- id = MEM_callocN(sizeof(Lattice), "latt");
- break;
- case ID_LA:
- id = MEM_callocN(sizeof(Lamp), "lamp");
- break;
- case ID_CA:
- id = MEM_callocN(sizeof(Camera), "camera");
- break;
- case ID_IP:
- id = MEM_callocN(sizeof(Ipo), "ipo");
- break;
- case ID_KE:
- id = MEM_callocN(sizeof(Key), "key");
- break;
- case ID_WO:
- id = MEM_callocN(sizeof(World), "world");
- break;
- case ID_SCR:
- id = MEM_callocN(sizeof(bScreen), "screen");
- break;
- case ID_VF:
- id = MEM_callocN(sizeof(VFont), "vfont");
- break;
- case ID_TXT:
- id = MEM_callocN(sizeof(Text), "text");
- break;
- case ID_SPK:
- id = MEM_callocN(sizeof(Speaker), "speaker");
- break;
- case ID_SO:
- id = MEM_callocN(sizeof(bSound), "sound");
- break;
- case ID_GR:
- id = MEM_callocN(sizeof(Group), "group");
- break;
- case ID_AR:
- id = MEM_callocN(sizeof(bArmature), "armature");
- break;
- case ID_AC:
- id = MEM_callocN(sizeof(bAction), "action");
- break;
- case ID_NT:
- id = MEM_callocN(sizeof(bNodeTree), "nodetree");
- break;
- case ID_BR:
- id = MEM_callocN(sizeof(Brush), "brush");
- break;
- case ID_PA:
- id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings");
- break;
- case ID_WM:
- id = MEM_callocN(sizeof(wmWindowManager), "Window manager");
- break;
- case ID_GD:
- id = MEM_callocN(sizeof(bGPdata), "Grease Pencil");
- break;
- case ID_MC:
- id = MEM_callocN(sizeof(MovieClip), "Movie Clip");
- break;
- case ID_MSK:
- id = MEM_callocN(sizeof(Mask), "Mask");
- break;
- case ID_LS:
- id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style");
- break;
- case ID_PAL:
- id = MEM_callocN(sizeof(Palette), "Palette");
- break;
- case ID_PC:
- id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
- break;
- case ID_CF:
- id = MEM_callocN(sizeof(CacheFile), "Cache File");
- break;
+ const char *name;
+ size_t size = BKE_libblock_get_alloc_info(type, &name);
+ if (size != 0) {
+ return MEM_callocN(size, name);
}
- return id;
+ BLI_assert(!"Request to allocate unknown data type");
+ return NULL;
}
/**
@@ -1132,7 +1092,7 @@ void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action)
}
/* used everywhere in blenkernel */
-void *BKE_libblock_copy(Main *bmain, ID *id)
+void *BKE_libblock_copy(Main *bmain, const ID *id)
{
ID *idn;
size_t idn_len;
@@ -1154,7 +1114,7 @@ void *BKE_libblock_copy(Main *bmain, ID *id)
return idn;
}
-void *BKE_libblock_copy_nolib(ID *id, const bool do_action)
+void *BKE_libblock_copy_nolib(const ID *id, const bool do_action)
{
ID *idn;
size_t idn_len;
@@ -1716,10 +1676,19 @@ static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRela
for (; entry != NULL; entry = entry->next) {
ID *par_id = (ID *)entry->id_pointer; /* used_to_user stores ID pointer, not pointer to ID pointer... */
- /* Shapekeys are considered 'private' to their owner ID here, and never tagged (since they cannot be linked),
- * so we have to switch effective parent to their owner. */
- if (GS(par_id->name) == ID_KE) {
- par_id = ((Key *)par_id)->from;
+ /* Our oh-so-beloved 'from' pointers... */
+ if (entry->usage_flag & IDWALK_CB_LOOPBACK) {
+ /* We totally disregard Object->proxy_from 'usage' here, this one would only generate fake positives. */
+ if (GS(par_id->name) == ID_OB) {
+ BLI_assert(((Object *)par_id)->proxy_from == (Object *)id);
+ continue;
+ }
+
+ /* Shapekeys are considered 'private' to their owner ID here, and never tagged (since they cannot be linked),
+ * so we have to switch effective parent to their owner. */
+ if (GS(par_id->name) == ID_KE) {
+ par_id = ((Key *)par_id)->from;
+ }
}
if (par_id->lib == NULL) {
@@ -1777,9 +1746,18 @@ void BKE_library_make_local(
LinkNode *copied_ids = NULL;
MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__);
+ GSet *done_ids = BLI_gset_ptr_new(__func__);
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(make_local);
+#endif
+
BKE_main_relations_create(bmain);
- GSet *done_ids = BLI_gset_ptr_new(__func__);
+#ifdef DEBUG_TIME
+ printf("Pre-compute current ID relations: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
/* Step 1: Detect datablocks to make local. */
for (a = set_listbasepointers(bmain, lbarray); a--; ) {
@@ -1830,6 +1808,11 @@ void BKE_library_make_local(
}
}
+#ifdef DEBUG_TIME
+ printf("Step 1: Detect datablocks to make local: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
/* Step 2: Check which datablocks we can directly make local (because they are only used by already, or future,
* local data), others will need to be duplicated. */
GSet *loop_tags = BLI_gset_ptr_new(__func__);
@@ -1843,6 +1826,11 @@ void BKE_library_make_local(
/* Next step will most likely add new IDs, better to get rid of this mapping now. */
BKE_main_relations_free(bmain);
+#ifdef DEBUG_TIME
+ printf("Step 2: Check which datablocks we can directly make local: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
/* Step 3: Make IDs local, either directly (quick and simple), or using generic process,
* which involves more complex checks and might instead create a local copy of original linked ID. */
for (LinkNode *it = todo_ids, *it_next; it; it = it_next) {
@@ -1883,11 +1871,16 @@ void BKE_library_make_local(
}
}
+#ifdef DEBUG_TIME
+ printf("Step 3: Make IDs local: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
/* At this point, we are done with directly made local IDs. Now we have to handle duplicated ones, since their
* remaining linked original counterpart may not be needed anymore... */
todo_ids = NULL;
- /* Step 4: We have to remap local usages of old (linked) ID to new (local) id in a separated loop,
+ /* Step 4: We have to remap local usages of old (linked) ID to new (local) ID in a separated loop,
* as lbarray ordering is not enough to ensure us we did catch all dependencies
* (e.g. if making local a parent object before its child...). See T48907. */
/* TODO This is now the biggest step by far (in term of processing time). We may be able to gain here by
@@ -1911,6 +1904,11 @@ void BKE_library_make_local(
}
}
+#ifdef DEBUG_TIME
+ printf("Step 4: Remap local usages of old (linked) ID to new (local) ID: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
/* Note: Keeping both version of the code (old one being safer, since it still has checks against unused IDs)
* for now, we can remove old one once it has been tested for some time in master... */
#if 1
@@ -1955,6 +1953,12 @@ void BKE_library_make_local(
}
}
}
+
+#ifdef DEBUG_TIME
+ printf("Step 5: Proxy 'remapping' hack: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
#else
LinkNode *linked_loop_candidates = NULL;
@@ -2033,6 +2037,11 @@ void BKE_library_make_local(
}
}
+#ifdef DEBUG_TIME
+ printf("Step 5: Remove linked datablocks that have been copied and ended fully localized: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
/* Step 6: Try to find circle dependencies between indirectly-linked-only datablocks.
* Those are fake 'usages' that prevent their deletion. See T49775 for nice ugly case. */
BKE_library_unused_linked_data_set_tag(bmain, false);
@@ -2069,10 +2078,38 @@ void BKE_library_make_local(
it->link = NULL;
}
}
+
+#ifdef DEBUG_TIME
+ printf("Step 6: Try to find circle dependencies between indirectly-linked-only datablocks: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
+#endif
+
+#endif
+
+ /* This is probably more of a hack than something we should do here, but...
+ * Issue is, the whole copying + remapping done in complex cases above may leave pose channels of armatures
+ * in complete invalid state (more precisely, the bone pointers of the pchans - very crappy cross-datablocks
+ * relationship), se we tag it to be fully recomputed, but this does not seems to be enough in some cases,
+ * and evaluation code ends up trying to evaluate a not-yet-updated armature object's deformations.
+ * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL && ob->pose->flag & POSE_RECALC) {
+ BKE_pose_rebuild(ob, ob->data);
+ }
+ }
+
+#ifdef DEBUG_TIME
+ printf("Hack: Forcefully rebuild armature object poses: Done.\n");
+ TIMEIT_VALUE_PRINT(make_local);
#endif
BKE_main_id_clear_newpoins(bmain);
BLI_memarena_free(linklist_mem);
+
+#ifdef DEBUG_TIME
+ printf("Cleanup and finish: Done.\n");
+ TIMEIT_END(make_local);
+#endif
}
/**
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 9685f1f5af6..d1f0c87183d 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -33,6 +33,7 @@
#include "DNA_actuator_types.h"
#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
@@ -70,10 +71,12 @@
#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
+#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_node.h"
#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sca.h"
@@ -82,7 +85,9 @@
#define FOREACH_FINALIZE _finalize
-#define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0
+#define FOREACH_FINALIZE_VOID \
+ if (0) { goto FOREACH_FINALIZE; } \
+ FOREACH_FINALIZE: ((void)0)
#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, _cb_flag) \
CHECK_TYPE(id_pp, ID **); \
@@ -140,6 +145,37 @@ typedef struct LibraryForeachIDData {
BLI_LINKSTACK_DECLARE(ids_todo, ID *);
} LibraryForeachIDData;
+static void library_foreach_idproperty_ID_link(LibraryForeachIDData *data, IDProperty *prop, int flag)
+{
+ if (!prop)
+ return;
+
+ switch (prop->type) {
+ case IDP_GROUP:
+ {
+ for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) {
+ library_foreach_idproperty_ID_link(data, loop, flag);
+ }
+ break;
+ }
+ case IDP_IDPARRAY:
+ {
+ IDProperty *loop = IDP_Array(prop);
+ for (int i = 0; i < prop->len; i++) {
+ library_foreach_idproperty_ID_link(data, &loop[i], flag);
+ }
+ break;
+ }
+ case IDP_ID:
+ FOREACH_CALLBACK_INVOKE_ID(data, prop->data.pointer, flag);
+ break;
+ default:
+ break; /* Nothing to do here with other types of IDProperties... */
+ }
+
+ FOREACH_FINALIZE_VOID;
+}
+
static void library_foreach_rigidbodyworldSceneLooper(
struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cb_flag)
{
@@ -265,6 +301,17 @@ static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint)
FOREACH_FINALIZE_VOID;
}
+static void library_foreach_bone(LibraryForeachIDData *data, Bone *bone)
+{
+ library_foreach_idproperty_ID_link(data, bone->prop, IDWALK_CB_USER);
+
+ for (Bone *curbone = bone->childbase.first; curbone; curbone = curbone->next) {
+ library_foreach_bone(data, curbone);
+ }
+
+ FOREACH_FINALIZE_VOID;
+}
+
static void library_foreach_ID_as_subdata_link(
ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
{
@@ -337,6 +384,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
continue;
}
+ library_foreach_idproperty_ID_link(&data, id->properties, IDWALK_CB_USER);
+
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
library_foreach_animationData(&data, adt);
@@ -402,6 +451,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER);
CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER);
CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER);
+ library_foreach_idproperty_ID_link(&data, seq->prop, IDWALK_CB_USER);
for (SequenceModifierData *smd = seq->modifiers.first; smd; smd = smd->next) {
CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER);
}
@@ -462,7 +512,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
/* Object is special, proxies make things hard... */
const int data_cb_flag = data.cb_flag;
- const int proxy_cb_flag = (object->proxy || object->proxy_group) ? IDWALK_CB_INDIRECT_USAGE : 0;
+ const int proxy_cb_flag = ((data.flag & IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 && (object->proxy || object->proxy_group)) ?
+ IDWALK_CB_INDIRECT_USAGE : 0;
/* object data special case */
data.cb_flag |= proxy_cb_flag;
@@ -490,7 +541,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
if (object->proxy_from) {
data.cb_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_CB_INDIRECT_USAGE : 0;
}
- CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_LOOPBACK);
data.cb_flag = data_cb_flag;
CALLBACK_INVOKE(object->poselib, IDWALK_CB_USER);
@@ -515,6 +566,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
data.cb_flag |= proxy_cb_flag;
for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) {
+ library_foreach_idproperty_ID_link(&data, pchan->prop, IDWALK_CB_USER);
CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER);
BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data);
}
@@ -554,6 +606,16 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
break;
}
+ case ID_AR:
+ {
+ bArmature *arm = (bArmature *)id;
+
+ for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
+ library_foreach_bone(&data, bone);
+ }
+ break;
+ }
+
case ID_ME:
{
Mesh *mesh = (Mesh *) id;
@@ -684,12 +746,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
case ID_KE:
{
- /* XXX Only ID pointer from shapekeys is the 'from' one, which is not actually ID usage.
- * Maybe we should even nuke it from here, not 100% sure yet...
- * (see also foreach_libblock_id_users_callback).
- */
Key *key = (Key *) id;
- CALLBACK_INVOKE_ID(key->from, IDWALK_CB_NOP);
+ CALLBACK_INVOKE_ID(key->from, IDWALK_CB_LOOPBACK);
break;
}
@@ -736,9 +794,27 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
{
bNodeTree *ntree = (bNodeTree *) id;
bNode *node;
+ bNodeSocket *sock;
+
CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER);
+
for (node = ntree->nodes.first; node; node = node->next) {
CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER);
+
+ library_foreach_idproperty_ID_link(&data, node->prop, IDWALK_CB_USER);
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+ }
+ }
+
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
}
break;
}
@@ -892,14 +968,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
break;
}
+ case ID_GD:
+ {
+ bGPdata *gpencil = (bGPdata *) id;
+
+ for (bGPDlayer *gp_layer = gpencil->layers.first; gp_layer; gp_layer = gp_layer->next) {
+ CALLBACK_INVOKE(gp_layer->parent, IDWALK_CB_NOP);
+ }
+ break;
+ }
/* Nothing needed for those... */
case ID_IM:
case ID_VF:
case ID_TXT:
case ID_SO:
- case ID_AR:
- case ID_GD:
case ID_WM:
case ID_PAL:
case ID_PC:
@@ -948,9 +1031,25 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
*/
/* XXX This has to be fully rethink, basing check on ID type is not really working anymore (and even worth once
* IDProps will support ID pointers), we'll have to do some quick checks on IDs themselves... */
-bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used)
+bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
{
- if (id_type_can_have_animdata(id_type_owner)) {
+ /* any type of ID can be used in custom props. */
+ if (id_owner->properties) {
+ return true;
+ }
+
+ const short id_type_owner = GS(id_owner->name);
+
+ /* IDProps of armature bones and nodes, and bNode->id can use virtually any type of ID. */
+ if (ELEM(id_type_owner, ID_NT, ID_AR)) {
+ return true;
+ }
+
+ if (ntreeFromID(id_owner)) {
+ return true;
+ }
+
+ if (BKE_animdata_from_id(id_owner)) {
return true; /* AnimationData can use virtually any kind of datablocks, through drivers especially. */
}
@@ -959,8 +1058,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
return ELEM(id_type_used, ID_LI);
case ID_SCE:
return (ELEM(id_type_used, ID_OB, ID_WO, ID_SCE, ID_MC, ID_MA, ID_GR, ID_TXT,
- ID_LS, ID_MSK, ID_SO, ID_GD, ID_BR, ID_PAL, ID_IM, ID_NT) ||
- BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ ID_LS, ID_MSK, ID_SO, ID_GD, ID_BR, ID_PAL, ID_IM, ID_NT));
case ID_OB:
/* Could be the following, but simpler to just always say 'yes' here. */
#if 0
@@ -977,13 +1075,13 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
case ID_MB:
return ELEM(id_type_used, ID_MA);
case ID_MA:
- return (ELEM(id_type_used, ID_TE, ID_GR) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ return (ELEM(id_type_used, ID_TE, ID_GR));
case ID_TE:
- return (ELEM(id_type_used, ID_IM, ID_OB) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ return (ELEM(id_type_used, ID_IM, ID_OB));
case ID_LT:
return ELEM(id_type_used, ID_KE);
case ID_LA:
- return (ELEM(id_type_used, ID_TE) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ return (ELEM(id_type_used, ID_TE));
case ID_CA:
return ELEM(id_type_used, ID_OB);
case ID_KE:
@@ -991,7 +1089,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
case ID_SCR:
return ELEM(id_type_used, ID_SCE);
case ID_WO:
- return (ELEM(id_type_used, ID_TE) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ return (ELEM(id_type_used, ID_TE));
case ID_SPK:
return ELEM(id_type_used, ID_SO);
case ID_GR:
@@ -1012,7 +1110,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
case ID_MSK:
return ELEM(id_type_used, ID_MC); /* WARNING! mask->parent.id, not typed. */
case ID_LS:
- return (ELEM(id_type_used, ID_TE, ID_OB) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ return (ELEM(id_type_used, ID_TE, ID_OB));
case ID_IM:
case ID_VF:
case ID_TXT:
@@ -1045,20 +1143,15 @@ typedef struct IDUsersIter {
int count_direct, count_indirect; /* Set by callback. */
} IDUsersIter;
-static int foreach_libblock_id_users_callback(void *user_data, ID *self_id, ID **id_p, int cb_flag)
+static int foreach_libblock_id_users_callback(void *user_data, ID *UNUSED(self_id), ID **id_p, int cb_flag)
{
IDUsersIter *iter = user_data;
if (*id_p) {
- /* XXX This is actually some kind of hack...
- * Issue is, shapekeys' 'from' ID pointer is not actually ID usage.
- * Maybe we should even nuke it from BKE_library_foreach_ID_link, not 100% sure yet...
+ /* 'Loopback' ID pointers (the ugly 'from' ones, Object->proxy_from and Key->from).
+ * Those are not actually ID usage, we can ignore them here.
*/
- if ((GS(self_id->name) == ID_KE) && (((Key *)self_id)->from == *id_p)) {
- return IDWALK_RET_NOP;
- }
- /* XXX another hack, for similar reasons as above one. */
- if ((GS(self_id->name) == ID_OB) && (((Object *)self_id)->proxy_from == (Object *)*id_p)) {
+ if (cb_flag & IDWALK_CB_LOOPBACK) {
return IDWALK_RET_NOP;
}
@@ -1118,7 +1211,7 @@ static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
while (i-- && !is_defined) {
ID *id_curr = lb_array[i]->first;
- if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(id->name))) {
+ if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) {
continue;
}
@@ -1170,7 +1263,7 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo
while (i-- && !is_defined) {
ID *id_curr = lb_array[i]->first;
- if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(id->name))) {
+ if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) {
continue;
}
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index b6f4621a0b3..5e5ba44f039 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -419,6 +419,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
IDRemap id_remap_data;
ListBase *lb_array[MAX_LIBARRAY];
int i;
+ const int foreach_id_flags = (remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ? IDWALK_NO_INDIRECT_PROXY_DATA_USAGE : IDWALK_NOP;
if (r_id_remap_data == NULL) {
r_id_remap_data = &id_remap_data;
@@ -439,7 +440,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
#endif
r_id_remap_data->id = id;
libblock_remap_data_preprocess(r_id_remap_data);
- BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags);
}
else {
i = set_listbasepointers(bmain, lb_array);
@@ -448,20 +449,16 @@ ATTR_NONNULL(1) static void libblock_remap_data(
* objects actually using given old_id... sounds rather unlikely currently, though, so this will do for now. */
while (i--) {
- ID *id_curr = lb_array[i]->first;
-
- if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(old_id->name))) {
- continue;
- }
-
- for (; id_curr; id_curr = id_curr->next) {
- /* Note that we cannot skip indirect usages of old_id here (if requested), we still need to check it for
- * the user count handling...
- * XXX No more true (except for debug usage of those skipping counters). */
- r_id_remap_data->id = id_curr;
- libblock_remap_data_preprocess(r_id_remap_data);
- BKE_library_foreach_ID_link(
- NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ for (ID *id_curr = lb_array[i]->first; id_curr; id_curr = id_curr->next) {
+ if (BKE_library_id_can_use_idtype(id_curr, GS(old_id->name))) {
+ /* Note that we cannot skip indirect usages of old_id here (if requested), we still need to check it for
+ * the user count handling...
+ * XXX No more true (except for debug usage of those skipping counters). */
+ r_id_remap_data->id = id_curr;
+ libblock_remap_data_preprocess(r_id_remap_data);
+ BKE_library_foreach_ID_link(
+ NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags);
+ }
}
}
}
@@ -530,8 +527,12 @@ void BKE_libblock_remap_locked(
id_us_clear_real(old_id);
}
- BLI_assert(old_id->us - skipped_refcounted >= 0);
- UNUSED_VARS_NDEBUG(skipped_refcounted);
+ if (old_id->us - skipped_refcounted < 0) {
+ printf("Error in remapping process from '%s' (%p) to '%s' (%p): "
+ "wrong user count in old ID after process (summing up to %d)\n",
+ old_id->name, old_id, new_id ? new_id->name : "<NULL>", new_id, old_id->us - skipped_refcounted);
+ BLI_assert(0);
+ }
if (skipped_direct == 0) {
/* old_id is assumed to not be used directly anymore... */
@@ -723,38 +724,17 @@ void BKE_libblock_relink_to_newid(ID *id)
BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
}
-void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id)
+void BKE_libblock_free_data(ID *id, const bool do_id_user)
{
if (id->properties) {
- IDP_FreeProperty(id->properties);
+ IDP_FreeProperty_ex(id->properties, do_id_user);
MEM_freeN(id->properties);
}
}
-/**
- * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
- *
- * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv.
- * (only applies to main database)
- * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to
- * \a id.
- */
-void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user)
+void BKE_libblock_free_datablock(ID *id)
{
- ID *id = idv;
- short type = GS(id->name);
- ListBase *lb = which_libbase(bmain, type);
-
- DAG_id_type_tag(bmain, type);
-
-#ifdef WITH_PYTHON
- BPY_id_release(id);
-#endif
-
- if (do_id_user) {
- BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
- }
-
+ const short type = GS(id->name);
switch (type) {
case ID_SCE:
BKE_scene_free((Scene *)id);
@@ -860,6 +840,33 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b
BKE_cachefile_free((CacheFile *)id);
break;
}
+}
+
+/**
+ * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
+ *
+ * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv.
+ * (only applies to main database)
+ * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to
+ * \a id.
+ */
+void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user)
+{
+ ID *id = idv;
+ short type = GS(id->name);
+ ListBase *lb = which_libbase(bmain, type);
+
+ DAG_id_type_tag(bmain, type);
+
+#ifdef WITH_PYTHON
+ BPY_id_release(id);
+#endif
+
+ if (do_id_user) {
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
+ }
+
+ BKE_libblock_free_datablock(id);
/* avoid notifying on removed data */
BKE_main_lock(bmain);
@@ -876,7 +883,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b
BLI_remlink(lb, id);
- BKE_libblock_free_data(bmain, id);
+ BKE_libblock_free_data(id, do_id_user);
BKE_main_unlock(bmain);
MEM_freeN(id);
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 1eb909bd9f9..771e81ddc4f 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -155,7 +155,7 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle)
BKE_linestyle_geometry_modifier_remove(linestyle, m);
}
-FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle)
+FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle)
{
FreestyleLineStyle *new_linestyle;
LineStyleModifier *m;
@@ -355,7 +355,7 @@ LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -594,7 +594,7 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl
return m;
}
-LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -863,7 +863,7 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *line
return m;
}
-LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m)
{
LineStyleModifier *new_m;
@@ -1195,7 +1195,7 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *lines
return m;
}
-LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m)
{
LineStyleModifier *new_m;
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 6f23b82c6df..ae27e9bcd34 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -192,7 +192,7 @@ void BKE_mask_layer_rename(Mask *mask, MaskLayer *masklay, char *oldname, char *
BKE_animdata_fix_paths_rename_all(&mask->id, "layers", oldname, masklay->name);
}
-MaskLayer *BKE_mask_layer_copy(MaskLayer *masklay)
+MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay)
{
MaskLayer *masklay_new;
MaskSpline *spline;
@@ -236,7 +236,7 @@ MaskLayer *BKE_mask_layer_copy(MaskLayer *masklay)
return masklay_new;
}
-void BKE_mask_layer_copy_list(ListBase *masklayers_new, ListBase *masklayers)
+void BKE_mask_layer_copy_list(ListBase *masklayers_new, const ListBase *masklayers)
{
MaskLayer *layer;
@@ -840,7 +840,7 @@ Mask *BKE_mask_copy_nolib(Mask *mask)
return mask_new;
}
-Mask *BKE_mask_copy(Main *bmain, Mask *mask)
+Mask *BKE_mask_copy(Main *bmain, const Mask *mask)
{
Mask *mask_new;
@@ -851,7 +851,7 @@ Mask *BKE_mask_copy(Main *bmain, Mask *mask)
BKE_mask_layer_copy_list(&mask_new->masklayers, &mask->masklayers);
/* enable fake user by default */
- id_fake_user_set(&mask->id);
+ id_fake_user_set(&mask_new->id);
BKE_id_copy_ensure_local(bmain, &mask->id, &mask_new->id);
@@ -906,7 +906,7 @@ void BKE_mask_spline_free_list(ListBase *splines)
}
}
-static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot_point)
+static MaskSplinePoint *mask_spline_points_copy(const MaskSplinePoint *points, int tot_point)
{
MaskSplinePoint *npoints;
int i;
@@ -923,7 +923,7 @@ static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot
return npoints;
}
-MaskSpline *BKE_mask_spline_copy(MaskSpline *spline)
+MaskSpline *BKE_mask_spline_copy(const MaskSpline *spline)
{
MaskSpline *nspline = MEM_callocN(sizeof(MaskSpline), "new spline");
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 54945242fe4..f21efb71180 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -220,7 +220,7 @@ Material *BKE_material_add(Main *bmain, const char *name)
}
/* XXX keep synced with next function */
-Material *BKE_material_copy(Main *bmain, Material *ma)
+Material *BKE_material_copy(Main *bmain, const Material *ma)
{
Material *man;
int a;
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 97033a9555d..b80579014d6 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -103,7 +103,7 @@ MetaBall *BKE_mball_add(Main *bmain, const char *name)
return mb;
}
-MetaBall *BKE_mball_copy(Main *bmain, MetaBall *mb)
+MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb)
{
MetaBall *mbn;
int a;
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 5c0b09f0ff0..76965176be8 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -316,12 +316,12 @@ static float densfunc(const MetaElem *ball, float x, float y, float z)
if (dvec[2] > ball->expz) dvec[2] -= ball->expz;
else if (dvec[2] < -ball->expz) dvec[2] += ball->expz;
else dvec[2] = 0.0;
- /* fall through */
+ ATTR_FALLTHROUGH;
case MB_PLANE:
if (dvec[1] > ball->expy) dvec[1] -= ball->expy;
else if (dvec[1] < -ball->expy) dvec[1] += ball->expy;
else dvec[1] = 0.0;
- /* fall through */
+ ATTR_FALLTHROUGH;
case MB_TUBE:
if (dvec[0] > ball->expx) dvec[0] -= ball->expx;
else if (dvec[0] < -ball->expx) dvec[0] += ball->expx;
@@ -660,7 +660,7 @@ static void makecubetable(void)
for (i = 0; i < 256; i++) {
for (e = 0; e < 12; e++) done[e] = 0;
for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c);
- for (e = 0; e < 12; e++)
+ for (e = 0; e < 12; e++) {
if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
INTLIST *ints = NULL;
INTLISTS *lists = MEM_callocN(sizeof(INTLISTS), "mball_intlist");
@@ -687,6 +687,7 @@ static void makecubetable(void)
lists->next = cubetable[i];
cubetable[i] = lists;
}
+ }
}
for (i = 0; i < 256; i++) {
@@ -1193,10 +1194,10 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
break;
case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
expz += ml->expz;
- /* fall through */
+ ATTR_FALLTHROUGH;
case MB_PLANE: /* plane is "expanded" by expy and expx */
expy += ml->expy;
- /* fall through */
+ ATTR_FALLTHROUGH;
case MB_TUBE: /* tube is "expanded" by expx */
expx += ml->expx;
break;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index befe1a4d70e..6233caa43fa 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -501,7 +501,7 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
return me;
}
-Mesh *BKE_mesh_copy(Main *bmain, Mesh *me)
+Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me)
{
Mesh *men;
int a;
@@ -1339,7 +1339,7 @@ int BKE_mesh_nurbs_displist_to_mdata(
/* this may fail replacing ob->data, be sure to check ob->type */
-void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv)
+void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name)
{
Main *bmain = G.main;
Object *ob1;
@@ -1366,7 +1366,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
}
/* make mesh */
- me = BKE_mesh_add(bmain, "Mesh");
+ me = BKE_mesh_add(bmain, obdata_name);
me->totvert = totvert;
me->totedge = totedge;
me->totloop = totloop;
@@ -1386,7 +1386,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
BKE_mesh_calc_normals(me);
}
else {
- me = BKE_mesh_add(bmain, "Mesh");
+ me = BKE_mesh_add(bmain, obdata_name);
DM_to_mesh(dm, me, ob, CD_MASK_MESH, false);
}
@@ -1398,9 +1398,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
cu->mat = NULL;
cu->totcol = 0;
- if (ob->data) {
- BKE_libblock_free(bmain, ob->data);
- }
+ /* Do not decrement ob->data usercount here, it's done at end of func with BKE_libblock_free_us() call. */
ob->data = me;
ob->type = OB_MESH;
@@ -1410,11 +1408,14 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
if (ob1->data == cu) {
ob1->type = OB_MESH;
+ id_us_min((ID *)ob1->data);
ob1->data = ob->data;
- id_us_plus((ID *)ob->data);
+ id_us_plus((ID *)ob1->data);
}
ob1 = ob1->id.next;
}
+
+ BKE_libblock_free_us(bmain, cu);
}
void BKE_mesh_from_nurbs(Object *ob)
@@ -1427,7 +1428,7 @@ void BKE_mesh_from_nurbs(Object *ob)
disp = ob->curve_cache->disp;
}
- BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv);
+ BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv, cu->id.name);
}
typedef struct EdgeLink {
@@ -2145,6 +2146,8 @@ static int split_faces_prepare_new_verts(
/* If vert is already used by another smooth fan, we need a new vert for this one. */
const int new_vert_idx = vert_used ? num_verts++ : vert_idx;
+ BLI_assert(*lnor_space);
+
if ((*lnor_space)->loops) {
for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
@@ -2377,19 +2380,24 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
* loops' vertex and edge indices to new, to-be-created split ones). */
const int num_new_edges = split_faces_prepare_new_edges(mesh, &new_edges, memarena);
- BLI_assert(num_new_edges > 0);
+ /* We can have to split a vertex without having to add a single new edge... */
+ const bool do_edges = (num_new_edges > 0);
/* Reallocate all vert and edge related data. */
mesh->totvert += num_new_verts;
mesh->totedge += num_new_edges;
CustomData_realloc(&mesh->vdata, mesh->totvert);
- CustomData_realloc(&mesh->edata, mesh->totedge);
+ if (do_edges) {
+ CustomData_realloc(&mesh->edata, mesh->totedge);
+ }
/* Update pointers to a newly allocated memory. */
BKE_mesh_update_customdata_pointers(mesh, false);
/* Perform actual split of vertices and edges. */
split_faces_split_new_verts(mesh, new_verts, num_new_verts);
- split_faces_split_new_edges(mesh, new_edges, num_new_edges);
+ if (do_edges) {
+ split_faces_split_new_edges(mesh, new_edges, num_new_edges);
+ }
}
/* Note: after this point mesh is expected to be valid again. */
@@ -2479,7 +2487,7 @@ Mesh *BKE_mesh_new_from_object(
/* convert object type to mesh */
uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
- BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco);
+ BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2);
tmpmesh = tmpobj->data;
@@ -2515,7 +2523,7 @@ Mesh *BKE_mesh_new_from_object(
if (ob != basis_ob)
return NULL; /* only do basis metaball */
- tmpmesh = BKE_mesh_add(bmain, "Mesh");
+ tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
/* BKE_mesh_add gives us a user count we don't need */
id_us_min(&tmpmesh->id);
@@ -2570,7 +2578,7 @@ Mesh *BKE_mesh_new_from_object(
else
dm = mesh_create_derived_view(sce, ob, mask);
- tmpmesh = BKE_mesh_add(bmain, "Mesh");
+ tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
DM_to_mesh(dm, tmpmesh, ob, mask, true);
/* Copy autosmooth settings from original mesh. */
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index e96a434194c..5dfcef9f9bf 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -304,13 +304,13 @@ void BKE_mesh_calc_normals_poly(
void BKE_mesh_calc_normals(Mesh *mesh)
{
#ifdef DEBUG_TIME
- TIMEIT_START(BKE_mesh_calc_normals);
+ TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
#endif
BKE_mesh_calc_normals_poly(mesh->mvert, NULL, mesh->totvert,
mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
NULL, false);
#ifdef DEBUG_TIME
- TIMEIT_END(BKE_mesh_calc_normals);
+ TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
#endif
}
@@ -630,7 +630,6 @@ typedef struct LoopSplitTaskDataCommon {
* Note we do not need to protect it, though, since two different tasks will *always* affect different
* elements in the arrays. */
MLoopNorSpaceArray *lnors_spacearr;
- BLI_bitmap *sharp_verts;
float (*loopnors)[3];
short (*clnors_data)[2];
@@ -643,11 +642,8 @@ typedef struct LoopSplitTaskDataCommon {
const int *loop_to_poly;
const float (*polynors)[3];
+ int numLoops;
int numPolys;
-
- /* ***** Workers communication. ***** */
- ThreadQueue *task_queue;
-
} LoopSplitTaskDataCommon;
#define INDEX_UNSET INT_MIN
@@ -655,6 +651,50 @@ typedef struct LoopSplitTaskDataCommon {
/* See comment about edge_to_loops below. */
#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID))
+static void loop_manifold_fan_around_vert_next(
+ const MLoop *mloops, const MPoly *mpolys,
+ const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index,
+ const MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index)
+{
+ const MLoop *mlfan_next;
+ const MPoly *mpfan_next;
+
+ /* Warning! This is rather complex!
+ * We have to find our next edge around the vertex (fan mode).
+ * First we find the next loop, which is either previous or next to mlfan_curr_index, depending
+ * whether both loops using current edge are in the same direction or not, and whether
+ * mlfan_curr_index actually uses the vertex we are fanning around!
+ * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
+ * (i.e. not the future mlfan_curr)...
+ */
+ *r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
+ *r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index];
+
+ BLI_assert(*r_mlfan_curr_index >= 0);
+ BLI_assert(*r_mpfan_curr_index >= 0);
+
+ mlfan_next = &mloops[*r_mlfan_curr_index];
+ mpfan_next = &mpolys[*r_mpfan_curr_index];
+ if (((*r_mlfan_curr)->v == mlfan_next->v && (*r_mlfan_curr)->v == mv_pivot_index) ||
+ ((*r_mlfan_curr)->v != mlfan_next->v && (*r_mlfan_curr)->v != mv_pivot_index))
+ {
+ /* We need the previous loop, but current one is our vertex's loop. */
+ *r_mlfan_vert_index = *r_mlfan_curr_index;
+ if (--(*r_mlfan_curr_index) < mpfan_next->loopstart) {
+ *r_mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
+ }
+ }
+ else {
+ /* We need the next loop, which is also our vertex's loop. */
+ if (++(*r_mlfan_curr_index) >= mpfan_next->loopstart + mpfan_next->totloop) {
+ *r_mlfan_curr_index = mpfan_next->loopstart;
+ }
+ *r_mlfan_vert_index = *r_mlfan_curr_index;
+ }
+ *r_mlfan_curr = &mloops[*r_mlfan_curr_index];
+ /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+}
+
static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
@@ -680,7 +720,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
*/
copy_v3_v3(*lnor, polynors[mp_index]);
- /* printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", ml_curr_index, ml_curr->e, ml_curr->v, mp_index); */
+// printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", ml_curr_index, ml_curr->e, ml_curr->v, mp_index);
/* If needed, generate this (simple!) lnor space. */
if (lnors_spacearr) {
@@ -747,8 +787,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
const MEdge *me_org = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */
const int *e2lfan_curr;
float vec_curr[3], vec_prev[3], vec_org[3];
- const MLoop *mlfan_curr, *mlfan_next;
- const MPoly *mpfan_next;
+ const MLoop *mlfan_curr;
float lnor[3] = {0.0f, 0.0f, 0.0f};
/* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
@@ -787,7 +826,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
}
}
- /* printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); */
+// printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e);
while (true) {
const MEdge *me_curr = &medges[mlfan_curr->e];
@@ -803,7 +842,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
normalize_v3(vec_curr);
}
- /* printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index); */
+// printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index);
{
/* Code similar to accumulate_vertex_normals_poly. */
@@ -845,46 +884,16 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* Current edge is sharp and we have finished with this fan of faces around this vert,
* or this vert is smooth, and we have completed a full turn around it.
*/
- /* printf("FAN: Finished!\n"); */
+// printf("FAN: Finished!\n");
break;
}
copy_v3_v3(vec_prev, vec_curr);
- /* Warning! This is rather complex!
- * We have to find our next edge around the vertex (fan mode).
- * First we find the next loop, which is either previous or next to mlfan_curr_index, depending
- * whether both loops using current edge are in the same direction or not, and whether
- * mlfan_curr_index actually uses the vertex we are fanning around!
- * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
- * (i.e. not the future mlfan_curr)...
- */
- mlfan_curr_index = (e2lfan_curr[0] == mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
- mpfan_curr_index = loop_to_poly[mlfan_curr_index];
-
- BLI_assert(mlfan_curr_index >= 0);
- BLI_assert(mpfan_curr_index >= 0);
-
- mlfan_next = &mloops[mlfan_curr_index];
- mpfan_next = &mpolys[mpfan_curr_index];
- if ((mlfan_curr->v == mlfan_next->v && mlfan_curr->v == mv_pivot_index) ||
- (mlfan_curr->v != mlfan_next->v && mlfan_curr->v != mv_pivot_index))
- {
- /* We need the previous loop, but current one is our vertex's loop. */
- mlfan_vert_index = mlfan_curr_index;
- if (--mlfan_curr_index < mpfan_next->loopstart) {
- mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
- }
- }
- else {
- /* We need the next loop, which is also our vertex's loop. */
- if (++mlfan_curr_index >= mpfan_next->loopstart + mpfan_next->totloop) {
- mlfan_curr_index = mpfan_next->loopstart;
- }
- mlfan_vert_index = mlfan_curr_index;
- }
- mlfan_curr = &mloops[mlfan_curr_index];
- /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+ /* Find next loop of the smooth fan. */
+ loop_manifold_fan_around_vert_next(
+ mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
+ &mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
e2lfan_curr = edge_to_loops[mlfan_curr->e];
}
@@ -955,31 +964,25 @@ static void loop_split_worker_do(
}
}
-static void loop_split_worker(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
+static void loop_split_worker(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid))
{
- LoopSplitTaskDataCommon *common_data = taskdata;
- LoopSplitTaskData *data_buff;
+ LoopSplitTaskDataCommon *common_data = BLI_task_pool_userdata(pool);
+ LoopSplitTaskData *data = taskdata;
/* Temp edge vectors stack, only used when computing lnor spacearr. */
BLI_Stack *edge_vectors = common_data->lnors_spacearr ? BLI_stack_new(sizeof(float[3]), __func__) : NULL;
#ifdef DEBUG_TIME
- TIMEIT_START(loop_split_worker);
+ TIMEIT_START_AVERAGED(loop_split_worker);
#endif
- while ((data_buff = BLI_thread_queue_pop(common_data->task_queue))) {
- LoopSplitTaskData *data = data_buff;
- int i;
-
- for (i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) {
- /* A NULL ml_curr is used to tag ended data! */
- if (data->ml_curr == NULL) {
- break;
- }
- loop_split_worker_do(common_data, data, edge_vectors);
+ for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) {
+ /* A NULL ml_curr is used to tag ended data! */
+ if (data->ml_curr == NULL) {
+ break;
}
- MEM_freeN(data_buff);
+ loop_split_worker_do(common_data, data, edge_vectors);
}
if (edge_vectors) {
@@ -987,38 +990,104 @@ static void loop_split_worker(TaskPool * __restrict UNUSED(pool), void *taskdata
}
#ifdef DEBUG_TIME
- TIMEIT_END(loop_split_worker);
+ TIMEIT_END_AVERAGED(loop_split_worker);
#endif
}
-static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const bool threaded)
+/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not.
+ * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */
+static bool loop_split_generator_check_cyclic_smooth_fan(
+ const MLoop *mloops, const MPoly *mpolys,
+ const int (*edge_to_loops)[2], const int *loop_to_poly, const int *e2l_prev, BLI_bitmap *skip_loops,
+ const MLoop *ml_curr, const MLoop *ml_prev, const int ml_curr_index, const int ml_prev_index,
+ const int mp_curr_index)
+{
+ const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
+ const int *e2lfan_curr;
+ const MLoop *mlfan_curr;
+ /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
+
+ e2lfan_curr = e2l_prev;
+ if (IS_EDGE_SHARP(e2lfan_curr)) {
+ /* Sharp loop, so not a cyclic smooth fan... */
+ return false;
+ }
+
+ mlfan_curr = ml_prev;
+ mlfan_curr_index = ml_prev_index;
+ mlfan_vert_index = ml_curr_index;
+ mpfan_curr_index = mp_curr_index;
+
+ BLI_assert(mlfan_curr_index >= 0);
+ BLI_assert(mlfan_vert_index >= 0);
+ BLI_assert(mpfan_curr_index >= 0);
+
+ BLI_assert(!BLI_BITMAP_TEST(skip_loops, mlfan_vert_index));
+ BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index);
+
+ while (true) {
+ /* Find next loop of the smooth fan. */
+ loop_manifold_fan_around_vert_next(
+ mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
+ &mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
+
+ e2lfan_curr = edge_to_loops[mlfan_curr->e];
+
+ if (IS_EDGE_SHARP(e2lfan_curr)) {
+ /* Sharp loop/edge, so not a cyclic smooth fan... */
+ return false;
+ }
+ /* Smooth loop/edge... */
+ else if (BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)) {
+ if (mlfan_vert_index == ml_curr_index) {
+ /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can
+ * use initial ml_curr/ml_prev edge as start for this smooth fan. */
+ return true;
+ }
+ /* ... already checked in some previous looping, we can abort. */
+ return false;
+ }
+ else {
+ /* ... we can skip it in future, and keep checking the smooth fan. */
+ BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index);
+ }
+ }
+}
+
+static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
- BLI_bitmap *sharp_verts = common_data->sharp_verts;
float (*loopnors)[3] = common_data->loopnors;
const MLoop *mloops = common_data->mloops;
const MPoly *mpolys = common_data->mpolys;
+ const int *loop_to_poly = common_data->loop_to_poly;
const int (*edge_to_loops)[2] = common_data->edge_to_loops;
+ const int numLoops = common_data->numLoops;
const int numPolys = common_data->numPolys;
const MPoly *mp;
int mp_index;
- LoopSplitTaskData *data, *data_buff = NULL, data_mem;
+ const MLoop *ml_curr;
+ const MLoop *ml_prev;
+ int ml_curr_index;
+ int ml_prev_index;
+
+ BLI_bitmap *skip_loops = BLI_BITMAP_NEW(numLoops, __func__);
+
+ LoopSplitTaskData *data_buff = NULL;
int data_idx = 0;
/* Temp edge vectors stack, only used when computing lnor spacearr (and we are not multi-threading). */
BLI_Stack *edge_vectors = NULL;
#ifdef DEBUG_TIME
- TIMEIT_START(loop_split_generator);
+ TIMEIT_START_AVERAGED(loop_split_generator);
#endif
- if (!threaded) {
- memset(&data_mem, 0, sizeof(data_mem));
- data = &data_mem;
-
+ if (!pool) {
if (lnors_spacearr) {
edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
}
@@ -1028,11 +1097,10 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
* Now, time to generate the normals.
*/
for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- const MLoop *ml_curr, *ml_prev;
float (*lnors)[3];
const int ml_last_index = (mp->loopstart + mp->totloop) - 1;
- int ml_curr_index = mp->loopstart;
- int ml_prev_index = ml_last_index;
+ ml_curr_index = mp->loopstart;
+ ml_prev_index = ml_last_index;
ml_curr = &mloops[ml_curr_index];
ml_prev = &mloops[ml_prev_index];
@@ -1042,23 +1110,40 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
const int *e2l_curr = edge_to_loops[ml_curr->e];
const int *e2l_prev = edge_to_loops[ml_prev->e];
- if (!IS_EDGE_SHARP(e2l_curr) && (!lnors_spacearr || BLI_BITMAP_TEST_BOOL(sharp_verts, ml_curr->v))) {
- /* A smooth edge, and we are not generating lnor_spacearr, or the related vertex is sharp.
- * We skip it because it is either:
- * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
- * one of its ends, i.e. one of its two sharp edges), or...
- * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex
- * are just fine (or it has already be handled in a previous loop in case of needed lnors spacearr)!
- */
- /* printf("Skipping loop %d / edge %d / vert %d(%d)\n", ml_curr_index, ml_curr->e, ml_curr->v, sharp_verts[ml_curr->v]); */
+// printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)...",
+// ml_curr_index, ml_curr->e, ml_curr->v, IS_EDGE_SHARP(e2l_curr), BLI_BITMAP_TEST_BOOL(skip_loops, ml_curr_index));
+
+ /* A smooth edge, we have to check for cyclic smooth fan case.
+ * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as
+ * 'entry point', otherwise we can skip it. */
+ /* Note: In theory, we could make loop_split_generator_check_cyclic_smooth_fan() store
+ * mlfan_vert_index'es and edge indexes in two stacks, to avoid having to fan again around the vert during
+ * actual computation of clnor & clnorspace. However, this would complicate the code, add more memory usage,
+ * and despite its logical complexity, loop_manifold_fan_around_vert_next() is quite cheap in term of
+ * CPU cycles, so really think it's not worth it. */
+ if (!IS_EDGE_SHARP(e2l_curr) &&
+ (BLI_BITMAP_TEST(skip_loops, ml_curr_index) ||
+ !loop_split_generator_check_cyclic_smooth_fan(
+ mloops, mpolys, edge_to_loops, loop_to_poly, e2l_prev, skip_loops,
+ ml_curr, ml_prev, ml_curr_index, ml_prev_index, mp_index)))
+ {
+// printf("SKIPPING!\n");
}
else {
- if (threaded) {
+ LoopSplitTaskData *data, data_local;
+
+// printf("PROCESSING!\n");
+
+ if (pool) {
if (data_idx == 0) {
data_buff = MEM_callocN(sizeof(*data_buff) * LOOP_SPLIT_TASK_BLOCK_SIZE, __func__);
}
data = &data_buff[data_idx];
}
+ else {
+ data = &data_local;
+ memset(data, 0, sizeof(*data));
+ }
if (IS_EDGE_SHARP(e2l_curr) && IS_EDGE_SHARP(e2l_prev)) {
data->lnor = lnors;
@@ -1094,22 +1179,18 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
data->mp_index = mp_index;
if (lnors_spacearr) {
data->lnor_space = BKE_lnor_space_create(lnors_spacearr);
- /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one).
- * This *has* to be done outside of workers tasks! */
- BLI_BITMAP_ENABLE(sharp_verts, ml_curr->v);
}
}
- if (threaded) {
+ if (pool) {
data_idx++;
if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) {
- BLI_thread_queue_push(common_data->task_queue, data_buff);
+ BLI_task_pool_push(pool, loop_split_worker, data_buff, true, TASK_PRIORITY_LOW);
data_idx = 0;
}
}
else {
loop_split_worker_do(common_data, data, edge_vectors);
- memset(data, 0, sizeof(data_mem));
}
}
@@ -1118,38 +1199,27 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
}
}
- if (threaded) {
- /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, everything is fine. */
- if (LIKELY(data_idx)) {
- BLI_thread_queue_push(common_data->task_queue, data_buff);
- }
-
- /* This will signal all other worker threads to wake up and finish! */
- BLI_thread_queue_nowait(common_data->task_queue);
+ /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, everything is fine. */
+ if (pool && data_idx) {
+ BLI_task_pool_push(pool, loop_split_worker, data_buff, true, TASK_PRIORITY_LOW);
}
if (edge_vectors) {
BLI_stack_free(edge_vectors);
}
+ MEM_freeN(skip_loops);
#ifdef DEBUG_TIME
- TIMEIT_END(loop_split_generator);
+ TIMEIT_END_AVERAGED(loop_split_generator);
#endif
}
-static void loop_split_generator(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- LoopSplitTaskDataCommon *common_data = taskdata;
-
- loop_split_generator_do(common_data, true);
-}
-
/**
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
*/
void BKE_mesh_normals_loop_split(
- const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
+ const MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
const bool use_split_normals, float split_angle,
@@ -1187,8 +1257,6 @@ void BKE_mesh_normals_loop_split(
return;
}
- {
-
/* Mapping edge -> loops.
* If that edge is used by more than two loops (polys), it is always sharp (and tagged as such, see below).
* We also use the second loop index as a kind of flag: smooth edge: > 0,
@@ -1198,33 +1266,25 @@ void BKE_mesh_normals_loop_split(
* store the negated value of loop index instead of INDEX_INVALID to retrieve the real value later in code).
* Note also that lose edges always have both values set to 0!
*/
- int (*edge_to_loops)[2] = MEM_callocN(sizeof(int[2]) * (size_t)numEdges, __func__);
+ int (*edge_to_loops)[2] = MEM_callocN(sizeof(*edge_to_loops) * (size_t)numEdges, __func__);
/* Simple mapping from a loop to its polygon index. */
- int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
+ int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_mallocN(sizeof(*loop_to_poly) * (size_t)numLoops, __func__);
MPoly *mp;
- int mp_index, me_index;
- bool check_angle = (split_angle < (float)M_PI);
- int i;
+ int mp_index;
- BLI_bitmap *sharp_verts = NULL;
- MLoopNorSpaceArray _lnors_spacearr = {NULL};
+ /* When using custom loop normals, disable the angle feature! */
+ const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL);
- LoopSplitTaskDataCommon common_data = {NULL};
+ MLoopNorSpaceArray _lnors_spacearr = {NULL};
#ifdef DEBUG_TIME
- TIMEIT_START(BKE_mesh_normals_loop_split);
+ TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split);
#endif
if (check_angle) {
- /* When using custom loop normals, disable the angle feature! */
- if (clnors_data) {
- check_angle = false;
- }
- else {
- split_angle = cosf(split_angle);
- }
+ split_angle = cosf(split_angle);
}
if (!r_lnors_spacearr && clnors_data) {
@@ -1233,7 +1293,6 @@ void BKE_mesh_normals_loop_split(
}
if (r_lnors_spacearr) {
BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops);
- sharp_verts = BLI_BITMAP_NEW((size_t)numVerts, __func__);
}
/* This first loop check which edges are actually smooth, and compute edge vectors. */
@@ -1287,60 +1346,38 @@ void BKE_mesh_normals_loop_split(
}
}
- if (r_lnors_spacearr) {
- /* Tag vertices that have at least one sharp edge as 'sharp' (used for the lnor spacearr computation).
- * XXX This third loop over edges is a bit disappointing, could not find any other way yet.
- * Not really performance-critical anyway.
- */
- for (me_index = 0; me_index < numEdges; me_index++) {
- const int *e2l = edge_to_loops[me_index];
- const MEdge *me = &medges[me_index];
- if (IS_EDGE_SHARP(e2l)) {
- BLI_BITMAP_ENABLE(sharp_verts, me->v1);
- BLI_BITMAP_ENABLE(sharp_verts, me->v2);
- }
- }
- }
-
/* Init data common to all tasks. */
- common_data.lnors_spacearr = r_lnors_spacearr;
- common_data.loopnors = r_loopnors;
- common_data.clnors_data = clnors_data;
-
- common_data.mverts = mverts;
- common_data.medges = medges;
- common_data.mloops = mloops;
- common_data.mpolys = mpolys;
- common_data.sharp_verts = sharp_verts;
- common_data.edge_to_loops = (const int(*)[2])edge_to_loops;
- common_data.loop_to_poly = loop_to_poly;
- common_data.polynors = polynors;
- common_data.numPolys = numPolys;
+ LoopSplitTaskDataCommon common_data = {
+ .lnors_spacearr = r_lnors_spacearr,
+ .loopnors = r_loopnors,
+ .clnors_data = clnors_data,
+ .mverts = mverts,
+ .medges = medges,
+ .mloops = mloops,
+ .mpolys = mpolys,
+ .edge_to_loops = (const int(*)[2])edge_to_loops,
+ .loop_to_poly = loop_to_poly,
+ .polynors = polynors,
+ .numLoops = numLoops,
+ .numPolys = numPolys,
+ };
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead... */
- loop_split_generator_do(&common_data, false);
+ loop_split_generator(NULL, &common_data);
}
else {
TaskScheduler *task_scheduler;
TaskPool *task_pool;
- int nbr_workers;
-
- common_data.task_queue = BLI_thread_queue_init();
task_scheduler = BLI_task_scheduler_get();
- task_pool = BLI_task_pool_create(task_scheduler, NULL);
+ task_pool = BLI_task_pool_create(task_scheduler, &common_data);
+
+ loop_split_generator(task_pool, &common_data);
- nbr_workers = max_ii(2, BLI_task_scheduler_num_threads(task_scheduler));
- for (i = 1; i < nbr_workers; i++) {
- BLI_task_pool_push(task_pool, loop_split_worker, &common_data, false, TASK_PRIORITY_HIGH);
- }
- BLI_task_pool_push(task_pool, loop_split_generator, &common_data, false, TASK_PRIORITY_HIGH);
BLI_task_pool_work_and_wait(task_pool);
BLI_task_pool_free(task_pool);
-
- BLI_thread_queue_free(common_data.task_queue);
}
MEM_freeN(edge_to_loops);
@@ -1349,17 +1386,14 @@ void BKE_mesh_normals_loop_split(
}
if (r_lnors_spacearr) {
- MEM_freeN(sharp_verts);
if (r_lnors_spacearr == &_lnors_spacearr) {
BKE_lnor_spacearr_free(r_lnors_spacearr);
}
}
#ifdef DEBUG_TIME
- TIMEIT_END(BKE_mesh_normals_loop_split);
+ TIMEIT_END_AVERAGED(BKE_mesh_normals_loop_split);
#endif
-
- }
}
#undef INDEX_UNSET
@@ -1595,8 +1629,8 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(
/**
* Computes average per-vertex normals from given custom loop normals.
*
- * @param clnors The computed custom loop normals.
- * @param r_vert_clnors The (already allocated) array where to store averaged per-vertex normals.
+ * \param clnors: The computed custom loop normals.
+ * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals.
*/
void BKE_mesh_normals_loop_to_vertex(
const int numVerts, const MLoop *mloops, const int numLoops,
@@ -1959,36 +1993,54 @@ float BKE_mesh_calc_poly_area(
}
}
-/* note, results won't be correct if polygon is non-planar */
-static float mesh_calc_poly_planar_area_centroid(
+/**
+ * Calculate the volume and volume-weighted centroid of the volume formed by the polygon and the origin.
+ * Results will be negative if the origin is "outside" the polygon
+ * (+ve normal side), but the polygon may be non-planar with no effect.
+ *
+ * Method from:
+ * - http://forums.cgsociety.org/archive/index.php?t-756235.html
+ * - http://www.globalspec.com/reference/52702/203279/4-8-the-centroid-of-a-tetrahedron
+ *
+ * \note volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid
+ * (so division can be done once at the end)
+ * \note results will have bias if polygon is non-planar.
+ */
+static float mesh_calc_poly_volume_and_weighted_centroid(
const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray,
float r_cent[3])
{
- int i;
- float tri_area;
- float total_area = 0.0f;
- float v1[3], v2[3], v3[3], normal[3], tri_cent[3];
+ const float *v_pivot, *v_step1;
+ float total_volume = 0.0f;
- 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(r_cent);
- for (i = 2; i < mpoly->totloop; i++) {
- copy_v3_v3(v3, mvarray[loopstart[i].v].co);
+ v_pivot = mvarray[loopstart[0].v].co;
+ v_step1 = mvarray[loopstart[1].v].co;
- tri_area = area_tri_signed_v3(v1, v2, v3, normal);
- total_area += tri_area;
+ for (int i = 2; i < mpoly->totloop; i++) {
+ const float *v_step2 = mvarray[loopstart[i].v].co;
- mid_v3_v3v3v3(tri_cent, v1, v2, v3);
- madd_v3_v3fl(r_cent, tri_cent, tri_area);
+ /* Calculate the 6x volume of the tetrahedron formed by the 3 vertices
+ * of the triangle and the origin as the fourth vertex */
+ float v_cross[3];
+ cross_v3_v3v3(v_cross, v_pivot, v_step1);
+ const float tetra_volume = dot_v3v3 (v_cross, v_step2);
+ total_volume += tetra_volume;
- copy_v3_v3(v2, v3);
- }
+ /* Calculate the centroid of the tetrahedron formed by the 3 vertices
+ * of the triangle and the origin as the fourth vertex.
+ * The centroid is simply the average of the 4 vertices.
+ *
+ * Note that the vector is 4x the actual centroid so the division can be done once at the end. */
+ for (uint j = 0; j < 3; j++) {
+ r_cent[j] += tetra_volume * (v_pivot[j] + v_step1[j] + v_step2[j]);
+ }
- mul_v3_fl(r_cent, 1.0f / total_area);
+ v_step1 = v_step2;
+ }
- return total_area;
+ return total_volume;
}
#if 0 /* slow version of the function below */
@@ -2109,25 +2161,28 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
{
int i = me->totpoly;
MPoly *mpoly;
- float poly_area;
- float total_area = 0.0f;
+ float poly_volume;
+ float total_volume = 0.0f;
float poly_cent[3];
zero_v3(r_cent);
- /* calculate a weighted average of polygon centroids */
+ /* calculate a weighted average of polyhedron centroids */
for (mpoly = me->mpoly; i--; mpoly++) {
- poly_area = mesh_calc_poly_planar_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
+ poly_volume = mesh_calc_poly_volume_and_weighted_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
- madd_v3_v3fl(r_cent, poly_cent, poly_area);
- total_area += poly_area;
+ /* poly_cent is already volume-weighted, so no need to multiply by the volume */
+ add_v3_v3(r_cent, poly_cent);
+ total_volume += poly_volume;
}
/* otherwise we get NAN for 0 polys */
- if (me->totpoly) {
- mul_v3_fl(r_cent, 1.0f / total_area);
+ if (total_volume != 0.0f) {
+ /* multipy by 0.25 to get the correct centroid */
+ /* no need to divide volume by 6 as the centroid is weighted by 6x the volume, so it all cancels out */
+ mul_v3_fl(r_cent, 0.25f / total_volume);
}
- /* zero area faces cause this, fallback to median */
+ /* this can happen for non-manifold objects, fallback to median */
if (UNLIKELY(!is_finite_v3(r_cent))) {
return BKE_mesh_center_median(me, r_cent);
}
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 8562988b5e1..525c0c9728e 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -165,7 +165,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(
vmap->vert[a] = newvlist;
}
- if (use_winding) {
+ if (use_winding) {
MEM_freeN(winding);
}
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index ba890b005d8..4aeddbb4c45 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -584,8 +584,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
int prev_e = ml->e;
ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
fix_flag.loops_edge = true;
- PRINT_ERR("\tPoly %u has invalid edge reference (%d), fixed using edge %u\n",
- sp->index, prev_e, ml->e);
+ PRINT_ERR("\tPoly %u has invalid edge reference (%d, is_removed: %d), fixed using edge %u\n",
+ sp->index, prev_e, IS_REMOVED_EDGE(me), ml->e);
}
else {
PRINT_ERR("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e);
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 6794a8e8f93..dfa8742a295 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -1488,7 +1488,7 @@ void BKE_movieclip_free(MovieClip *clip)
BKE_animdata_free((ID *) clip, false);
}
-MovieClip *BKE_movieclip_copy(Main *bmain, MovieClip *clip)
+MovieClip *BKE_movieclip_copy(Main *bmain, const MovieClip *clip)
{
MovieClip *clip_new;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 3f3b4896653..dd28a534d22 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -921,7 +921,7 @@ static void node_socket_copy(bNodeSocket *dst, bNodeSocket *src)
/* keep socket listorder identical, for copying links */
/* ntree is the target tree */
-bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
+bNode *nodeCopyNode(bNodeTree *ntree, bNode *node)
{
bNode *nnode = MEM_callocN(sizeof(bNode), "dupli node");
bNodeSocket *sock, *oldsock;
@@ -1200,7 +1200,9 @@ 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, Main *bmain, bool skip_database, bool do_id_user, bool do_make_extern, bool copy_previews)
+static bNodeTree *ntreeCopyTree_internal(
+ const bNodeTree *ntree, Main *bmain,
+ bool skip_database, bool do_id_user, bool do_make_extern, bool copy_previews)
{
bNodeTree *newtree;
bNode *node /*, *nnode */ /* UNUSED */, *last;
@@ -1299,11 +1301,11 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski
return newtree;
}
-bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user)
+bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user)
{
return ntreeCopyTree_internal(ntree, bmain, false, do_id_user, true, true);
}
-bNodeTree *ntreeCopyTree(Main *bmain, bNodeTree *ntree)
+bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree)
{
return ntreeCopyTree_ex(ntree, bmain, true);
}
@@ -1828,7 +1830,7 @@ void ntreeFreeTree(bNodeTree *ntree)
if (tntree == ntree)
break;
if (tntree == NULL) {
- BKE_libblock_free_data(G.main, &ntree->id);
+ BKE_libblock_free_data(&ntree->id, true);
}
}
@@ -3568,6 +3570,7 @@ static void registerShaderNodes(void)
register_node_type_sh_background();
register_node_type_sh_bsdf_anisotropic();
register_node_type_sh_bsdf_diffuse();
+ register_node_type_sh_bsdf_principled();
register_node_type_sh_bsdf_glossy();
register_node_type_sh_bsdf_glass();
register_node_type_sh_bsdf_translucent();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 6e754755cf3..f3086396c3a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -127,6 +127,7 @@
#endif
#include "CCGSubSurf.h"
+#include "atomic_ops.h"
#include "GPU_material.h"
@@ -319,19 +320,24 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
/* free data derived from mesh, called when mesh changes or is freed */
void BKE_object_free_derived_caches(Object *ob)
{
- /* also serves as signal to remake texspace */
+ /* Also serves as signal to remake texspace.
+ *
+ * NOTE: This function can be called from threads on different objects
+ * sharing same data datablock. So we need to ensure atomic nature of
+ * data modification here.
+ */
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
if (me && me->bb) {
- me->bb->flag |= BOUNDBOX_DIRTY;
+ atomic_fetch_and_or_uint32((uint*)&me->bb->flag, BOUNDBOX_DIRTY);
}
}
else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
Curve *cu = ob->data;
if (cu && cu->bb) {
- cu->bb->flag |= BOUNDBOX_DIRTY;
+ atomic_fetch_and_or_uint32((uint*)&cu->bb->flag, BOUNDBOX_DIRTY);
}
}
@@ -876,7 +882,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
return sbn;
}
-BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
+BulletSoftBody *copy_bulletsoftbody(const BulletSoftBody *bsb)
{
BulletSoftBody *bsbn;
@@ -1008,7 +1014,7 @@ void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src)
}
}
-static void copy_object_pose(Object *obn, Object *ob)
+static void copy_object_pose(Object *obn, const Object *ob)
{
bPoseChannel *chan;
@@ -1041,7 +1047,7 @@ static void copy_object_pose(Object *obn, Object *ob)
}
}
-static void copy_object_lod(Object *obn, Object *ob)
+static void copy_object_lod(Object *obn, const Object *ob)
{
BLI_duplicatelist(&obn->lodlevels, &ob->lodlevels);
@@ -1092,7 +1098,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
copy_v3_v3(ob_tar->size, ob_src->size);
}
-Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
+Object *BKE_object_copy_ex(Main *bmain, const Object *ob, bool copy_caches)
{
Object *obn;
ModifierData *md;
@@ -1139,6 +1145,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
/* increase user numbers */
id_us_plus((ID *)obn->data);
+ id_us_plus((ID *)obn->poselib);
id_us_plus((ID *)obn->gpd);
id_us_plus((ID *)obn->dup_group);
@@ -1180,7 +1187,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
}
/* copy objects, will re-initialize cached simulation data */
-Object *BKE_object_copy(Main *bmain, Object *ob)
+Object *BKE_object_copy(Main *bmain, const Object *ob)
{
return BKE_object_copy_ex(bmain, ob, false);
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index e3b801b3193..e9ebd397df0 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -64,6 +64,7 @@
#include "BLI_strict_flags.h"
+#include "BLI_hash.h"
/* Dupli-Geometry */
@@ -180,6 +181,23 @@ static DupliObject *make_dupli(const DupliContext *ctx,
if (ob->type == OB_MBALL)
dob->no_draw = true;
+ /* random number */
+ /* the logic here is designed to match Cycles */
+ dob->random_id = BLI_hash_string(dob->ob->id.name + 2);
+
+ if (dob->persistent_id[0] != INT_MAX) {
+ for (i = 0; i < MAX_DUPLI_RECUR * 2; i++) {
+ dob->random_id = BLI_hash_int_2d(dob->random_id, (unsigned int)dob->persistent_id[i]);
+ }
+ }
+ else {
+ dob->random_id = BLI_hash_int_2d(dob->random_id, 0);
+ }
+
+ if (ctx->object != ob) {
+ dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2));
+ }
+
return dob;
}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 5cb704e4737..e03af585cf2 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -54,6 +54,7 @@
#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_material.h"
#include "BKE_image.h"
@@ -144,18 +145,6 @@ void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob)
else ob->transflag &= ~OB_NEG_SCALE;
}
-void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob,
- struct ModifierData *md)
-{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
- (void) eval_ctx; /* Ignored. */
- (void) scene; /* Ignored. */
- (void) ob; /* Ignored. */
- (void) md; /* Ignored. */
-}
-
void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
@@ -347,3 +336,9 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
}
+
+void BKE_object_eval_cloth(EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *object)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, object->id.name);
+ BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);
+}
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 621ac9c2480..537c8926a5b 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -334,10 +334,10 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
i1 = i1 % oc->_M;
j1 = j1 % oc->_N;
-
#define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
frac_z))
+
{
if (oc->_do_disp_y) {
ocr->disp[1] = BILERP(oc->_disp_y);
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 489fc2f3710..64f90ef5c52 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -450,7 +450,7 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na
break;
}
/* else create it */
- /* fall-through */
+ ATTR_FALLTHROUGH;
}
case PF_WRITE_LOCAL:
if (writePackedFile(reports, local_name, pf, 1) == RET_OK) {
@@ -471,7 +471,7 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na
break;
}
/* else create it */
- /* fall-through */
+ ATTR_FALLTHROUGH;
}
case PF_WRITE_ORIGINAL:
if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 6b954f060d3..c7cfe55f659 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -314,7 +314,7 @@ PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
return pc;
}
-PaintCurve *BKE_paint_curve_copy(Main *bmain, PaintCurve *pc)
+PaintCurve *BKE_paint_curve_copy(Main *bmain, const PaintCurve *pc)
{
PaintCurve *pc_new;
@@ -396,7 +396,7 @@ Palette *BKE_palette_add(Main *bmain, const char *name)
return palette;
}
-Palette *BKE_palette_copy(Main *bmain, Palette *palette)
+Palette *BKE_palette_copy(Main *bmain, const Palette *palette)
{
Palette *palette_new;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 228ae6afaba..fe7138f6774 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -590,7 +590,7 @@ void psys_free(Object *ob, ParticleSystem *psys)
BLI_bvhtree_free(psys->bvhtree);
BLI_kdtree_free(psys->tree);
-
+
if (psys->fluid_springs)
MEM_freeN(psys->fluid_springs);
@@ -3326,7 +3326,7 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
part->roughcurve = cumap;
}
-ParticleSettings *BKE_particlesettings_copy(Main *bmain, ParticleSettings *part)
+ParticleSettings *BKE_particlesettings_copy(Main *bmain, const ParticleSettings *part)
{
ParticleSettings *partn;
int a;
@@ -3466,7 +3466,8 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
case TEXCO_UV:
if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec))
break;
- /* no break, failed to get uv's, so let's try orco's */
+ /* no break, failed to get uv's, so let's try orco's */
+ ATTR_FALLTHROUGH;
case TEXCO_ORCO:
copy_v3_v3(texvec, orco);
break;
@@ -3538,7 +3539,8 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
case TEXCO_UV:
if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec))
break;
- /* no break, failed to get uv's, so let's try orco's */
+ /* no break, failed to get uv's, so let's try orco's */
+ ATTR_FALLTHROUGH;
case TEXCO_ORCO:
psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, 0, 0, 0, texvec, 0);
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index 842de869291..bfcda89a635 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -355,9 +355,13 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
{
const float step_length = 1.0f / (float)(totkeys - 1);
-
float cur_length = 0.0f;
-
+
+ if (max_length <= 0.0f) {
+ keys->segments = -1;
+ totkeys = 0;
+ }
+
/* we have to correct velocity because of kink & clump */
for (k = 0, key = keys; k < totkeys; ++k, ++key) {
if (k >= 2) {
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 44cf5b119c1..6603521c42f 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -1092,7 +1092,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* 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)) {
+ if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents != 0.0f)) {
int *orig_index = NULL;
if (from == PART_FROM_VERT) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 943dc781246..3f9a92a5577 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -1000,7 +1000,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
part=psys->part;
/* get precise emitter matrix if particle is born */
- if (part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
+ if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
evaluate_emitter_anim(sim->scene, sim->ob, pa->time);
psys->flag |= PSYS_OB_ANIM_RESTORE;
@@ -1183,7 +1183,7 @@ static void set_keyed_keys(ParticleSimulationData *sim)
key->time = pa->time;
}
- if (psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f)
+ if (psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f)
k++;
ksim.psys->flag |= keyed_flag;
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 4fe4d6e75a6..53dfffe2b97 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -620,7 +620,7 @@ void BKE_pbvh_free(PBVH *bvh)
if (node->flag & PBVH_Leaf) {
if (node->draw_buffers)
- GPU_free_pbvh_buffers(node->draw_buffers);
+ GPU_pbvh_buffers_free(node->draw_buffers);
if (node->vert_indices)
MEM_freeN((void *)node->vert_indices);
if (node->face_vert_indices)
@@ -635,7 +635,7 @@ void BKE_pbvh_free(PBVH *bvh)
BLI_gset_free(node->bm_other_verts, NULL);
}
}
- GPU_free_pbvh_buffer_multires(&bvh->grid_common_gpu_buffer);
+ GPU_pbvh_multires_buffers_free(&bvh->grid_common_gpu_buffer);
if (bvh->deformed) {
if (bvh->verts) {
@@ -1090,11 +1090,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
PBVHNode *node = nodes[n];
if (node->flag & PBVH_RebuildDrawBuffers) {
- GPU_free_pbvh_buffers(node->draw_buffers);
+ GPU_pbvh_buffers_free(node->draw_buffers);
switch (bvh->type) {
case PBVH_GRIDS:
node->draw_buffers =
- GPU_build_grid_pbvh_buffers(node->prim_indices,
+ GPU_pbvh_grid_buffers_build(node->prim_indices,
node->totprim,
bvh->grid_hidden,
bvh->gridkey.grid_size,
@@ -1102,7 +1102,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
break;
case PBVH_FACES:
node->draw_buffers =
- GPU_build_mesh_pbvh_buffers(node->face_vert_indices,
+ GPU_pbvh_mesh_buffers_build(node->face_vert_indices,
bvh->mpoly, bvh->mloop, bvh->looptri,
bvh->verts,
node->prim_indices,
@@ -1110,42 +1110,44 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
break;
case PBVH_BMESH:
node->draw_buffers =
- GPU_build_bmesh_pbvh_buffers(bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING);
+ GPU_pbvh_bmesh_buffers_build(bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING);
break;
}
-
+
node->flag &= ~PBVH_RebuildDrawBuffers;
}
if (node->flag & PBVH_UpdateDrawBuffers) {
switch (bvh->type) {
case PBVH_GRIDS:
- GPU_update_grid_pbvh_buffers(node->draw_buffers,
- bvh->grids,
- bvh->grid_flag_mats,
- node->prim_indices,
- node->totprim,
- &bvh->gridkey,
- bvh->show_diffuse_color);
+ GPU_pbvh_grid_buffers_update(
+ node->draw_buffers,
+ bvh->grids,
+ bvh->grid_flag_mats,
+ node->prim_indices,
+ node->totprim,
+ &bvh->gridkey,
+ bvh->show_diffuse_color);
break;
case PBVH_FACES:
- GPU_update_mesh_pbvh_buffers(node->draw_buffers,
- bvh->verts,
- node->vert_indices,
- node->uniq_verts +
- node->face_verts,
- CustomData_get_layer(bvh->vdata,
- CD_PAINT_MASK),
- node->face_vert_indices,
- bvh->show_diffuse_color);
+ GPU_pbvh_mesh_buffers_update(
+ node->draw_buffers,
+ bvh->verts,
+ node->vert_indices,
+ node->uniq_verts +
+ node->face_verts,
+ CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
+ node->face_vert_indices,
+ bvh->show_diffuse_color);
break;
case PBVH_BMESH:
- GPU_update_bmesh_pbvh_buffers(node->draw_buffers,
- bvh->bm,
- node->bm_faces,
- node->bm_unique_verts,
- node->bm_other_verts,
- bvh->show_diffuse_color);
+ GPU_pbvh_bmesh_buffers_update(
+ node->draw_buffers,
+ bvh->bm,
+ node->bm_faces,
+ node->bm_unique_verts,
+ node->bm_other_verts,
+ bvh->show_diffuse_color);
break;
}
@@ -1156,15 +1158,15 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
static void pbvh_draw_BB(PBVH *bvh)
{
- GPU_init_draw_pbvh_BB();
+ GPU_pbvh_BB_draw_init();
for (int a = 0; a < bvh->totnode; a++) {
PBVHNode *node = &bvh->nodes[a];
- GPU_draw_pbvh_BB(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0));
+ GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0));
}
- GPU_end_draw_pbvh_BB();
+ GPU_pbvh_BB_draw_end();
}
static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
@@ -1756,7 +1758,7 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
#endif
if (!(node->flag & PBVH_FullyHidden)) {
- GPU_draw_pbvh_buffers(node->draw_buffers,
+ GPU_pbvh_buffers_draw(node->draw_buffers,
data->setMaterial,
data->wireframe,
data->fast);
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index a821578db1a..c5e49883dc6 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -352,7 +352,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
n->layer_disp = NULL;
if (n->draw_buffers) {
- GPU_free_pbvh_buffers(n->draw_buffers);
+ GPU_pbvh_buffers_free(n->draw_buffers);
n->draw_buffers = NULL;
}
n->flag &= ~PBVH_Leaf;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 30eb8dcb287..a7e00a8103a 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3618,9 +3618,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
}
- if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) &&
- (render || bake))
- {
+ if (((cache->flag & PTCACHE_BAKED) == 0) && (render || bake)) {
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
}
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index dc4063b42ed..b163f623d21 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -65,7 +65,7 @@ void BKE_bproperty_free_list(ListBase *lb)
}
}
-bProperty *BKE_bproperty_copy(bProperty *prop)
+bProperty *BKE_bproperty_copy(const bProperty *prop)
{
bProperty *propn;
@@ -80,7 +80,7 @@ bProperty *BKE_bproperty_copy(bProperty *prop)
return propn;
}
-void BKE_bproperty_copy_list(ListBase *lbn, ListBase *lbo)
+void BKE_bproperty_copy_list(ListBase *lbn, const ListBase *lbo)
{
bProperty *prop, *propn;
BKE_bproperty_free_list(lbn); /* in case we are copying to an object with props */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 5353cc26295..390e6dedc3f 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -184,7 +184,7 @@ void BKE_rigidbody_free_constraint(Object *ob)
* be added to relevant groups later...
*/
-RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
+RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob)
{
RigidBodyOb *rboN = NULL;
@@ -204,7 +204,7 @@ RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
return rboN;
}
-RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
+RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob)
{
RigidBodyCon *rbcN = NULL;
@@ -822,7 +822,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z);
RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
- /* fall-through */
+ ATTR_FALLTHROUGH;
case RBC_TYPE_6DOF:
if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */
rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
@@ -1622,8 +1622,8 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
# pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
-struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; }
-struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; }
+struct RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob) { return NULL; }
+struct RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob) { return NULL; }
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {}
void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; }
void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) { zero_v3(r_center); }
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index 7920d8b5696..19d646daf9f 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -87,7 +87,7 @@ bSensor *copy_sensor(bSensor *sens)
return sensn;
}
-void copy_sensors(ListBase *lbn, ListBase *lbo)
+void copy_sensors(ListBase *lbn, const ListBase *lbo)
{
bSensor *sens, *sensn;
@@ -251,7 +251,7 @@ bController *copy_controller(bController *cont)
return contn;
}
-void copy_controllers(ListBase *lbn, ListBase *lbo)
+void copy_controllers(ListBase *lbn, const ListBase *lbo)
{
bController *cont, *contn;
@@ -389,7 +389,7 @@ bActuator *copy_actuator(bActuator *act)
return actn;
}
-void copy_actuators(ListBase *lbn, ListBase *lbo)
+void copy_actuators(ListBase *lbn, const ListBase *lbo)
{
bActuator *act, *actn;
@@ -783,7 +783,7 @@ void BKE_sca_logic_links_remap(Main *bmain, Object *ob_old, Object *ob_new)
* Handle the copying of logic data into a new object, including internal logic links update.
* External links (links between logic bricks of different objects) must be handled separately.
*/
-void BKE_sca_logic_copy(Object *ob_new, Object *ob)
+void BKE_sca_logic_copy(Object *ob_new, const Object *ob)
{
copy_sensors(&ob_new->sensors, &ob->sensors);
copy_controllers(&ob_new->controllers, &ob->controllers);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 906fa0134a0..44b71416bf0 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -233,6 +233,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
/* copy Freestyle settings */
new_srl = scen->r.layers.first;
for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ if (new_srl->prop != NULL) {
+ new_srl->prop = IDP_CopyProperty(new_srl->prop);
+ }
BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig);
if (type == SCE_COPY_FULL) {
for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
@@ -416,11 +419,15 @@ void BKE_scene_free(Scene *sce)
MEM_freeN(sce->r.ffcodecdata.properties);
sce->r.ffcodecdata.properties = NULL;
}
-
+
for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ if (srl->prop != NULL) {
+ IDP_FreeProperty(srl->prop);
+ MEM_freeN(srl->prop);
+ }
BKE_freestyle_config_free(&srl->freestyleConfig);
}
-
+
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->transform_spaces);
BLI_freelistN(&sce->r.layers);
@@ -2063,6 +2070,11 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
BKE_freestyle_config_free(&srl->freestyleConfig);
+ if (srl->prop) {
+ IDP_FreeProperty(srl->prop);
+ MEM_freeN(srl->prop);
+ }
+
BLI_remlink(&scene->r.layers, srl);
MEM_freeN(srl);
@@ -2125,7 +2137,7 @@ bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv)
int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
{
- if (r->mode & R_SIMPLIFY) {
+ if (r->mode & R_SIMPLIFY) {
if (for_render)
return min_ii(r->simplify_subsurf_render, lvl);
else
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 298671beedb..e435d87024e 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -684,7 +684,7 @@ static float invGammaCorrect(float c)
else if (i >= RE_GAMMA_TABLE_SIZE) res = powf(c, valid_inv_gamma);
else res = inv_gamma_range_table[i] +
((c - color_domain_table[i]) * inv_gamfactor_table[i]);
-
+
return res;
}
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index 89c2f76c661..e2f74dbab3c 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -202,21 +202,22 @@ static void whiteBalance_apply_threaded(int width, int height, unsigned char *re
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
int pixel_index = (y * width + x) * 4;
- float result[4], mask[3] = {1.0f, 1.0f, 1.0f};
+ float rgba[4], result[4], mask[3] = {1.0f, 1.0f, 1.0f};
if (rect_float) {
- copy_v3_v3(result, rect_float + pixel_index);
+ copy_v3_v3(rgba, rect_float + pixel_index);
}
else {
- straight_uchar_to_premul_float(result, rect + pixel_index);
+ straight_uchar_to_premul_float(rgba, rect + pixel_index);
}
+ copy_v4_v4(result, rgba);
#if 0
mul_v3_v3(result, multiplier);
#else
/* similar to division without the clipping */
for (int i = 0; i < 3; i++) {
- result[i] = 1.0f - powf(1.0f - result[i], multiplier[i]);
+ result[i] = 1.0f - powf(1.0f - rgba[i], multiplier[i]);
}
#endif
@@ -227,9 +228,9 @@ static void whiteBalance_apply_threaded(int width, int height, unsigned char *re
rgb_uchar_to_float(mask, mask_rect + pixel_index);
}
- result[0] = result[0] * (1.0f - mask[0]) + result[0] * mask[0];
- result[1] = result[1] * (1.0f - mask[1]) + result[1] * mask[1];
- result[2] = result[2] * (1.0f - mask[2]) + result[2] * mask[2];
+ result[0] = rgba[0] * (1.0f - mask[0]) + result[0] * mask[0];
+ result[1] = rgba[1] * (1.0f - mask[1]) + result[1] * mask[1];
+ result[2] = rgba[2] * (1.0f - mask[2]) + result[2] * mask[2];
if (rect_float) {
copy_v3_v3(rect_float + pixel_index, result);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 2de7cd49901..dbdffa54d29 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -1775,7 +1775,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
if (proxy->anim == NULL) {
return NULL;
}
-
+
seq_open_anim_file(context->scene, seq, true);
sanim = seq->anims.first;
@@ -1783,7 +1783,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c
return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE);
}
-
+
if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) {
return NULL;
}
@@ -4190,9 +4190,10 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha
if (free_imbuf) {
if (ibuf_change) {
- if (seq->type == SEQ_TYPE_MOVIE)
+ if (seq->type == SEQ_TYPE_MOVIE) {
BKE_sequence_free_anim(seq);
- if (seq->type == SEQ_TYPE_SPEED) {
+ }
+ else if (seq->type == SEQ_TYPE_SPEED) {
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
}
}
@@ -5182,6 +5183,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */
if (sound->playback_handle == NULL) {
+ BKE_libblock_free(bmain, sound);
#if 0
if (op)
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index b14ed2d67ad..7094d5a3547 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -588,13 +588,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
DerivedMesh *ss_mesh = NULL;
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
- /* remove loop dependencies on derived meshes (TODO should this be done elsewhere?)
- * This also ensure the target is of type OBJ_MESH avoiding crash in `object_get_derived_final` (see T50899). */
- if (smd->target) {
- if (smd->target->type != OB_MESH || smd->target == ob) {
- smd->target = NULL;
- }
- }
+ /* 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/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 03cf33083da..600bc3f453d 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -1856,19 +1856,21 @@ static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len
float m, delta_ij;
int i, j;
if (L < len) {
- for (i=0;i<3;i++)
+ for (i=0;i<3;i++) {
for (j=0;j<3;j++) {
delta_ij = (i==j ? (1.0f): (0.0f));
m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j]));
EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
}
+ }
}
else {
- for (i=0;i<3;i++)
+ for (i=0;i<3;i++) {
for (j=0;j<3;j++) {
m=factor*dir[i]*dir[j];
EIG_linear_solver_matrix_add(ia+i, op+ic+j, m);
}
+ }
}
}
@@ -2233,9 +2235,9 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow)
{
-/* rule we never alter free variables :bp->vec bp->pos in here !
- * this will ruin adaptive stepsize AKA heun! (BM)
- */
+ /* rule we never alter free variables :bp->vec bp->pos in here !
+ * this will ruin adaptive stepsize AKA heun! (BM)
+ */
SoftBody *sb= ob->soft; /* is supposed to be there */
/*BodyPoint *bproot;*/ /* UNUSED */
ListBase *do_effector = NULL;
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index ee6886e3fb2..d00e4b1a0d2 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -68,7 +68,7 @@ void *BKE_speaker_add(Main *bmain, const char *name)
return spk;
}
-Speaker *BKE_speaker_copy(Main *bmain, Speaker *spk)
+Speaker *BKE_speaker_copy(Main *bmain, const Speaker *spk)
{
Speaker *spkn;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 298790a9e9b..466bef7ff36 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -449,7 +449,7 @@ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
return BKE_text_load_ex(bmain, file, relpath, false);
}
-Text *BKE_text_copy(Main *bmain, Text *ta)
+Text *BKE_text_copy(Main *bmain, const Text *ta)
{
Text *tan;
TextLine *line, *tmp;
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 60990c03b0e..1e0659d3d67 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -549,11 +549,11 @@ int colorband_element_remove(struct ColorBand *coba, int index)
if (index < 0 || index >= coba->tot)
return 0;
+ coba->tot--;
for (a = index; a < coba->tot; a++) {
coba->data[a] = coba->data[a + 1];
}
if (coba->cur) coba->cur--;
- coba->tot--;
return 1;
}
@@ -846,7 +846,7 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot)
/* ------------------------------------------------------------------------- */
-Tex *BKE_texture_copy(Main *bmain, Tex *tex)
+Tex *BKE_texture_copy(Main *bmain, const Tex *tex)
{
Tex *texn;
@@ -1263,7 +1263,7 @@ EnvMap *BKE_texture_envmap_add(void)
/* ------------------------------------------------------------------------- */
-EnvMap *BKE_texture_envmap_copy(EnvMap *env)
+EnvMap *BKE_texture_envmap_copy(const EnvMap *env)
{
EnvMap *envn;
int a;
@@ -1336,7 +1336,7 @@ PointDensity *BKE_texture_pointdensity_add(void)
return pd;
}
-PointDensity *BKE_texture_pointdensity_copy(PointDensity *pd)
+PointDensity *BKE_texture_pointdensity_copy(const PointDensity *pd)
{
PointDensity *pdn;
@@ -1430,7 +1430,7 @@ OceanTex *BKE_texture_ocean_add(void)
return ot;
}
-OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot)
+OceanTex *BKE_texture_ocean_copy(const OceanTex *ot)
{
OceanTex *otn = MEM_dupallocN(ot);
@@ -1519,3 +1519,33 @@ void BKE_texture_get_value(
{
BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management);
}
+
+static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePool *pool)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_IMAGE && node->id != NULL) {
+ Image *image = (Image *)node->id;
+ BKE_image_pool_acquire_ibuf(image, NULL, pool);
+ }
+ else if (node->type == NODE_GROUP && node->id != NULL) {
+ /* TODO(sergey): Do we need to control recursion here? */
+ bNodeTree *nested_tree = (bNodeTree *)node->id;
+ texture_nodes_fetch_images_for_pool(nested_tree, pool);
+ }
+ }
+}
+
+/* Make sure all images used by texture are loaded into pool. */
+void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool)
+{
+ if (texture->nodetree != NULL) {
+ texture_nodes_fetch_images_for_pool(texture->nodetree, pool);
+ }
+ else {
+ if (texture->type == TEX_IMAGE) {
+ if (texture->ima != NULL) {
+ BKE_image_pool_acquire_ibuf(texture->ima, NULL, pool);
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 990d250b854..9120d384a16 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -190,7 +190,7 @@ void BKE_tracking_free(MovieTracking *tracking)
}
/* Copy the whole list of tracks. */
-static void tracking_tracks_copy(ListBase *tracks_dst, ListBase *tracks_src, GHash *tracks_mapping)
+static void tracking_tracks_copy(ListBase *tracks_dst, const ListBase *tracks_src, GHash *tracks_mapping)
{
MovieTrackingTrack *track_dst, *track_src;
@@ -210,7 +210,7 @@ static void tracking_tracks_copy(ListBase *tracks_dst, ListBase *tracks_src, GHa
/* copy the whole list of plane tracks (need whole MovieTracking structures due to embedded pointers to tracks).
* WARNING: implies tracking_[dst/src] and their tracks have already been copied. */
-static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, ListBase *plane_tracks_src, GHash *tracks_mapping)
+static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, const ListBase *plane_tracks_src, GHash *tracks_mapping)
{
MovieTrackingPlaneTrack *plane_track_dst, *plane_track_src;
@@ -232,7 +232,7 @@ static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, ListBase *pla
/* Copy reconstruction structure. */
static void tracking_reconstruction_copy(
- MovieTrackingReconstruction *reconstruction_dst, MovieTrackingReconstruction *reconstruction_src)
+ MovieTrackingReconstruction *reconstruction_dst, const MovieTrackingReconstruction *reconstruction_src)
{
*reconstruction_dst = *reconstruction_src;
if (reconstruction_src->cameras) {
@@ -242,14 +242,14 @@ static void tracking_reconstruction_copy(
/* Copy stabilization structure. */
static void tracking_stabilization_copy(
- MovieTrackingStabilization *stabilization_dst, MovieTrackingStabilization *stabilization_src)
+ MovieTrackingStabilization *stabilization_dst, const MovieTrackingStabilization *stabilization_src)
{
*stabilization_dst = *stabilization_src;
}
/* Copy tracking object. */
static void tracking_object_copy(
- MovieTrackingObject *object_dst, MovieTrackingObject *object_src, GHash *tracks_mapping)
+ MovieTrackingObject *object_dst, const MovieTrackingObject *object_src, GHash *tracks_mapping)
{
*object_dst = *object_src;
tracking_tracks_copy(&object_dst->tracks, &object_src->tracks, tracks_mapping);
@@ -258,7 +258,7 @@ static void tracking_object_copy(
}
/* Copy list of tracking objects. */
-static void tracking_objects_copy(ListBase *objects_dst, ListBase *objects_src, GHash *tracks_mapping)
+static void tracking_objects_copy(ListBase *objects_dst, const ListBase *objects_src, GHash *tracks_mapping)
{
MovieTrackingObject *object_dst, *object_src;
@@ -272,7 +272,7 @@ static void tracking_objects_copy(ListBase *objects_dst, ListBase *objects_src,
}
/* Copy tracking structure content. */
-void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src)
+void BKE_tracking_copy(MovieTracking *tracking_dst, const MovieTracking *tracking_src)
{
GHash *tracks_mapping = BLI_ghash_ptr_new(__func__);
@@ -974,8 +974,11 @@ static void track_mask_set_pixel_cb(int x, int x_end, int y, void *user_data)
}
static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height,
- MovieTrackingMarker *marker, bGPDlayer *layer,
- float *mask, int mask_width, int mask_height)
+ const float region_min[2],
+ bGPDlayer *layer,
+ float *mask,
+ int mask_width,
+ int mask_height)
{
bGPDframe *frame = layer->frames.first;
TrackMaskSetPixelData data;
@@ -994,8 +997,8 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height
point = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(int),
"track mask rasterization points");
for (int i = 0; i < stroke->totpoints; i++, point += 2) {
- point[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width;
- point[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height;
+ point[0] = stroke_points[i].x * frame_width - region_min[0];
+ point[1] = stroke_points[i].y * frame_height - region_min[1];
}
/* TODO: add an option to control whether AA is enabled or not */
BLI_bitmap_draw_2d_poly_v2i_n(
@@ -1010,26 +1013,42 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height
}
}
-float *BKE_tracking_track_get_mask(int frame_width, int frame_height,
- MovieTrackingTrack *track, MovieTrackingMarker *marker)
+/* Region is in pixel space, relative to marker's center. */
+float *tracking_track_get_mask_for_region(int frame_width, int frame_height,
+ const float region_min[2],
+ const float region_max[2],
+ MovieTrackingTrack *track)
{
float *mask = NULL;
bGPDlayer *layer = track_mask_gpencil_layer_get(track);
- int mask_width, mask_height;
-
- mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width;
- mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height;
-
- if (layer) {
+ if (layer != NULL) {
+ const int mask_width = region_max[0] - region_min[0];
+ const int mask_height = region_max[1] - region_min[1];
mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask");
-
- track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer,
- mask, mask_width, mask_height);
+ track_mask_gpencil_layer_rasterize(frame_width, frame_height,
+ region_min,
+ layer,
+ mask,
+ mask_width, mask_height);
}
-
return mask;
}
+float *BKE_tracking_track_get_mask(int frame_width, int frame_height,
+ MovieTrackingTrack *track,
+ MovieTrackingMarker *marker)
+{
+ /* Convert normalized space marker's search area to pixel-space region. */
+ const float region_min[2] = {marker->search_min[0] * frame_width,
+ marker->search_min[1] * frame_height};
+ const float region_max[2] = {marker->search_max[0] * frame_width,
+ marker->search_max[1] * frame_height};
+ return tracking_track_get_mask_for_region(frame_width, frame_height,
+ region_min,
+ region_max,
+ track);
+}
+
float BKE_tracking_track_get_weight_for_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker)
{
FCurve *weight_fcurve;
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index 3b56ea271d0..9475925cdda 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -36,8 +36,9 @@
#include "DNA_movieclip_types.h"
#include "DNA_object_types.h" /* SELECT */
-#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
#include "BLI_math.h"
#include "BKE_movieclip.h"
@@ -76,6 +77,9 @@ typedef struct AutoTrackContext {
int num_tracks; /* Number of tracks being tracked. */
AutoTrackOptions *options; /* Per-tracking track options. */
+ /* Array of all tracks, indexed by track_index. */
+ MovieTrackingTrack **tracks;
+
bool backwards;
bool sequence;
int first_frame;
@@ -306,8 +310,15 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
BLI_spin_init(&context->spin_lock);
+ int num_total_tracks = BLI_listbase_count(tracksbase);
+ context->tracks =
+ MEM_callocN(sizeof(MovieTrackingTrack*) * num_total_tracks,
+ "auto track pointers");
+
context->image_accessor =
- tracking_image_accessor_new(context->clips, 1, user->framenr);
+ tracking_image_accessor_new(context->clips, 1,
+ context->tracks, num_total_tracks,
+ user->framenr);
context->autotrack =
libmv_autoTrackNew(context->image_accessor->libmv_accessor);
@@ -361,6 +372,7 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
options->use_keyframe_match =
track->pattern_match == TRACK_MATCH_KEYFRAME;
}
+ context->tracks[track_index] = track;
++track_index;
}
@@ -565,6 +577,7 @@ void BKE_autotrack_context_free(AutoTrackContext *context)
libmv_autoTrackDestroy(context->autotrack);
tracking_image_accessor_destroy(context->image_accessor);
MEM_freeN(context->options);
+ MEM_freeN(context->tracks);
BLI_spin_end(&context->spin_lock);
MEM_freeN(context);
}
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 722fc89a75f..b8dfb217c16 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -203,7 +203,7 @@ static float get_animated_scaleinf(StabContext *ctx, int framenr)
static void get_animated_target_pos(StabContext *ctx,
int framenr,
- float target_pos[2])
+ float target_pos[2])
{
target_pos[0] = fetch_from_fcurve(ctx->target_pos[0],
framenr,
@@ -755,7 +755,8 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
if (ok) {
r_ref_pos[0] /= weight_sum;
r_ref_pos[1] /= weight_sum;
- } else {
+ }
+ else {
/* No usable tracking data on any track on this frame.
* Use data from neighbouring frames to extrapolate...
*/
@@ -784,7 +785,8 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
* Also default to this frame when we're in a gap */
average_marker_positions(ctx, next_lower, r_ref_pos);
- } else if (next_higher < MAXFRAME) {
+ }
+ else if (next_higher < MAXFRAME) {
average_marker_positions(ctx, next_higher, r_ref_pos);
}
use_values_from_fcurves(ctx, false);
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index 1c056cda68d..a95399562d5 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -875,8 +875,64 @@ static void accessor_release_image_callback(libmv_CacheKey cache_key)
IMB_freeImBuf(ibuf);
}
+static libmv_CacheKey accessor_get_mask_for_track_callback(
+ libmv_FrameAccessorUserData* user_data,
+ int clip_index,
+ int frame,
+ int track_index,
+ const libmv_Region *region,
+ float **r_destination,
+ int *r_width,
+ int *r_height)
+{
+ /* Perform sanity checks first. */
+ TrackingImageAccessor *accessor = (TrackingImageAccessor *) user_data;
+ BLI_assert(clip_index < accessor->num_clips);
+ BLI_assert(track_index < accessor->num_tracks);
+ MovieTrackingTrack *track = accessor->tracks[track_index];
+ /* Early output, track does not use mask. */
+ if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) == 0) {
+ return NULL;
+ }
+ MovieClip *clip = accessor->clips[clip_index];
+ /* Construct fake user so we can access movie clip. */
+ MovieClipUser user;
+ int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame);
+ BKE_movieclip_user_set_frame(&user, scene_frame);
+ user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
+ user.render_flag = 0;
+ /* Get frame width and height so we can convert stroke coordinates
+ * and other things from normalized to pixel space.
+ */
+ int frame_width, frame_height;
+ BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
+ /* Actual mask sampling. */
+ MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, frame);
+ const float region_min[2] = {region->min[0] - marker->pos[0] * frame_width,
+ region->min[1] - marker->pos[1] * frame_height};
+ const float region_max[2] = {region->max[0] - marker->pos[0] * frame_width,
+ region->max[1] - marker->pos[1] * frame_height};
+ *r_destination = tracking_track_get_mask_for_region(frame_width, frame_height,
+ region_min,
+ region_max,
+ track);
+ *r_width = region->max[0] - region->min[0];
+ *r_height = region->max[1] - region->min[1];
+ return *r_destination;
+}
+
+static void accessor_release_mask_callback(libmv_CacheKey cache_key)
+{
+ if (cache_key != NULL) {
+ float *mask = (float *)cache_key;
+ MEM_freeN(mask);
+ }
+}
+
TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP],
int num_clips,
+ MovieTrackingTrack **tracks,
+ int num_tracks,
int start_frame)
{
TrackingImageAccessor *accessor =
@@ -891,12 +947,16 @@ TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR
memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *));
accessor->num_clips = num_clips;
+ accessor->tracks = tracks;
+ accessor->num_tracks = num_tracks;
accessor->start_frame = start_frame;
accessor->libmv_accessor =
libmv_FrameAccessorNew((libmv_FrameAccessorUserData *) accessor,
accessor_get_image_callback,
- accessor_release_image_callback);
+ accessor_release_image_callback,
+ accessor_get_mask_for_track_callback,
+ accessor_release_mask_callback);
return accessor;
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index caa9a1e357f..363c36e644d 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -119,7 +119,7 @@ World *add_world(Main *bmain, const char *name)
return wrld;
}
-World *BKE_world_copy(Main *bmain, World *wrld)
+World *BKE_world_copy(Main *bmain, const World *wrld)
{
World *wrldn;
int a;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 9994d479ce7..156b74f5c3d 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -568,7 +568,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int
if (context->ffmpeg_crf >= 0) {
ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf);
- } else {
+ }
+ else {
c->bit_rate = context->ffmpeg_video_bitrate * 1000;
c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
@@ -576,8 +577,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int
}
if (context->ffmpeg_preset) {
- char const * preset_name;
- switch(context->ffmpeg_preset) {
+ char const *preset_name;
+ switch (context->ffmpeg_preset) {
case FFM_PRESET_ULTRAFAST: preset_name = "ultrafast"; break;
case FFM_PRESET_SUPERFAST: preset_name = "superfast"; break;
case FFM_PRESET_VERYFAST: preset_name = "veryfast"; break;
diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c
index 212af76a7e8..4757186f546 100644
--- a/source/blender/blenkernel/intern/writeframeserver.c
+++ b/source/blender/blenkernel/intern/writeframeserver.c
@@ -268,11 +268,7 @@ int BKE_frameserver_loop(void *context_v, RenderData *rd, ReportList *UNUSED(rep
struct timeval tv;
struct sockaddr_in addr;
int len, rval;
-#ifdef FREE_WINDOWS
- int socklen;
-#else
unsigned int socklen;
-#endif
char buf[4096];
FrameserverContext *context = context_v;
diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h
index 591ee4d0d01..1a68a1cac6a 100644
--- a/source/blender/blenkernel/tracking_private.h
+++ b/source/blender/blenkernel/tracking_private.h
@@ -105,6 +105,13 @@ struct MovieTrackingMarker *tracking_get_keyframed_marker(
int current_frame,
bool backwards);
+/*********************** Masking *************************/
+
+float *tracking_track_get_mask_for_region(int frame_width, int frame_height,
+ const float region_min[2],
+ const float region_max[2],
+ MovieTrackingTrack *track);
+
/*********************** Frame accessr *************************/
struct libmv_FrameAccessor;
@@ -114,12 +121,16 @@ typedef struct TrackingImageAccessor {
struct MovieCache *cache;
struct MovieClip *clips[MAX_ACCESSOR_CLIP];
int num_clips;
+ struct MovieTrackingTrack **tracks;
+ int num_tracks;
int start_frame;
struct libmv_FrameAccessor *libmv_accessor;
} TrackingImageAccessor;
TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP],
int num_clips,
+ MovieTrackingTrack **tracks,
+ int num_tracks,
int start_frame);
void tracking_image_accessor_destroy(TrackingImageAccessor *accessor);
diff --git a/source/blender/blenlib/BLI_alloca.h b/source/blender/blenlib/BLI_alloca.h
index b44e6c66d2a..4fa69a24966 100644
--- a/source/blender/blenlib/BLI_alloca.h
+++ b/source/blender/blenlib/BLI_alloca.h
@@ -29,10 +29,6 @@
/* BLI_array_alloca / alloca */
-#if defined(__MINGW32__)
-# include <malloc.h> /* mingw needs for alloca() */
-#endif
-
#if defined(__GNUC__) || defined(__clang__)
#if defined(__cplusplus) && (__cplusplus > 199711L)
#define BLI_array_alloca(arr, realsize) \
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index c645ff06c00..74f24c808ff 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -137,8 +137,8 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
#define BLI_array_free(arr) \
if (arr && (char *)arr != _##arr##_static) { \
- BLI_array_fake_user(arr); \
- MEM_freeN(arr); \
+ BLI_array_fake_user(arr); \
+ MEM_freeN(arr); \
} (void)0
#define BLI_array_pop(arr) ( \
diff --git a/source/blender/blenlib/BLI_compiler_attrs.h b/source/blender/blenlib/BLI_compiler_attrs.h
index f0d32670229..4c548654e33 100644
--- a/source/blender/blenlib/BLI_compiler_attrs.h
+++ b/source/blender/blenlib/BLI_compiler_attrs.h
@@ -92,4 +92,12 @@
# define ATTR_PRINTF_FORMAT(format_param, dots_param)
#endif
+/* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */
+#if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */
+#define ATTR_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define ATTR_FALLTHROUGH ((void)0)
+#endif
+
+
#endif /* __BLI_COMPILER_ATTRS_H__ */
diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h
index 8edbc25bcbc..01fc9d70207 100644
--- a/source/blender/blenlib/BLI_compiler_compat.h
+++ b/source/blender/blenlib/BLI_compiler_compat.h
@@ -32,11 +32,6 @@
# define alloca _alloca
#endif
-/* alloca is defined here for MinGW32 */
-#ifdef __MINGW32__
-# include <malloc.h>
-#endif
-
#if defined(__cplusplus) && ((__cplusplus >= 201103L) || defined(_MSC_VER))
# define HAS_CPP11_FEATURES
#endif
diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h
index 7aa1c30e449..b26accc7f78 100644
--- a/source/blender/blenlib/BLI_dynstr.h
+++ b/source/blender/blenlib/BLI_dynstr.h
@@ -43,11 +43,14 @@
#include "BLI_compiler_attrs.h"
struct DynStr;
+struct MemArena;
/** The abstract DynStr type */
typedef struct DynStr DynStr;
DynStr *BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+DynStr *BLI_dynstr_new_memarena(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL();
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL();
@@ -56,8 +59,9 @@ void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format
int BLI_dynstr_get_len(DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
char *BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict str) ATTR_NONNULL();
+
+void BLI_dynstr_clear(DynStr *ds) ATTR_NONNULL();
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL();
#endif /* __BLI_DYNSTR_H__ */
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 91d139c7085..5c1fa57886a 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -65,10 +65,8 @@ int BLI_create_symlink(const char *path, const char *to) ATTR_NONNULL();
/* keep in sync with the definition of struct direntry in BLI_fileops_types.h */
#ifdef WIN32
-# if defined(_MSC_VER) || defined(__MINGW64__)
+# if defined(_MSC_VER)
typedef struct _stat64 BLI_stat_t;
-# elif defined(__MINGW32__)
-typedef struct _stati64 BLI_stat_t;
# else
typedef struct _stat BLI_stat_t;
# endif
diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h
index 0cf8c8ddb4a..0ffa3276f1f 100644
--- a/source/blender/blenlib/BLI_fileops_types.h
+++ b/source/blender/blenlib/BLI_fileops_types.h
@@ -35,7 +35,7 @@
#include <sys/stat.h>
-#if defined(WIN32) && !defined(FREE_WINDOWS)
+#if defined(WIN32)
typedef unsigned int mode_t;
#endif
@@ -50,10 +50,8 @@ struct direntry {
const char *relname;
const char *path;
#ifdef WIN32 /* keep in sync with the definition of BLI_stat_t in BLI_fileops.h */
-# if defined(_MSC_VER) || defined(__MINGW64__)
+# if defined(_MSC_VER)
struct _stat64 s;
-# elif defined(__MINGW32__)
- struct _stati64 s;
# else
struct _stat s;
# endif
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 7e3a009ede8..7cf3e97bdc9 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -167,6 +167,8 @@ unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr);
unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr);
bool BLI_ghashutil_intcmp(const void *a, const void *b);
+size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b);
+
unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
#define BLI_ghashutil_inthash_v4(key) ( \
@@ -294,6 +296,25 @@ double BLI_ghash_calc_quality(GHash *gh);
double BLI_gset_calc_quality(GSet *gs);
#endif /* GHASH_INTERNAL_API */
+#define GHASH_FOREACH_BEGIN(type, var, what) \
+ do { \
+ GHashIterator gh_iter##var; \
+ GHASH_ITER(gh_iter##var, what) { \
+ type var = (type)(BLI_ghashIterator_getValue(&gh_iter##var)); \
+
+#define GHASH_FOREACH_END() \
+ } \
+ } while(0)
+
+#define GSET_FOREACH_BEGIN(type, var, what) \
+ do { \
+ GSetIterator gh_iter##var; \
+ GSET_ITER(gh_iter##var, what) { \
+ type var = (type)(BLI_gsetIterator_getKey(&gh_iter##var));
+
+#define GSET_FOREACH_END() \
+ } \
+ } while(0)
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h
new file mode 100644
index 00000000000..e849e5f8f61
--- /dev/null
+++ b/source/blender/blenlib/BLI_hash.h
@@ -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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_HASH_H__
+#define __BLI_HASH_H__
+
+/** \file BLI_hash.h
+ * \ingroup bli
+ */
+
+BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
+{
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+
+ unsigned int a, b, c;
+
+ a = b = c = 0xdeadbeef + (2 << 2) + 13;
+ a += kx;
+ b += ky;
+
+ c ^= b; c -= rot(b, 14);
+ a ^= c; a -= rot(c, 11);
+ b ^= a; b -= rot(a, 25);
+ c ^= b; c -= rot(b, 16);
+ a ^= c; a -= rot(c, 4);
+ b ^= a; b -= rot(a, 14);
+ c ^= b; c -= rot(b, 24);
+
+ return c;
+
+#undef rot
+}
+
+BLI_INLINE unsigned int BLI_hash_string(const char *str)
+{
+ unsigned int i = 0, c;
+
+ while ((c = *str++)) {
+ i = i * 37 + c;
+ }
+ return i;
+}
+
+BLI_INLINE unsigned int BLI_hash_int(unsigned int k)
+{
+ return BLI_hash_int_2d(k, 0);
+}
+
+#endif // __BLI_HASH_H__
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index ba565fca522..564659ad21e 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -36,7 +36,7 @@
*/
#ifdef __cplusplus
-extern "C" {
+extern "C" {
#endif
struct BVHTree;
@@ -62,7 +62,7 @@ typedef struct BVHTreeNearest {
int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */
float co[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */
float no[3]; /* normal at nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */
- float dist_sq; /* squared distance to search arround */
+ float dist_sq; /* squared distance to search around */
int flags;
} BVHTreeNearest;
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index 96349a7b066..b06944e4985 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -67,6 +67,7 @@ void *BLI_poptail(ListBase *listbase) ATTR_NONNULL(1);
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1);
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1);
+void BLI_insertlinkreplace(ListBase *listbase, void *v_l_src, void *v_l_dst) ATTR_NONNULL(1, 2, 3);
void BLI_listbase_sort(struct ListBase *listbase, int (*cmp)(const void *, const void *)) ATTR_NONNULL(1, 2);
void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1, 2);
bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL();
@@ -124,6 +125,11 @@ if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \
(lb_iter != lb_init)); \
}
+#define LINKLIST_FOREACH(type, var, list) \
+ for (type var = (type)((list)->first); \
+ var != NULL; \
+ var = (type)(((Link*)(var))->next))
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index d60be30e10d..e059327a490 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -218,8 +218,12 @@ float angle_wrap_deg(float angle);
float angle_compat_rad(float angle, float angle_compat);
-int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up,
- float r_mat[3][3]);
+bool mat3_from_axis_conversion(
+ int src_forward, int src_up, int dst_forward, int dst_up,
+ float r_mat[3][3]);
+bool mat3_from_axis_conversion_single(
+ int src_axis, int dst_axis,
+ float r_mat[3][3]);
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 8e0884ba347..43f414f376a 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -286,6 +286,8 @@ 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 cos_v2v2v2(const float p1[2], const float p2[2], const float p3[2]) ATTR_WARN_UNUSED_RESULT;
+float angle_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT;
+float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[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;
float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT;
@@ -299,6 +301,8 @@ void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2]);
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3]);
void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3]);
void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2]);
+void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3]);
+void project_plane_normalized_v2_v2v2(float out[2], const float p[2], const float v_plane[2]);
void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3]);
void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3]);
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index baa1f792018..b59e7f99d59 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -39,20 +39,12 @@ extern "C" {
struct ListBase;
-#ifdef WIN32
-#define SEP '\\'
-#define ALTSEP '/'
-#else
-#define SEP '/'
-#define ALTSEP '\\'
-#endif
-
void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1);
void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1);
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file);
void BLI_make_exist(char *dir);
-void BLI_make_existing_file(const char *name);
+bool BLI_make_existing_file(const char *name);
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen);
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);
@@ -60,7 +52,13 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen,
const char *__restrict file) ATTR_NONNULL();
void BLI_join_dirfile(char *__restrict string, const size_t maxlen,
const char *__restrict dir, const char *__restrict file) ATTR_NONNULL();
+size_t BLI_path_join(
+ char *__restrict dst, const size_t dst_len,
+ const char *path_first, ...) ATTR_NONNULL(1, 3) ATTR_SENTINEL(0);
const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+bool BLI_path_name_at_index(
+ const char *__restrict path, const int index,
+ int *__restrict r_offset, int *__restrict r_len) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
#if 0
typedef enum bli_rebase_state {
@@ -83,7 +81,6 @@ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen);
#endif
bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name);
-void BLI_getlastdir(const char *dir, char *last, const size_t maxlen);
bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
bool BLI_testextensie_n(const char *str, ...) ATTR_NONNULL(1) ATTR_SENTINEL(0);
bool BLI_testextensie_array(const char *str, const char **ext_array) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
@@ -143,6 +140,18 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char
# define FILE_MAX 1024
#endif
+#ifdef WIN32
+# define SEP '\\'
+# define ALTSEP '/'
+# define SEP_STR "\\"
+# define ALTSEP_STR "/"
+#else
+# define SEP '/'
+# define ALTSEP '\\'
+# define SEP_STR "/"
+# define ALTSEP_STR "\\"
+#endif
+
/* Parent and current dir helpers. */
#define FILENAME_PARENT ".."
#define FILENAME_CURRENT "."
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index 041679ef876..21b9c75ac35 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -97,6 +97,7 @@ void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2);
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src);
void BLI_rcti_rctf_copy_floor(struct rcti *dst, const struct rctf *src);
+void BLI_rcti_rctf_copy_round(struct rcti *dst, const struct rctf *src);
void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle);
diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h
index 222005ee92e..d54f2a7bab2 100644
--- a/source/blender/blenlib/BLI_stack.h
+++ b/source/blender/blenlib/BLI_stack.h
@@ -30,6 +30,10 @@
#include "BLI_compiler_attrs.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct BLI_Stack BLI_Stack;
BLI_Stack *BLI_stack_new_ex(
@@ -55,4 +59,8 @@ size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONN
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BLI_STACK_H__ */
diff --git a/source/blender/blenlib/BLI_strict_flags.h b/source/blender/blenlib/BLI_strict_flags.h
index 964ee06469d..86b7285655e 100644
--- a/source/blender/blenlib/BLI_strict_flags.h
+++ b/source/blender/blenlib/BLI_strict_flags.h
@@ -30,6 +30,8 @@
#ifdef __GNUC__
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
# pragma GCC diagnostic error "-Wsign-compare"
+# endif
+# if __GNUC__ >= 6 /* gcc6+ only */
# pragma GCC diagnostic error "-Wconversion"
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h
index 9d8222c575d..9477f61713c 100644
--- a/source/blender/blenlib/BLI_sys_types.h
+++ b/source/blender/blenlib/BLI_sys_types.h
@@ -65,8 +65,8 @@ typedef uint64_t u_int64_t;
#include <inttypes.h>
-/* MinGW and MSVC >= 2010 */
-#elif defined(FREE_WINDOWS) || defined(_MSC_VER)
+/* MSVC >= 2010 */
+#elif defined(_MSC_VER)
#include <stdint.h>
#else
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index c3c587275e1..721327d26a8 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -106,6 +106,13 @@ void *BLI_task_pool_userdata(TaskPool *pool);
/* optional mutex to use from run function */
ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
+/* Delayed push, use that to reduce thread overhead by accumulating
+ * all new tasks into local queue first and pushing it to scheduler
+ * from within a single mutex lock.
+ */
+void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id);
+void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id);
+
/* Parallel for routines */
typedef void (*TaskParallelRangeFunc)(void *userdata, const int iter);
typedef void (*TaskParallelRangeFuncEx)(void *userdata, void *userdata_chunk, const int iter, const int thread_id);
diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h
index b421b7dbb90..6fbbed01400 100644
--- a/source/blender/blenlib/BLI_winstuff.h
+++ b/source/blender/blenlib/BLI_winstuff.h
@@ -37,15 +37,6 @@
# error "This include is for Windows only!"
#endif
-#ifdef FREE_WINDOWS
-# ifdef WINVER
-# undef WINVER
-# endif
-
-/* Some stuff requires WINVER 0x500, but mingw's default is 0x400 */
-# define WINVER 0x0501
-#endif
-
#define WIN32_LEAN_AND_MEAN
#ifndef WIN32_SKIP_HKEY_PROTECTION
@@ -94,7 +85,7 @@ extern "C" {
# define snprintf _snprintf
#endif
-#if defined(_MSC_VER) || (defined(FREE_WINDOWS) && !defined(FREE_WINDOWS64))
+#if defined(_MSC_VER)
# define R_OK 4
# define W_OK 2
// not accepted by access() on windows
@@ -102,28 +93,22 @@ extern "C" {
# define F_OK 0
#endif
-#ifndef FREE_WINDOWS
typedef unsigned int mode_t;
-#endif
/* use functions that take a 64 bit offset for files larger than 4GB */
-#ifndef FREE_WINDOWS
-# include <stdio.h>
-# define fseek(stream, offset, origin) _fseeki64(stream, offset, origin)
-# define ftell(stream) _ftelli64(stream)
-# define lseek(fd, offset, origin) _lseeki64(fd, offset, origin)
-# define tell(fd) _telli64(fd)
-#endif
+#include <stdio.h>
+#define fseek(stream, offset, origin) _fseeki64(stream, offset, origin)
+#define ftell(stream) _ftelli64(stream)
+#define lseek(fd, offset, origin) _lseeki64(fd, offset, origin)
+#define tell(fd) _telli64(fd)
+
-/* mingw using _SSIZE_T_ to declare ssize_t type */
#ifndef _SSIZE_T_
# define _SSIZE_T_
/* python uses HAVE_SSIZE_T */
# ifndef HAVE_SSIZE_T
# define HAVE_SSIZE_T 1
-# ifndef FREE_WINDOWS64
typedef long ssize_t;
-# endif
# endif
#endif
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 3277519c66e..fcb02a86a84 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -152,6 +152,7 @@ set(SRC
BLI_ghash.h
BLI_graph.h
BLI_gsqueue.h
+ BLI_hash.h
BLI_hash_md5.h
BLI_hash_mm2a.h
BLI_heap.h
diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c
index ecd4a6e6b09..bce6614beb5 100644
--- a/source/blender/blenlib/intern/BLI_dynstr.c
+++ b/source/blender/blenlib/intern/BLI_dynstr.c
@@ -35,6 +35,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_memarena.h"
#include "BLI_string.h"
#include "BLI_dynstr.h"
@@ -64,6 +65,7 @@ struct DynStrElem {
struct DynStr {
DynStrElem *elems, *last;
int curlen;
+ MemArena *memarena;
};
/***/
@@ -78,11 +80,32 @@ DynStr *BLI_dynstr_new(void)
DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr");
ds->elems = ds->last = NULL;
ds->curlen = 0;
+ ds->memarena = NULL;
return ds;
}
/**
+ * Create a new DynStr.
+ *
+ * \return Pointer to a new DynStr.
+ */
+DynStr *BLI_dynstr_new_memarena(void)
+{
+ DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr");
+ ds->elems = ds->last = NULL;
+ ds->curlen = 0;
+ ds->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ return ds;
+}
+
+BLI_INLINE void *dynstr_alloc(DynStr *__restrict ds, size_t size)
+{
+ return ds->memarena ? BLI_memarena_alloc(ds->memarena, size) : malloc(size);
+}
+
+/**
* Append a c-string to a DynStr.
*
* \param ds The DynStr to append to.
@@ -90,10 +113,10 @@ DynStr *BLI_dynstr_new(void)
*/
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr)
{
- DynStrElem *dse = malloc(sizeof(*dse));
+ DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse));
int cstrlen = strlen(cstr);
- dse->str = malloc(cstrlen + 1);
+ dse->str = dynstr_alloc(ds, cstrlen + 1);
memcpy(dse->str, cstr, cstrlen + 1);
dse->next = NULL;
@@ -114,10 +137,10 @@ void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr)
*/
void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len)
{
- DynStrElem *dse = malloc(sizeof(*dse));
+ DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse));
int cstrlen = BLI_strnlen(cstr, len);
- dse->str = malloc(cstrlen + 1);
+ dse->str = dynstr_alloc(ds, cstrlen + 1);
memcpy(dse->str, cstr, cstrlen);
dse->str[cstrlen] = '\0';
dse->next = NULL;
@@ -296,22 +319,41 @@ char *BLI_dynstr_get_cstring(DynStr *ds)
}
/**
+ * Clear the DynStr
+ *
+ * \param ds The DynStr to clear.
+ */
+void BLI_dynstr_clear(DynStr *ds)
+{
+ if (ds->memarena) {
+ BLI_memarena_clear(ds->memarena);
+ }
+ else {
+ for (DynStrElem *dse_next, *dse = ds->elems; dse; dse = dse_next) {
+ dse_next = dse->next;
+
+ free(dse->str);
+ free(dse);
+ }
+ }
+
+ ds->elems = ds->last = NULL;
+ ds->curlen = 0;
+}
+
+/**
* Free the DynStr
*
* \param ds The DynStr to free.
*/
void BLI_dynstr_free(DynStr *ds)
{
- DynStrElem *dse;
-
- for (dse = ds->elems; dse; ) {
- DynStrElem *n = dse->next;
-
- free(dse->str);
- free(dse);
-
- dse = n;
+ if (ds->memarena) {
+ BLI_memarena_free(ds->memarena);
}
-
+ else {
+ BLI_dynstr_clear(ds);
+ }
+
MEM_freeN(ds);
}
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 944ee18e6b2..69dee12c713 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -116,6 +116,12 @@ struct GHash {
};
+/* -------------------------------------------------------------------- */
+/* GHash API */
+
+/** \name Internal Utility API
+ * \{ */
+
BLI_INLINE void ghash_entry_copy(
GHash *gh_dst, Entry *dst, GHash *gh_src, Entry *src,
GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
@@ -132,12 +138,6 @@ BLI_INLINE void ghash_entry_copy(
}
}
-/* -------------------------------------------------------------------- */
-/* GHash API */
-
-/** \name Internal Utility API
- * \{ */
-
/**
* Get the full hash for a key.
*/
@@ -1225,6 +1225,11 @@ bool BLI_ghashutil_intcmp(const void *a, const void *b)
return (a != b);
}
+size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
+{
+ return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
+}
+
/**
* This function implements the widely used "djb" hash apparently posted
* by Daniel Bernstein to comp.lang.c some time ago. The 32 bit
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 19d9711922e..e5ca53a0193 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -55,12 +55,20 @@
#include "BLI_stack.h"
#include "BLI_kdopbvh.h"
#include "BLI_math.h"
-#include "BLI_strict_flags.h"
#include "BLI_task.h"
+#include "BLI_strict_flags.h"
+
/* used for iterative_raycast */
// #define USE_SKIP_LINKS
+/* Use to print balanced output. */
+// #define USE_PRINT_TREE
+
+/* Check tree is valid. */
+// #define USE_VERIFY_TREE
+
+
#define MAX_TREETYPE 32
/* Setting zero so we can catch bugs in BLI_task/KDOPBVH.
@@ -129,7 +137,7 @@ typedef struct BVHOverlapData_Thread {
} BVHOverlapData_Thread;
typedef struct BVHNearestData {
- BVHTree *tree;
+ const BVHTree *tree;
const float *co;
BVHTree_NearestPointCallback callback;
void *userdata;
@@ -139,7 +147,7 @@ typedef struct BVHNearestData {
} BVHNearestData;
typedef struct BVHRayCastData {
- BVHTree *tree;
+ const BVHTree *tree;
BVHTree_RayCastCallback callback;
void *userdata;
@@ -171,9 +179,9 @@ typedef struct BVHRayCastData {
*/
const float bvhtree_kdop_axes[13][3] = {
- {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0},
- {1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0},
- {0, 1.0, -1.0}
+ {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0},
+ {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0},
+ {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, {0, 1.0, -1.0}
};
@@ -321,11 +329,16 @@ static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode *x, int axis)
{
int i = lo, j = hi;
while (1) {
- while ((a[i])->bv[axis] < x->bv[axis]) i++;
+ while (a[i]->bv[axis] < x->bv[axis]) {
+ i++;
+ }
j--;
- while (x->bv[axis] < (a[j])->bv[axis]) j--;
- if (!(i < j))
+ while (x->bv[axis] < a[j]->bv[axis]) {
+ j--;
+ }
+ if (!(i < j)) {
return i;
+ }
SWAP(BVHNode *, a[i], a[j]);
i++;
}
@@ -427,19 +440,18 @@ static void sort_along_axis(BVHTree *tree, int start, int end, int axis)
* \note after a call to this function you can expect one of:
* - every node to left of a[n] are smaller or equal to it
* - every node to the right of a[n] are greater or equal to it */
-static int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis)
+static void partition_nth_element(BVHNode **a, int begin, int end, const int n, const int axis)
{
- int begin = _begin, end = _end, cut;
while (end - begin > 3) {
- cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis);
- if (cut <= n)
+ const int cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis);
+ if (cut <= n) {
begin = cut;
- else
+ }
+ else {
end = cut;
+ }
}
bvh_insertionsort(a, begin, end, axis);
-
- return n;
}
#ifdef USE_SKIP_LINKS
@@ -464,7 +476,7 @@ static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNod
/*
* BVHTree bounding volumes functions
*/
-static void create_kdop_hull(BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving)
+static void create_kdop_hull(const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving)
{
float newminmax;
float *bv = node->bv;
@@ -491,7 +503,7 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, const float *co, int
/**
* \note depends on the fact that the BVH's for each face is already build
*/
-static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end)
+static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int end)
{
float newmin, newmax;
float *bv = node->bv;
@@ -566,10 +578,12 @@ static void node_join(BVHTree *tree, BVHNode *node)
}
}
-/*
+#ifdef USE_PRINT_TREE
+
+/**
* Debug and information functions
*/
-#if 0
+
static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
{
int i;
@@ -592,26 +606,29 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth)
static void bvhtree_info(BVHTree *tree)
{
- printf("BVHTree info\n");
- 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", (int)MEM_allocN_len(tree->nodebv));
-
- printf("Total memory = %ldbytes\n", sizeof(BVHTree) +
- MEM_allocN_len(tree->nodes) +
- MEM_allocN_len(tree->nodearray) +
- MEM_allocN_len(tree->nodechild) +
- MEM_allocN_len(tree->nodebv));
-
-// bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0);
+ printf("BVHTree Info: 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 = %ubytes\n",
+ (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis));
+ printf("BV memory = %ubytes\n",
+ (uint)MEM_allocN_len(tree->nodebv));
+
+ printf("Total memory = %ubytes\n",
+ (uint)(sizeof(BVHTree) +
+ MEM_allocN_len(tree->nodes) +
+ MEM_allocN_len(tree->nodearray) +
+ MEM_allocN_len(tree->nodechild) +
+ MEM_allocN_len(tree->nodebv)));
+
+ bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0);
}
-#endif
-
-#if 0
+#endif /* USE_PRINT_TREE */
+#ifdef USE_VERIFY_TREE
-static void verify_tree(BVHTree *tree)
+static void bvhtree_verify(BVHTree *tree)
{
int i, j, check = 0;
@@ -649,12 +666,14 @@ static void verify_tree(BVHTree *tree)
}
}
- printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf);
+ printf("branches: %d, leafs: %d, total: %d\n",
+ tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf);
}
-#endif
+#endif /* USE_VERIFY_TREE */
/* Helper data and structures to build a min-leaf generalized implicit tree
- * This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) */
+ * This code can be easily reduced
+ * (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) */
typedef struct BVHBuildHelper {
int tree_type; /* */
int totleafs; /* */
@@ -666,7 +685,7 @@ typedef struct BVHBuildHelper {
} BVHBuildHelper;
-static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data)
+static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data)
{
int depth = 0;
int remain;
@@ -696,7 +715,7 @@ static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data)
}
// return the min index of all the leafs archivable with the given branch
-static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index)
+static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index)
{
int min_leaf_index = child_index * data->leafs_per_child[depth - 1];
if (min_leaf_index <= data->remain_leafs)
@@ -711,8 +730,8 @@ static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index
* Generalized implicit tree build
*
* An implicit tree is a tree where its structure is implied, thus there is no need to store child pointers or indexs.
- * Its possible to find the position of the child or the parent with simple maths (multiplication and adittion). This type
- * of tree is for example used on heaps.. where node N has its childs at indexs N*2 and N*2+1.
+ * Its possible to find the position of the child or the parent with simple maths (multiplication and adittion).
+ * This type of tree is for example used on heaps.. where node N has its childs at indexs N*2 and N*2+1.
*
* Although in this case the tree type is general.. and not know until runtime.
* tree_type stands for the maximum number of childs that a tree node can have.
@@ -753,7 +772,7 @@ static int implicit_needed_branches(int tree_type, int leafs)
*
* TODO: This can be optimized a bit by doing a specialized nth_element instead of K nth_elements
*/
-static void split_leafs(BVHNode **leafs_array, int *nth, int partitions, int split_axis)
+static void split_leafs(BVHNode **leafs_array, const int nth[], const int partitions, const int split_axis)
{
int i;
for (i = 0; i < partitions - 1; i++) {
@@ -765,14 +784,14 @@ static void split_leafs(BVHNode **leafs_array, int *nth, int partitions, int spl
}
typedef struct BVHDivNodesData {
- BVHTree *tree;
+ const BVHTree *tree;
BVHNode *branches_array;
BVHNode **leafs_array;
int tree_type;
int tree_offset;
- BVHBuildHelper *data;
+ const BVHBuildHelper *data;
int depth;
int i;
@@ -785,7 +804,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *userdata, const int j)
int k;
const int parent_level_index = j - data->i;
- BVHNode *parent = data->branches_array + j;
+ BVHNode *parent = &data->branches_array[j];
int nth_positions[MAX_TREETYPE + 1];
char split_axis;
@@ -824,7 +843,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *userdata, const int j)
const int child_leafs_end = implicit_leafs_index(data->data, data->depth + 1, child_level_index + 1);
if (child_leafs_end - child_leafs_begin > 1) {
- parent->children[k] = data->branches_array + child_index;
+ parent->children[k] = &data->branches_array[child_index];
parent->children[k]->parent = parent;
}
else if (child_leafs_end - child_leafs_begin == 1) {
@@ -855,7 +874,8 @@ static void non_recursive_bvh_div_nodes_task_cb(void *userdata, const int j)
* To archive this is necessary to find how much leafs are accessible from a certain branch, BVHBuildHelper
* implicit_needed_branches and implicit_leafs_index are auxiliary functions to solve that "optimal-split".
*/
-static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs)
+static void non_recursive_bvh_div_nodes(
+ const BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs)
{
int i;
@@ -867,13 +887,13 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array,
int depth;
/* set parent from root node to NULL */
- BVHNode *tmp = branches_array + 0;
+ BVHNode *tmp = &branches_array[0];
tmp->parent = NULL;
/* Most of bvhtree code relies on 1-leaf trees having at least one branch
* We handle that special case here */
if (num_leafs == 1) {
- BVHNode *root = branches_array + 0;
+ BVHNode *root = &branches_array[0];
refit_kdop_hull(tree, root, 0, num_leafs);
root->main_axis = get_largest_axis(root->bv) / 2;
root->totnode = 1;
@@ -895,16 +915,24 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array,
/* Loop tree levels (log N) loops */
for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) {
const int first_of_next_level = i * tree_type + tree_offset;
- const int end_j = min_ii(first_of_next_level, num_branches + 1); /* index of last branch on this level */
+ const int i_stop = min_ii(first_of_next_level, num_branches + 1); /* index of last branch on this level */
/* Loop all branches on this level */
cb_data.first_of_next_level = first_of_next_level;
cb_data.i = i;
cb_data.depth = depth;
- BLI_task_parallel_range(
- i, end_j, &cb_data, non_recursive_bvh_div_nodes_task_cb,
- num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD);
+ if (true) {
+ BLI_task_parallel_range(
+ i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb,
+ num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD);
+ }
+ else {
+ /* Less hassle for debugging. */
+ for (int i_task = i; i_task < i_stop; i_task++) {
+ non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task);
+ }
+ }
}
}
@@ -1021,7 +1049,8 @@ void BLI_bvhtree_balance(BVHTree *tree)
BVHNode *branches_array = tree->nodearray + tree->totleaf;
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) */
+ /* This function should only be called once
+ * (some big bug goes here if its being called more than once per tree) */
BLI_assert(tree->totbranch == 0);
/* Build the implicit tree */
@@ -1037,7 +1066,13 @@ void BLI_bvhtree_balance(BVHTree *tree)
build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL);
#endif
- /* bvhtree_info(tree); */
+#ifdef USE_VERIFY_TREE
+ bvhtree_verify(tree);
+#endif
+
+#ifdef USE_PRINT_TREE
+ bvhtree_info(tree);
+#endif
}
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
@@ -1470,7 +1505,8 @@ static void bfs_find_nearest(BVHNearestData *data, BVHNode *node)
else {
/* adjust heap size */
if ((heap_size >= max_heap_size) &&
- ADJUST_MEMORY(default_heap, (void **)&heap, heap_size + 1, &max_heap_size, sizeof(heap[0])) == false)
+ ADJUST_MEMORY(default_heap, (void **)&heap,
+ heap_size + 1, &max_heap_size, sizeof(heap[0])) == false)
{
printf("WARNING: bvh_find_nearest got out of memory\n");
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
index 295b39c1a2f..d3a63aceb89 100644
--- a/source/blender/blenlib/intern/array_store.c
+++ b/source/blender/blenlib/intern/array_store.c
@@ -878,7 +878,7 @@ static hash_key key_from_chunk_ref(
{
/* in C, will fill in a reusable array */
BChunk *chunk = cref->link;
- BLI_assert(info->accum_read_ahead_bytes * info->chunk_stride);
+ BLI_assert((info->accum_read_ahead_bytes * info->chunk_stride) != 0);
if (info->accum_read_ahead_bytes <= chunk->data_len) {
hash_key key;
@@ -1560,7 +1560,7 @@ BArrayState *BLI_array_store_state_add(
const void *data, const size_t data_len,
const BArrayState *state_reference)
{
- /* ensure we're aligned to the stride */
+ /* ensure we're aligned to the stride */
BLI_assert((data_len % bs->info.chunk_stride) == 0);
#ifdef USE_PARANOID_CHECKS
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index db4b3bcf20c..1df7f6f81e4 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -42,9 +42,6 @@
#include "zlib.h"
#ifdef WIN32
-# ifdef __MINGW32__
-# include <ctype.h>
-# endif
# include <io.h>
# include "BLI_winstuff.h"
# include "BLI_callbacks.h"
@@ -265,7 +262,7 @@ void *BLI_gzopen(const char *filename, const char *mode)
/* temporary #if until we update all libraries to 1.2.7
* for correct wide char path handling */
-#if ZLIB_VERNUM >= 0x1270 && !defined(FREE_WINDOWS)
+#if ZLIB_VERNUM >= 0x1270
UTF16_ENCODE(filename);
gzfile = gzopen_w(filename_16, mode);
diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c
index af6ef4f355f..e8ca9244f25 100644
--- a/source/blender/blenlib/intern/hash_mm2a.c
+++ b/source/blender/blenlib/intern/hash_mm2a.c
@@ -36,6 +36,8 @@
* for temporary data.
*/
+#include "BLI_compiler_attrs.h"
+
#include "BLI_hash_mm2a.h" /* own include */
/* Helpers. */
@@ -128,10 +130,10 @@ uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed)
switch (len) {
case 3:
h ^= data[2] << 16;
- /* fall through */
+ ATTR_FALLTHROUGH;
case 2:
h ^= data[1] << 8;
- /* fall through */
+ ATTR_FALLTHROUGH;
case 1:
h ^= data[0];
h *= MM2A_M;
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index c9bf4976ae8..46dcee48eda 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -342,6 +342,40 @@ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
}
}
+
+/**
+ * Insert a link in place of another, without changing it's position in the list.
+ *
+ * Puts `vnewlink` in the position of `vreplacelink`, removing `vreplacelink`.
+ * - `vreplacelink` *must* be in the list.
+ * - `vnewlink` *must not* be in the list.
+ */
+void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink)
+{
+ Link *l_old = vreplacelink;
+ Link *l_new = vnewlink;
+
+ /* update adjacent links */
+ if (l_old->next != NULL) {
+ l_old->next->prev = l_new;
+ }
+ if (l_old->prev != NULL) {
+ l_old->prev->next = l_new;
+ }
+
+ /* set direct links */
+ l_new->next = l_old->next;
+ l_new->prev = l_old->prev;
+
+ /* update list */
+ if (listbase->first == l_old) {
+ listbase->first = l_new;
+ }
+ if (listbase->last == l_old) {
+ listbase->last = l_new;
+ }
+}
+
/**
* Reinsert \a vlink relative to its current position but offset by \a step. Doesn't move
* item if new position would exceed list (could optionally move to head/tail).
@@ -630,7 +664,7 @@ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
}
/**
- * Returns the 1-based index of the first element of listbase which contains the specified
+ * Returns the 0-based index of the first element of listbase which contains the specified
* null-terminated string at the specified offset, or -1 if not found.
*/
int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset)
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 048ab71c6dc..dc3874f83a2 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -444,7 +444,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const ch
else if (src2[i] == 0) {
temp = 0;
}
- else if (src2[i] > 127) {
+ else if (src2[i] > 127) {
temp = min_ii(((src1[i]) * 255) / (2 * (255 - src2[i])), 255);
}
else {
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 4e20872cb51..630eaed05db 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -572,8 +572,8 @@ float dist_squared_to_ray_v3(
}
/**
* Find the closest point in a seg to a ray and return the distance squared.
- * \param r_point : Is the point on segment closest to ray (or to ray_origin if the ray and the segment are parallel).
- * \param depth: the distance of r_point projection on ray to the ray_origin.
+ * \param r_point: Is the point on segment closest to ray (or to ray_origin if the ray and the segment are parallel).
+ * \param r_depth: the distance of r_point projection on ray to the ray_origin.
*/
float dist_squared_ray_to_seg_v3(
const float ray_origin[3], const float ray_direction[3],
@@ -1828,7 +1828,7 @@ bool isect_tri_tri_epsilon_v3(
(range[0].max < range[1].min)) == 0)
{
if (r_i1 && r_i2) {
- project_plane_v3_v3v3(plane_co, plane_co, plane_no);
+ project_plane_normalized_v3_v3v3(plane_co, plane_co, plane_no);
madd_v3_v3v3fl(r_i1, plane_co, plane_no, max_ff(range[0].min, range[1].min));
madd_v3_v3v3fl(r_i2, plane_co, plane_no, min_ff(range[0].max, range[1].max));
}
@@ -2851,6 +2851,9 @@ bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[
/**
* \note: using #cross_tri_v2 means locations outside the triangle are correctly weighted
+ *
+ * \note This is *exactly* the same calculation as #resolve_tri_uv_v2,
+ * although it has double precision and is used for texture baking, so keep both.
*/
void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
{
@@ -2890,9 +2893,11 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl
}
}
-/* same as #barycentric_weights_v2 but works with a quad,
+/**
+ * same as #barycentric_weights_v2 but works with a quad,
* note: untested for values outside the quad's bounds
- * this is #interp_weights_poly_v2 expanded for quads only */
+ * this is #interp_weights_poly_v2 expanded for quads only
+ */
void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const float v3[2], const float v4[2],
const float co[2], float w[4])
{
@@ -3345,6 +3350,8 @@ void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3
* Barycentric reverse
*
* Compute coordinates (u, v) for point \a st with respect to triangle (\a st0, \a st1, \a st2)
+ *
+ * \note same basic result as #barycentric_weights_v2, see it's comment for details.
*/
void resolve_tri_uv_v2(float r_uv[2], const float st[2],
const float st0[2], const float st1[2], const float st2[2])
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 9a60c670ec7..f47f9ad76e6 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1738,16 +1738,16 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
/**
* A polar-decomposition-based interpolation between matrix A and matrix B.
*
- * \note This code is about five times slower as the 'naive' interpolation done by \a blend_m3_m3m3
- * (it typically remains below 2 usec on an average i74700, while \a blend_m3_m3m3 remains below 0.4 usec).
+ * \note This code is about five times slower as the 'naive' interpolation done by #blend_m3_m3m3
+ * (it typically remains below 2 usec on an average i74700, while #blend_m3_m3m3 remains below 0.4 usec).
* However, it gives expected results even with non-uniformaly scaled matrices, see T46418 for an example.
*
* Based on "Matrix Animation and Polar Decomposition", by Ken Shoemake & Tom Duff
*
- * @return R the interpolated matrix.
- * @param A the intput matrix which is totally effective with \a t = 0.0.
- * @param B the intput matrix which is totally effective with \a t = 1.0.
- * @param t the interpolation factor.
+ * \param R: Resulting interpolated matrix.
+ * \param A: Input matrix which is totally effective with `t = 0.0`.
+ * \param B: Input matrix which is totally effective with `t = 1.0`.
+ * \param t: Interpolation factor.
*/
void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
{
@@ -1777,12 +1777,12 @@ void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
}
/**
- * Complete transform matrix interpolation, based on polar-decomposition-based interpolation from interp_m3_m3m3.
+ * Complete transform matrix interpolation, based on polar-decomposition-based interpolation from #interp_m3_m3m3.
*
- * @return R the interpolated matrix.
- * @param A the intput matrix which is totally effective with \a t = 0.0.
- * @param B the intput matrix which is totally effective with \a t = 1.0.
- * @param t the interpolation factor.
+ * \param R: Resulting interpolated matrix.
+ * \param A: Input matrix which is totally effective with `t = 0.0`.
+ * \param B: Input matrix which is totally effective with `t = 1.0`.
+ * \param t: Interpolation factor.
*/
void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
{
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 9b5dad3f767..23bd5e60e22 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -84,8 +84,6 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4])
* \note:
* Assumes a unit quaternion?
*
- * \note: multiplying by 3x3 matrix is ~25% faster.
- *
* in fact not, but you may want to use a unit quat, read on...
*
* Shortcut for 'q v q*' when \a v is actually a quaternion.
@@ -98,6 +96,8 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4])
*
* For people used to python mathutils, its like:
* def mul_qt_v3(q, v): (q * Quaternion((0.0, v[0], v[1], v[2])) * q.conjugated())[1:]
+ *
+ * \note: multiplying by 3x3 matrix is ~25% faster.
*/
void mul_qt_v3(const float q[4], float v[3])
{
@@ -2147,38 +2147,37 @@ BLI_INLINE int _axis_signed(const int axis)
return (axis < 3) ? axis : axis - 3;
}
-/*
+/**
* Each argument us an axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z']
* where the first 2 are a source and the second 2 are the target.
*/
-int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up,
- float r_mat[3][3])
+bool mat3_from_axis_conversion(
+ int src_forward, int src_up, int dst_forward, int dst_up,
+ float r_mat[3][3])
{
// from functools import reduce
int value;
- unsigned int i;
- if (from_forward == to_forward && from_up == to_up) {
+ if (src_forward == dst_forward && src_up == dst_up) {
unit_m3(r_mat);
return false;
}
- if ((_axis_signed(from_forward) == _axis_signed(from_up)) ||
- (_axis_signed(to_forward) == _axis_signed(to_up)))
+ if ((_axis_signed(src_forward) == _axis_signed(src_up)) ||
+ (_axis_signed(dst_forward) == _axis_signed(dst_up)))
{
/* we could assert here! */
unit_m3(r_mat);
return false;
}
- value = ((from_forward << (0 * 3)) |
- (from_up << (1 * 3)) |
- (to_forward << (2 * 3)) |
- (to_up << (3 * 3)));
+ value = ((src_forward << (0 * 3)) |
+ (src_up << (1 * 3)) |
+ (dst_forward << (2 * 3)) |
+ (dst_up << (3 * 3)));
- for (i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) {
- unsigned int j;
- for (j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) {
+ for (uint i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) {
+ for (uint j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) {
if (_axis_convert_lut[i][j] == value) {
copy_m3_m3(r_mat, _axis_convert_matrix[i]);
return true;
@@ -2189,3 +2188,27 @@ int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int
// BLI_assert(0);
return false;
}
+
+/**
+ * Use when the second axis can be guessed.
+ */
+bool mat3_from_axis_conversion_single(
+ int src_axis, int dst_axis,
+ float r_mat[3][3])
+{
+ if (src_axis == dst_axis) {
+ unit_m3(r_mat);
+ return false;
+ }
+
+ /* Pick predictable next axis. */
+ int src_axis_next = (src_axis + 1) % 3;
+ int dst_axis_next = (dst_axis + 1) % 3;
+
+ if ((src_axis < 3) != (dst_axis < 3)) {
+ /* Flip both axis so matrix sign remains positive. */
+ dst_axis_next += 3;
+ }
+
+ return mat3_from_axis_conversion(src_axis, src_axis_next, dst_axis, dst_axis_next, r_mat);
+}
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index dfecc3b556a..c6e9b8229ba 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -518,38 +518,27 @@ float angle_normalized_v2v2(const float v1[2], const float v2[2])
}
/**
- * angle between 2 vectors defined by 3 coords, about an axis. */
-float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+ * Angle between 2 vectors, about an axis (axis can be considered a plane).
+ */
+float angle_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3])
{
- float v1_proj[3], v2_proj[3], tproj[3];
-
- sub_v3_v3v3(v1_proj, v1, v2);
- sub_v3_v3v3(v2_proj, v3, v2);
+ float v1_proj[3], v2_proj[3];
/* project the vectors onto the axis */
- project_v3_v3v3(tproj, v1_proj, axis);
- sub_v3_v3(v1_proj, tproj);
-
- project_v3_v3v3(tproj, v2_proj, axis);
- sub_v3_v3(v2_proj, tproj);
+ project_plane_normalized_v3_v3v3(v1_proj, v1, axis);
+ project_plane_normalized_v3_v3v3(v2_proj, v2, axis);
return angle_v3v3(v1_proj, v2_proj);
}
-float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3])
{
float v1_proj[3], v2_proj[3], tproj[3];
float angle;
- sub_v3_v3v3(v1_proj, v1, v2);
- sub_v3_v3v3(v2_proj, v3, v2);
-
/* project the vectors onto the axis */
- project_v3_v3v3(tproj, v1_proj, axis);
- sub_v3_v3(v1_proj, tproj);
-
- project_v3_v3v3(tproj, v2_proj, axis);
- sub_v3_v3(v2_proj, tproj);
+ project_plane_normalized_v3_v3v3(v1_proj, v1, axis);
+ project_plane_normalized_v3_v3v3(v2_proj, v2, axis);
angle = angle_v3v3(v1_proj, v2_proj);
@@ -562,6 +551,29 @@ float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const
return angle;
}
+/**
+ * Angle between 2 vectors defined by 3 coords, about an axis (axis can be considered a plane).
+ */
+float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+{
+ float vec1[3], vec2[3];
+
+ sub_v3_v3v3(vec1, v1, v2);
+ sub_v3_v3v3(vec2, v3, v2);
+
+ return angle_on_axis_v3v3_v3(vec1, vec2, axis);
+}
+
+float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
+{
+ float vec1[3], vec2[3];
+
+ sub_v3_v3v3(vec1, v1, v2);
+ sub_v3_v3v3(vec2, v3, v2);
+
+ return angle_signed_on_axis_v3v3_v3(vec1, vec2, axis);
+}
+
void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3])
{
float ed1[3], ed2[3], ed3[3];
@@ -669,6 +681,25 @@ void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2
out[1] = p[1] - (mul * v_plane[1]);
}
+void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
+{
+ BLI_ASSERT_UNIT_V3(v_plane);
+ const float mul = dot_v3v3(p, v_plane);
+
+ out[0] = p[0] - (mul * v_plane[0]);
+ out[1] = p[1] - (mul * v_plane[1]);
+ out[2] = p[2] - (mul * v_plane[2]);
+}
+
+void project_plane_normalized_v2_v2v2(float out[2], const float p[2], const float v_plane[2])
+{
+ BLI_ASSERT_UNIT_V2(v_plane);
+ const float mul = dot_v2v2(p, v_plane);
+
+ out[0] = p[0] - (mul * v_plane[0]);
+ out[1] = p[1] - (mul * v_plane[1]);
+}
+
/* project a vector on a plane defined by normal and a plane point p */
void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3])
{
@@ -697,7 +728,19 @@ void bisect_v3_v3v3v3(float out[3], const float v1[3], const float v2[3], const
/**
* Returns a reflection vector from a vector and a normal vector
- * reflect = vec - ((2 * DotVecs(vec, mirror)) * mirror)
+ * reflect = vec - ((2 * dot(vec, mirror)) * mirror).
+ *
+ * <pre>
+ * v
+ * + ^
+ * \ |
+ * \|
+ * + normal: axis of reflection
+ * /
+ * /
+ * +
+ * out: result (negate for a 'bounce').
+ * </pre>
*/
void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3])
{
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 6644e6605a1..4b3a74d02ae 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1167,52 +1167,16 @@ bool BLI_path_program_search(
}
/**
- * Copies into *last the part of *dir following the second-last slash.
- */
-void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
-{
- const char *s = dir;
- const char *lslash = NULL;
- const char *prevslash = NULL;
- while (*s) {
- if ((*s == '\\') || (*s == '/')) {
- prevslash = lslash;
- lslash = s;
- }
- s++;
- }
- if (prevslash) {
- BLI_strncpy(last, prevslash + 1, maxlen);
- }
- else {
- BLI_strncpy(last, dir, maxlen);
- }
-}
-
-
-/**
* Sets the specified environment variable to the specified value,
* and clears it if val == NULL.
*/
void BLI_setenv(const char *env, const char *val)
{
/* free windows */
-#if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
- char *envstr;
-
- if (val)
- envstr = BLI_sprintfN("%s=%s", env, val);
- else
- envstr = BLI_sprintfN("%s=", env);
-
- putenv(envstr);
- MEM_freeN(envstr);
- /* non-free windows */
-#elif (defined(WIN32) || defined(WIN64)) /* not free windows */
+#if (defined(WIN32) || defined(WIN64))
uputenv(env, val);
-
#else
/* linux/osx/bsd */
if (val)
@@ -1258,14 +1222,16 @@ void BLI_make_exist(char *dir)
/**
* Ensures that the parent directory of *name exists.
+ *
+ * \return true on success (i.e. given path now exists on FS), false otherwise.
*/
-void BLI_make_existing_file(const char *name)
+bool BLI_make_existing_file(const char *name)
{
char di[FILE_MAX];
BLI_split_dir_part(name, di, sizeof(di));
/* make if the dir doesn't exist */
- BLI_dir_create_recursive(di);
+ return BLI_dir_create_recursive(di);
}
/**
@@ -1615,6 +1581,90 @@ void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__r
}
/**
+ * Join multiple strings into a path, ensuring only a single path separator between each,
+ * and trailing slash is kept.
+ *
+ * \note If you want a trailing slash, add ``SEP_STR`` as the last path argument,
+ * duplicate slashes will be cleaned up.
+ */
+size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...)
+{
+ if (UNLIKELY(dst_len == 0)) {
+ return 0;
+ }
+ const size_t dst_last = dst_len - 1;
+ size_t ofs = BLI_strncpy_rlen(dst, path, dst_len);
+
+ if (ofs == dst_last) {
+ return ofs;
+ }
+
+ /* remove trailing slashes, unless there are _only_ trailing slashes
+ * (allow "//" as the first argument). */
+ bool has_trailing_slash = false;
+ if (ofs != 0) {
+ size_t len = ofs;
+ while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
+ len -= 1;
+ }
+ if (len != 0) {
+ ofs = len;
+ }
+ has_trailing_slash = (path[len] != '\0');
+ }
+
+ va_list args;
+ va_start(args, path);
+ while ((path = (const char *) va_arg(args, const char *))) {
+ has_trailing_slash = false;
+ const char *path_init = path;
+ while (ELEM(path[0], SEP, ALTSEP)) {
+ path++;
+ }
+ size_t len = strlen(path);
+ if (len != 0) {
+ while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
+ len -= 1;
+ }
+
+ if (len != 0) {
+ /* the very first path may have a slash at the end */
+ if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) {
+ dst[ofs++] = SEP;
+ if (ofs == dst_last) {
+ break;
+ }
+ }
+ has_trailing_slash = (path[len] != '\0');
+ if (ofs + len >= dst_last) {
+ len = dst_last - ofs;
+ }
+ memcpy(&dst[ofs], path, len);
+ ofs += len;
+ if (ofs == dst_last) {
+ break;
+ }
+ }
+ }
+ else {
+ has_trailing_slash = (path_init != path);
+ }
+ }
+ va_end(args);
+
+ if (has_trailing_slash) {
+ if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) {
+ dst[ofs++] = SEP;
+ }
+ }
+
+ BLI_assert(ofs <= dst_last);
+ dst[ofs] = '\0';
+
+ return ofs;
+}
+
+/**
* like pythons os.path.basename()
*
* \return The pointer into \a path string immediately after last slash,
@@ -1626,6 +1676,71 @@ const char *BLI_path_basename(const char *path)
return filename ? filename + 1 : path;
}
+/**
+ * Get an element of the path at an index, eg:
+ * "/some/path/file.txt" where an index of...
+ * - 0 or -3: "some"
+ * - 1 or -2: "path"
+ * - 2 or -1: "file.txt"
+ *
+ * Ignores multiple slashes at any point in the path (including start/end).
+ */
+bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, int *r_len)
+{
+ if (index >= 0) {
+ int index_step = 0;
+ int prev = -1;
+ int i = 0;
+ while (true) {
+ const char c = path[i];
+ if (ELEM(c, SEP, ALTSEP, '\0')) {
+ if (prev + 1 != i) {
+ prev += 1;
+ if (index_step == index) {
+ *r_offset = prev;
+ *r_len = i - prev;
+ /* printf("!!! %d %d\n", start, end); */
+ return true;
+ }
+ index_step += 1;
+ }
+ if (c == '\0') {
+ break;
+ }
+ prev = i;
+ }
+ i += 1;
+ }
+ return false;
+ }
+ else {
+ /* negative number, reverse where -1 is the last element */
+ int index_step = -1;
+ int prev = strlen(path);
+ int i = prev - 1;
+ while (true) {
+ const char c = i >= 0 ? path[i] : '\0';
+ if (ELEM(c, SEP, ALTSEP, '\0')) {
+ if (prev - 1 != i) {
+ i += 1;
+ if (index_step == index) {
+ *r_offset = i;
+ *r_len = prev - i;
+ return true;
+ }
+ index_step -= 1;
+ }
+ if (c == '\0') {
+ break;
+ }
+ prev = i;
+ }
+ i -= 1;
+ }
+ return false;
+ }
+}
+
/* UNUSED */
#if 0
/**
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index 2969b0eccf4..5f9b92198a5 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -105,24 +105,24 @@ typedef bool axis_t;
/* use for sorting */
typedef struct KDTreeNode2D_head {
- unsigned int neg, pos;
- unsigned int index;
+ uint neg, pos;
+ uint index;
} KDTreeNode2D_head;
typedef struct KDTreeNode2D {
- unsigned int neg, pos;
- unsigned int index;
+ uint neg, pos;
+ uint index;
axis_t axis; /* range is only (0-1) */
- unsigned short flag;
- unsigned int parent;
+ ushort flag;
+ uint parent;
} KDTreeNode2D;
struct KDTree2D {
KDTreeNode2D *nodes;
const float (*coords)[2];
- unsigned int root;
- unsigned int totnode;
- unsigned int *nodes_map; /* index -> node lookup */
+ uint root;
+ uint totnode;
+ uint *nodes_map; /* index -> node lookup */
};
struct KDRange2D {
@@ -140,14 +140,14 @@ typedef struct PolyFill {
struct PolyIndex *indices; /* vertex aligned */
const float (*coords)[2];
- unsigned int coords_tot;
+ uint coords_tot;
#ifdef USE_CONVEX_SKIP
- unsigned int coords_tot_concave;
+ uint coords_tot_concave;
#endif
/* A polygon with n vertices has a triangulation of n-2 triangles. */
- unsigned int (*tris)[3];
- unsigned int tris_tot;
+ uint (*tris)[3];
+ uint tris_tot;
#ifdef USE_KDTREE
struct KDTree2D kdtree;
@@ -158,7 +158,7 @@ typedef struct PolyFill {
/* circular linklist */
typedef struct PolyIndex {
struct PolyIndex *next, *prev;
- unsigned int index;
+ uint index;
eSign sign;
} PolyIndex;
@@ -212,7 +212,7 @@ static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float
#ifdef USE_KDTREE
-#define KDNODE_UNSET ((unsigned int)-1)
+#define KDNODE_UNSET ((uint)-1)
enum {
KDNODE_FLAG_REMOVED = (1 << 0),
@@ -220,7 +220,7 @@ enum {
static void kdtree2d_new(
struct KDTree2D *tree,
- unsigned int tot,
+ uint tot,
const float (*coords)[2])
{
/* set by caller */
@@ -235,11 +235,11 @@ static void kdtree2d_new(
*/
static void kdtree2d_init(
struct KDTree2D *tree,
- const unsigned int coords_tot,
+ const uint coords_tot,
const PolyIndex *indices)
{
KDTreeNode2D *node;
- unsigned int i;
+ uint i;
for (i = 0, node = tree->nodes; i < coords_tot; i++) {
if (indices[i].sign != CONVEX) {
@@ -251,15 +251,15 @@ static void kdtree2d_init(
}
}
- BLI_assert(tree->totnode == (unsigned int)(node - tree->nodes));
+ BLI_assert(tree->totnode == (uint)(node - tree->nodes));
}
-static unsigned int kdtree2d_balance_recursive(
- KDTreeNode2D *nodes, unsigned int totnode, axis_t axis,
- const float (*coords)[2], const unsigned int ofs)
+static uint kdtree2d_balance_recursive(
+ KDTreeNode2D *nodes, uint totnode, axis_t axis,
+ const float (*coords)[2], const uint ofs)
{
KDTreeNode2D *node;
- unsigned int neg, pos, median, i, j;
+ uint neg, pos, median, i, j;
if (totnode <= 0) {
return KDNODE_UNSET;
@@ -317,7 +317,7 @@ static void kdtree2d_balance(
static void kdtree2d_init_mapping(
struct KDTree2D *tree)
{
- unsigned int i;
+ uint i;
KDTreeNode2D *node;
for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) {
@@ -338,9 +338,9 @@ static void kdtree2d_init_mapping(
static void kdtree2d_node_remove(
struct KDTree2D *tree,
- unsigned int index)
+ uint index)
{
- unsigned int node_index = tree->nodes_map[index];
+ uint node_index = tree->nodes_map[index];
KDTreeNode2D *node;
if (node_index == KDNODE_UNSET) {
@@ -362,7 +362,7 @@ static void kdtree2d_node_remove(
{
KDTreeNode2D *node_parent = &tree->nodes[node->parent];
- BLI_assert((unsigned int)(node - tree->nodes) == node_index);
+ BLI_assert((uint)(node - tree->nodes) == node_index);
if (node_parent->neg == node_index) {
node_parent->neg = KDNODE_UNSET;
}
@@ -383,7 +383,7 @@ static void kdtree2d_node_remove(
static bool kdtree2d_isect_tri_recursive(
const struct KDTree2D *tree,
- const unsigned int tri_index[3],
+ const uint tri_index[3],
const float *tri_coords[3],
const float tri_center[2],
const struct KDRange2D bounds[2],
@@ -446,10 +446,10 @@ static bool kdtree2d_isect_tri_recursive(
static bool kdtree2d_isect_tri(
struct KDTree2D *tree,
- const unsigned int ind[3])
+ const uint ind[3])
{
const float *vs[3];
- unsigned int i;
+ uint i;
struct KDRange2D bounds[2] = {
{FLT_MAX, -FLT_MAX},
{FLT_MAX, -FLT_MAX},
@@ -475,7 +475,7 @@ static bool kdtree2d_isect_tri(
#endif /* USE_KDTREE */
-static unsigned int *pf_tri_add(PolyFill *pf)
+static uint *pf_tri_add(PolyFill *pf)
{
return pf->tris[pf->tris_tot++];
}
@@ -496,7 +496,7 @@ static void pf_coord_remove(PolyFill *pf, PolyIndex *pi)
pf->indices = pi->next;
}
#ifdef DEBUG
- pi->index = (unsigned int)-1;
+ pi->index = (uint)-1;
pi->next = pi->prev = NULL;
#endif
@@ -594,7 +594,7 @@ static void pf_triangulate(PolyFill *pf)
}
if (pf->coords_tot == 3) {
- unsigned int *tri = pf_tri_add(pf);
+ uint *tri = pf_tri_add(pf);
pi_ear = pf->indices;
tri[0] = pi_ear->index; pi_ear = pi_ear->next;
tri[1] = pi_ear->index; pi_ear = pi_ear->next;
@@ -627,10 +627,10 @@ static PolyIndex *pf_ear_tip_find(
)
{
/* localize */
- const unsigned int coords_tot = pf->coords_tot;
+ const uint coords_tot = pf->coords_tot;
PolyIndex *pi_ear;
- unsigned int i;
+ uint i;
#ifdef USE_CLIP_EVEN
pi_ear = pi_ear_init;
@@ -688,7 +688,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
#endif
#if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE)
- unsigned int coords_tot_concave_checked = 0;
+ uint coords_tot_concave_checked = 0;
#endif
@@ -697,8 +697,8 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
#ifdef USE_CONVEX_SKIP_TEST
/* check if counting is wrong */
{
- unsigned int coords_tot_concave_test = 0;
- unsigned int i = pf->coords_tot;
+ uint coords_tot_concave_test = 0;
+ uint i = pf->coords_tot;
while (i--) {
if (coords_sign[indices[i]] != CONVEX) {
coords_tot_concave_test += 1;
@@ -720,7 +720,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
#ifdef USE_KDTREE
{
- const unsigned int ind[3] = {
+ const uint ind[3] = {
pi_ear_tip->index,
pi_ear_tip->next->index,
pi_ear_tip->prev->index};
@@ -771,7 +771,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip)
{
- unsigned int *tri = pf_tri_add(pf);
+ uint *tri = pf_tri_add(pf);
tri[0] = pi_ear_tip->prev->index;
tri[1] = pi_ear_tip->index;
@@ -786,15 +786,15 @@ static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip)
static void polyfill_prepare(
PolyFill *pf,
const float (*coords)[2],
- const unsigned int coords_tot,
+ const uint coords_tot,
int coords_sign,
- unsigned int (*r_tris)[3],
+ uint (*r_tris)[3],
PolyIndex *r_indices)
{
/* localize */
PolyIndex *indices = r_indices;
- unsigned int i;
+ uint i;
/* assign all polyfill members here */
pf->indices = r_indices;
@@ -832,7 +832,7 @@ static void polyfill_prepare(
}
else {
/* reversed */
- unsigned int n = coords_tot - 1;
+ uint n = coords_tot - 1;
for (i = 0; i < coords_tot; i++) {
indices[i].next = &indices[i + 1];
indices[i].prev = &indices[i - 1];
@@ -876,9 +876,9 @@ static void polyfill_calc(
*/
void BLI_polyfill_calc_arena(
const float (*coords)[2],
- const unsigned int coords_tot,
+ const uint coords_tot,
const int coords_sign,
- unsigned int (*r_tris)[3],
+ uint (*r_tris)[3],
struct MemArena *arena)
{
@@ -932,9 +932,9 @@ void BLI_polyfill_calc_arena(
*/
void BLI_polyfill_calc(
const float (*coords)[2],
- const unsigned int coords_tot,
+ const uint coords_tot,
const int coords_sign,
- unsigned int (*r_tris)[3])
+ uint (*r_tris)[3])
{
PolyFill pf;
PolyIndex *indices = BLI_array_alloca(indices, coords_tot);
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index fd24a00156d..e0c4cbe9990 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -693,6 +693,14 @@ void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src)
dst->ymax = floorf(src->ymax);
}
+void BLI_rcti_rctf_copy_round(rcti *dst, const rctf *src)
+{
+ dst->xmin = floorf(src->xmin + 0.5f);
+ dst->xmax = floorf(src->xmax + 0.5f);
+ dst->ymin = floorf(src->ymin + 0.5f);
+ dst->ymax = floorf(src->ymax + 0.5f);
+}
+
void BLI_rctf_rcti_copy(rctf *dst, const rcti *src)
{
dst->xmin = src->xmin;
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 3edc00a8c1a..b819c513fbd 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -113,7 +113,7 @@ double BLI_dir_free_space(const char *dir)
#ifdef WIN32
DWORD sectorspc, bytesps, freec, clusters;
char tmp[4];
-
+
tmp[0] = '\\'; tmp[1] = 0; /* Just a failsafe */
if (dir[0] == '/' || dir[0] == '\\') {
tmp[0] = '\\';
@@ -139,10 +139,10 @@ double BLI_dir_free_space(const char *dir)
char name[FILE_MAXDIR], *slash;
int len = strlen(dir);
-
+
if (len >= FILE_MAXDIR) /* path too long */
return -1;
-
+
strcpy(name, dir);
if (len) {
@@ -194,7 +194,7 @@ size_t BLI_file_size(const char *path)
*/
int BLI_exists(const char *name)
{
-#if defined(WIN32)
+#if defined(WIN32)
BLI_stat_t st;
wchar_t *tmp_16 = alloc_utf16_from_8(name, 1);
int len, res;
@@ -253,10 +253,8 @@ int BLI_stat(const char *path, BLI_stat_t *buffer)
int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer)
{
-#if defined(_MSC_VER) || defined(__MINGW64__)
+#if defined(_MSC_VER)
return _wstat64(path, buffer);
-#elif defined(__MINGW32__)
- return _wstati64(path, buffer);
#else
return _wstat(path, buffer);
#endif
@@ -372,7 +370,7 @@ LinkNode *BLI_file_read_as_lines(const char *name)
size_t size;
if (!fp) return NULL;
-
+
fseek(fp, 0, SEEK_END);
size = (size_t)ftell(fp);
fseek(fp, 0, SEEK_SET);
@@ -385,7 +383,7 @@ LinkNode *BLI_file_read_as_lines(const char *name)
buf = MEM_mallocN(size, "file_as_lines");
if (buf) {
size_t i, last = 0;
-
+
/*
* size = because on win32 reading
* all the bytes in the file will return
@@ -403,10 +401,10 @@ LinkNode *BLI_file_read_as_lines(const char *name)
last = i + 1;
}
}
-
+
MEM_freeN(buf);
}
-
+
fclose(fp);
return lines.list;
@@ -424,23 +422,13 @@ void BLI_file_free_lines(LinkNode *lines)
bool BLI_file_older(const char *file1, const char *file2)
{
#ifdef WIN32
-#ifndef __MINGW32__
struct _stat st1, st2;
-#else
- struct _stati64 st1, st2;
-#endif
UTF16_ENCODE(file1);
UTF16_ENCODE(file2);
-
-#ifndef __MINGW32__
+
if (_wstat(file1_16, &st1)) return false;
if (_wstat(file2_16, &st2)) return false;
-#else
- if (_wstati64(file1_16, &st1)) return false;
- if (_wstati64(file2_16, &st2)) return false;
-#endif
-
UTF16_UN_ENCODE(file2);
UTF16_UN_ENCODE(file1);
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index f62ffe9e985..6022732025b 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -332,7 +332,7 @@ size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const siz
goto escape_finish;
case '\\':
case '"':
- /* fall-through */
+ ATTR_FALLTHROUGH;
/* less common but should also be support */
case '\t':
@@ -346,7 +346,7 @@ size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const siz
/* not enough space to escape */
break;
}
- /* fall-through */
+ ATTR_FALLTHROUGH;
default:
*dst = *src;
break;
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 83d4a75952f..229a97a2fa7 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -167,7 +167,7 @@ utf8_error:
/**
* Remove any invalid utf-8 byte (taking into account multi-bytes sequence of course).
*
- * @return number of stripped bytes.
+ * \return number of stripped bytes.
*/
int BLI_utf8_invalid_strip(char *str, size_t length)
{
@@ -205,11 +205,11 @@ int BLI_utf8_invalid_strip(char *str, size_t length)
while (*src != '\0' && (utf8_size = utf8_skip_data[*src]) < maxncpy) {\
maxncpy -= utf8_size; \
switch (utf8_size) { \
- case 6: *dst ++ = *src ++; \
- case 5: *dst ++ = *src ++; \
- case 4: *dst ++ = *src ++; \
- case 3: *dst ++ = *src ++; \
- case 2: *dst ++ = *src ++; \
+ case 6: *dst ++ = *src ++; ATTR_FALLTHROUGH; \
+ case 5: *dst ++ = *src ++; ATTR_FALLTHROUGH; \
+ case 4: *dst ++ = *src ++; ATTR_FALLTHROUGH; \
+ case 3: *dst ++ = *src ++; ATTR_FALLTHROUGH; \
+ case 2: *dst ++ = *src ++; ATTR_FALLTHROUGH; \
case 1: *dst ++ = *src ++; \
} \
} \
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 17e20f8fa18..e050f3148b8 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -52,7 +52,14 @@
*
* This allows thread to fetch next task without locking the whole queue.
*/
-#define LOCALQUEUE_SIZE 1
+#define LOCAL_QUEUE_SIZE 1
+
+/* Number of tasks which are allowed to be scheduled in a delayed manner.
+ *
+ * This allows to use less locks per graph node children schedule. More details
+ * could be found at TaskThreadLocalStorage::do_delayed_push.
+ */
+#define DELAYED_QUEUE_SIZE 4096
#ifndef NDEBUG
# define ASSERT_THREAD_ID(scheduler, thread_id) \
@@ -129,9 +136,28 @@ typedef struct TaskMemPoolStats {
#endif
typedef struct TaskThreadLocalStorage {
+ /* Memory pool for faster task allocation.
+ * The idea is to re-use memory of finished/discarded tasks by this thread.
+ */
TaskMemPool task_mempool;
+
+ /* Local queue keeps thread alive by keeping small amount of tasks ready
+ * to be picked up without causing global thread locks for synchronization.
+ */
int num_local_queue;
- Task *local_queue[LOCALQUEUE_SIZE];
+ Task *local_queue[LOCAL_QUEUE_SIZE];
+
+ /* Thread can be marked for delayed tasks push. This is helpful when it's
+ * know that lots of subsequent task pushed will happen from the same thread
+ * without "interrupting" for task execution.
+ *
+ * We try to accumulate as much tasks as possible in a local queue without
+ * any locks first, and then we push all of them into a scheduler's queue
+ * from within a single mutex lock.
+ */
+ bool do_delayed_push;
+ int num_delayed_queue;
+ Task *delayed_queue[DELAYED_QUEUE_SIZE];
} TaskThreadLocalStorage;
struct TaskPool {
@@ -162,6 +188,16 @@ struct TaskPool {
*/
int thread_id;
+ /* For the pools which are created from non-main thread which is not a
+ * scheduler worker thread we can't re-use any of scheduler's threads TLS
+ * and have to use our own one.
+ */
+ bool use_local_tls;
+ TaskThreadLocalStorage local_tls;
+#ifndef NDEBUG
+ pthread_t creator_thread_id;
+#endif
+
#ifdef DEBUG_STATS
TaskMemPoolStats *mempool_stats;
#endif
@@ -202,13 +238,25 @@ BLI_INLINE void task_data_free(Task *task, const int thread_id)
}
}
+BLI_INLINE void initialize_task_tls(TaskThreadLocalStorage *tls)
+{
+ memset(tls, 0, sizeof(TaskThreadLocalStorage));
+}
+
BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool,
const int thread_id)
{
TaskScheduler *scheduler = pool->scheduler;
BLI_assert(thread_id >= 0);
BLI_assert(thread_id <= scheduler->num_threads);
+ if (pool->use_local_tls && thread_id == 0) {
+ BLI_assert(pool->thread_id == 0);
+ BLI_assert(!BLI_thread_is_main());
+ BLI_assert(pthread_equal(pthread_self(), pool->creator_thread_id));
+ return &pool->local_tls;
+ }
if (thread_id == 0) {
+ BLI_assert(BLI_thread_is_main());
return &scheduler->task_threads[pool->thread_id].tls;
}
return &scheduler->task_threads[thread_id].tls;
@@ -252,6 +300,9 @@ static void task_free(TaskPool *pool, Task *task, const int thread_id)
task_data_free(task, thread_id);
BLI_assert(thread_id >= 0);
BLI_assert(thread_id <= pool->scheduler->num_threads);
+ if (thread_id == 0) {
+ BLI_assert(pool->use_local_tls || BLI_thread_is_main());
+ }
TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
TaskMemPool *task_mempool = &tls->task_mempool;
if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) {
@@ -353,6 +404,7 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls,
const int thread_id)
{
+ BLI_assert(!tls->do_delayed_push);
while (tls->num_local_queue > 0) {
/* We pop task from queue before handling it so handler of the task can
* push next job to the local queue.
@@ -366,6 +418,7 @@ BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls,
local_task->run(local_pool, local_task->taskdata, thread_id);
task_free(local_pool, local_task, thread_id);
}
+ BLI_assert(!tls->do_delayed_push);
}
static void *task_scheduler_thread_run(void *thread_p)
@@ -383,7 +436,9 @@ static void *task_scheduler_thread_run(void *thread_p)
TaskPool *pool = task->pool;
/* run task */
+ BLI_assert(!tls->do_delayed_push);
task->run(pool, task->taskdata, thread_id);
+ BLI_assert(!tls->do_delayed_push);
/* delete task */
task_free(pool, task, thread_id);
@@ -424,9 +479,12 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
num_threads = 1;
}
- scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * (num_threads + 1),
+ scheduler->task_threads = MEM_mallocN(sizeof(TaskThread) * (num_threads + 1),
"TaskScheduler task threads");
+ /* Initialize TLS for main thread. */
+ initialize_task_tls(&scheduler->task_threads[0].tls);
+
pthread_key_create(&scheduler->tls_id_key, NULL);
/* launch threads that will be waiting for work */
@@ -440,6 +498,7 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
TaskThread *thread = &scheduler->task_threads[i + 1];
thread->scheduler = scheduler;
thread->id = i + 1;
+ initialize_task_tls(&thread->tls);
if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) {
fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads);
@@ -518,6 +577,27 @@ static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriori
BLI_mutex_unlock(&scheduler->queue_mutex);
}
+static void task_scheduler_push_all(TaskScheduler *scheduler,
+ TaskPool *pool,
+ Task **tasks,
+ int num_tasks)
+{
+ if (num_tasks == 0) {
+ return;
+ }
+
+ task_pool_num_increase(pool, num_tasks);
+
+ BLI_mutex_lock(&scheduler->queue_mutex);
+
+ for (int i = 0; i < num_tasks; i++) {
+ BLI_addhead(&scheduler->queue, tasks[i]);
+ }
+
+ BLI_condition_notify_all(&scheduler->queue_cond);
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+}
+
static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
{
Task *task, *nexttask;
@@ -572,6 +652,7 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler,
pool->num_suspended = 0;
pool->suspended_queue.first = pool->suspended_queue.last = NULL;
pool->run_in_background = is_background;
+ pool->use_local_tls = false;
BLI_mutex_init(&pool->num_mutex);
BLI_condition_init(&pool->num_cond);
@@ -584,13 +665,18 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler,
}
else {
TaskThread *thread = pthread_getspecific(scheduler->tls_id_key);
- /* NOTE: It is possible that pool is created from non-main thread
- * which isn't a scheduler thread. In this case pthread's TLS will
- * be NULL and we can safely consider thread id 0 for the main
- * thread of this pool (the one which does wort_and_wait()).
- */
if (thread == NULL) {
+ /* NOTE: Task pool is created from non-main thread which is not
+ * managed by the task scheduler. We identify ourselves as thread ID
+ * 0 but we do not use scheduler's TLS storage and use our own
+ * instead to avoid any possible threading conflicts.
+ */
pool->thread_id = 0;
+ pool->use_local_tls = true;
+#ifndef NDEBUG
+ pool->creator_thread_id = pthread_self();
+#endif
+ initialize_task_tls(&pool->local_tls);
}
else {
pool->thread_id = thread->id;
@@ -670,43 +756,68 @@ void BLI_task_pool_free(TaskPool *pool)
MEM_freeN(pool->mempool_stats);
#endif
+ if (pool->use_local_tls) {
+ free_task_tls(&pool->local_tls);
+ }
+
MEM_freeN(pool);
BLI_end_threaded_malloc();
}
+BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id)
+{
+ return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work));
+}
+
static void task_pool_push(
TaskPool *pool, TaskRunFunction run, void *taskdata,
bool free_taskdata, TaskFreeFunction freedata, TaskPriority priority,
int thread_id)
{
+ /* Allocate task and fill it's properties. */
Task *task = task_alloc(pool, thread_id);
-
task->run = run;
task->taskdata = taskdata;
task->free_taskdata = free_taskdata;
task->freedata = freedata;
task->pool = pool;
-
+ /* For suspended pools we put everything yo a global queue first
+ * and exit as soon as possible.
+ *
+ * This tasks will be moved to actual execution when pool is
+ * activated by work_and_wait().
+ */
if (pool->is_suspended) {
BLI_addhead(&pool->suspended_queue, task);
atomic_fetch_and_add_z(&pool->num_suspended, 1);
return;
}
-
- if (thread_id != -1 &&
- (thread_id != pool->thread_id || pool->do_work))
- {
+ /* Populate to any local queue first, this is cheapest push ever. */
+ if (task_can_use_local_queues(pool, thread_id)) {
ASSERT_THREAD_ID(pool->scheduler, thread_id);
-
TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
- if (tls->num_local_queue < LOCALQUEUE_SIZE) {
+ /* Try to push to a local execution queue.
+ * These tasks will be picked up next.
+ */
+ if (tls->num_local_queue < LOCAL_QUEUE_SIZE) {
tls->local_queue[tls->num_local_queue] = task;
tls->num_local_queue++;
return;
}
+ /* If we are in the delayed tasks push mode, we push tasks to a
+ * temporary local queue first without any locks, and then move them
+ * to global execution queue with a single lock.
+ */
+ if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) {
+ tls->delayed_queue[tls->num_delayed_queue] = task;
+ tls->num_delayed_queue++;
+ return;
+ }
}
-
+ /* Do push to a global execution ppol, slowest possible method,
+ * causes quite reasonable amount of threading overhead.
+ */
task_scheduler_push(pool->scheduler, task, priority);
}
@@ -743,9 +854,7 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
BLI_condition_notify_all(&scheduler->queue_cond);
BLI_mutex_unlock(&scheduler->queue_mutex);
-
}
- pool->is_suspended = false;
}
pool->do_work = true;
@@ -779,7 +888,9 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* if found task, do it, otherwise wait until other tasks are done */
if (found_task) {
/* run task */
+ BLI_assert(!tls->do_delayed_push);
work_task->run(pool, work_task->taskdata, pool->thread_id);
+ BLI_assert(!tls->do_delayed_push);
/* delete task */
task_free(pool, task, pool->thread_id);
@@ -834,6 +945,30 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
return &pool->user_mutex;
}
+void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id)
+{
+ if (task_can_use_local_queues(pool, thread_id)) {
+ ASSERT_THREAD_ID(pool->scheduler, thread_id);
+ TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
+ tls->do_delayed_push = true;
+ }
+}
+
+void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id)
+{
+ if (task_can_use_local_queues(pool, thread_id)) {
+ ASSERT_THREAD_ID(pool->scheduler, thread_id);
+ TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
+ BLI_assert(tls->do_delayed_push);
+ task_scheduler_push_all(pool->scheduler,
+ pool,
+ tls->delayed_queue,
+ tls->num_delayed_queue);
+ tls->do_delayed_push = false;
+ tls->num_delayed_queue = 0;
+ }
+}
+
/* Parallel range routines */
/**
@@ -992,7 +1127,7 @@ static void task_parallel_range_ex(
atomic_fetch_and_add_uint32((uint32_t *)(&state.iter), 0);
if (use_userdata_chunk) {
- userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
+ userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
}
for (i = 0; i < num_tasks; i++) {
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index 77da3be0600..abf611d1245 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -813,6 +813,11 @@ void BLI_begin_threaded_malloc(void)
unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1);
if (level == 0) {
MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
+ /* There is a little chance that two threads will meed to acces to a
+ * scheduler which was not yet created from main thread. which could
+ * cause scheduler created multiple times.
+ */
+ BLI_task_scheduler_get();
}
}
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
index 3b06b7df09a..d6834428376 100644
--- a/source/blender/blenlib/intern/winstuff.c
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -160,8 +160,6 @@ void RegisterBlendExtension(void)
GetSystemDirectory(SysDir, FILE_MAXDIR);
#ifdef _WIN64
ThumbHandlerDLL = "BlendThumb64.dll";
-#elif defined(__MINGW32__)
- ThumbHandlerDLL = "BlendThumb.dll";
#else
IsWow64Process(GetCurrentProcess(), &IsWOW64);
if (IsWOW64 == true)
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index c85cf128643..e6fc4703248 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -71,11 +71,25 @@ typedef struct BlendFileData {
BlenFileType type;
} BlendFileData;
-BlendFileData *BLO_read_from_file(const char *filepath, struct ReportList *reports);
-BlendFileData *BLO_read_from_memory(const void *mem, int memsize, struct ReportList *reports);
+
+/* skip reading some data-block types (may want to skip screen data too). */
+typedef enum eBLOReadSkip {
+ BLO_READ_SKIP_NONE = 0,
+ BLO_READ_SKIP_USERDEF = (1 << 0),
+ BLO_READ_SKIP_DATA = (1 << 1),
+} eBLOReadSkip;
+#define BLO_READ_SKIP_ALL \
+ (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA)
+
+BlendFileData *BLO_read_from_file(
+ const char *filepath,
+ struct ReportList *reports, eBLOReadSkip skip_flag);
+BlendFileData *BLO_read_from_memory(
+ const void *mem, int memsize,
+ struct ReportList *reports, eBLOReadSkip skip_flag);
BlendFileData *BLO_read_from_memfile(
struct Main *oldmain, const char *filename, struct MemFile *memfile,
- struct ReportList *reports);
+ struct ReportList *reports, eBLOReadSkip skip_flag);
void BLO_blendfiledata_free(BlendFileData *bfd);
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 8cb9ef837b2..3d2e8a306de 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -69,6 +69,12 @@ if(WITH_BUILDINFO)
add_definitions(-DWITH_BUILDINFO)
endif()
+if(WITH_PYTHON)
+ if(WITH_PYTHON_SECURITY)
+ add_definitions(-DWITH_PYTHON_SECURITY)
+ endif()
+endif()
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index be893177b3b..73109413271 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -317,7 +317,9 @@ void BLO_blendhandle_close(BlendHandle *bh)
* \param reports If the return value is NULL, errors indicating the cause of the failure.
* \return The data of the file.
*/
-BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
+BlendFileData *BLO_read_from_file(
+ const char *filepath,
+ ReportList *reports, eBLOReadSkip skip_flags)
{
BlendFileData *bfd = NULL;
FileData *fd;
@@ -325,6 +327,7 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
fd = blo_openblenderfile(filepath, reports);
if (fd) {
fd->reports = reports;
+ fd->skip_flags = skip_flags;
bfd = blo_read_file_internal(fd, filepath);
blo_freefiledata(fd);
}
@@ -341,7 +344,9 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
* \param reports If the return value is NULL, errors indicating the cause of the failure.
* \return The data of the file.
*/
-BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *reports)
+BlendFileData *BLO_read_from_memory(
+ const void *mem, int memsize,
+ ReportList *reports, eBLOReadSkip skip_flags)
{
BlendFileData *bfd = NULL;
FileData *fd;
@@ -349,6 +354,7 @@ BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *re
fd = blo_openblendermemory(mem, memsize, reports);
if (fd) {
fd->reports = reports;
+ fd->skip_flags = skip_flags;
bfd = blo_read_file_internal(fd, "");
blo_freefiledata(fd);
}
@@ -362,7 +368,9 @@ BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *re
* \param oldmain old main, from which we will keep libraries and other datablocks that should not have changed.
* \param filename current file, only for retrieving library data.
*/
-BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFile *memfile, ReportList *reports)
+BlendFileData *BLO_read_from_memfile(
+ Main *oldmain, const char *filename, MemFile *memfile,
+ ReportList *reports, eBLOReadSkip skip_flags)
{
BlendFileData *bfd = NULL;
FileData *fd;
@@ -371,6 +379,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
fd = blo_openblendermemfile(memfile, reports);
if (fd) {
fd->reports = reports;
+ fd->skip_flags = skip_flags;
BLI_strncpy(fd->relabase, filename, sizeof(fd->relabase));
/* clear ob->proxy_from pointers in old main */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 638f877c841..f224f0b5633 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -129,6 +129,7 @@
#include "BKE_library_idmap.h"
#include "BKE_library_query.h"
#include "BKE_idcode.h"
+#include "BKE_idprop.h"
#include "BKE_material.h"
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
@@ -2001,7 +2002,7 @@ static void test_pointer_array(FileData *fd, void **mat)
/* ************ READ ID Properties *************** */
static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData *fd);
-static void IDP_LibLinkProperty(IDProperty *prop, int switch_endian, FileData *fd);
+static void IDP_LibLinkProperty(IDProperty *prop, FileData *fd);
static void IDP_DirectLinkIDPArray(IDProperty *prop, int switch_endian, FileData *fd)
{
@@ -2106,8 +2107,19 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData
BLI_endian_switch_int32(&prop->data.val2);
BLI_endian_switch_int64((int64_t *)&prop->data.val);
}
-
break;
+ case IDP_INT:
+ case IDP_FLOAT:
+ case IDP_ID:
+ break; /* Nothing special to do here. */
+ default:
+ /* Unknown IDP type, nuke it (we cannot handle unknown types everywhere in code,
+ * IDP are way too polymorphic to do it safely. */
+ printf("%s: found unknown IDProperty type %d, reset to Integer one !\n", __func__, prop->type);
+ /* Note: we do not attempt to free unknown prop, we have no way to know how to do that! */
+ prop->type = IDP_INT;
+ prop->subtype = 0;
+ IDP_Int(prop) = 0;
}
}
@@ -2132,10 +2144,39 @@ static void _IDP_DirectLinkGroup_OrFree(IDProperty **prop, int switch_endian, Fi
}
}
-/* stub function */
-static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endian), FileData *UNUSED(fd))
+static void IDP_LibLinkProperty(IDProperty *prop, FileData *fd)
{
- /* Should we do something here, prop should be ensured to be non-NULL first... */
+ if (!prop)
+ return;
+
+ switch (prop->type) {
+ case IDP_ID: /* PointerProperty */
+ {
+ void *newaddr = newlibadr_us(fd, NULL, IDP_Id(prop));
+ if (IDP_Id(prop) && !newaddr && G.debug) {
+ printf("Error while loading \"%s\". Data not found in file!\n", prop->name);
+ }
+ prop->data.pointer = newaddr;
+ break;
+ }
+ case IDP_IDPARRAY: /* CollectionProperty */
+ {
+ IDProperty *idp_array = IDP_IDPArray(prop);
+ for (int i = 0; i < prop->len; i++) {
+ IDP_LibLinkProperty(&(idp_array[i]), fd);
+ }
+ break;
+ }
+ case IDP_GROUP: /* PointerProperty */
+ {
+ for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) {
+ IDP_LibLinkProperty(loop, fd);
+ }
+ break;
+ }
+ default:
+ break; /* Nothing to do for other IDProps. */
+ }
}
/* ************ READ IMAGE PREVIEW *************** */
@@ -2192,19 +2233,19 @@ static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap)
/* library brush linking after fileread */
static void lib_link_brush(FileData *fd, Main *main)
{
- Brush *brush;
-
/* only link ID pointers */
- for (brush = main->brush.first; brush; brush = brush->id.next) {
+ for (Brush *brush = main->brush.first; brush; brush = brush->id.next) {
if (brush->id.tag & LIB_TAG_NEED_LINK) {
- brush->id.tag &= ~LIB_TAG_NEED_LINK;
-
+ IDP_LibLinkProperty(brush->id.properties, fd);
+
/* brush->(mask_)mtex.obj is ignored on purpose? */
brush->mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mtex.tex);
brush->mask_mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mask_mtex.tex);
brush->clone.image = newlibadr(fd, brush->id.lib, brush->clone.image);
brush->toggle_brush = newlibadr(fd, brush->id.lib, brush->toggle_brush);
brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve);
+
+ brush->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -2227,13 +2268,13 @@ static void direct_link_brush(FileData *fd, Brush *brush)
}
/* ************ READ Palette *************** */
-static void lib_link_palette(FileData *UNUSED(fd), Main *main)
+static void lib_link_palette(FileData *fd, Main *main)
{
- Palette *palette;
-
/* only link ID pointers */
- for (palette = main->palettes.first; palette; palette = palette->id.next) {
+ for (Palette *palette = main->palettes.first; palette; palette = palette->id.next) {
if (palette->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(palette->id.properties, fd);
+
palette->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -2245,13 +2286,13 @@ static void direct_link_palette(FileData *fd, Palette *palette)
link_list(fd, &palette->colors);
}
-static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main)
+static void lib_link_paint_curve(FileData *fd, Main *main)
{
- PaintCurve *pc;
-
/* only link ID pointers */
- for (pc = main->paintcurves.first; pc; pc = pc->id.next) {
+ for (PaintCurve *pc = main->paintcurves.first; pc; pc = pc->id.next) {
if (pc->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(pc->id.properties, fd);
+
pc->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -2503,15 +2544,12 @@ static void direct_link_fcurves(FileData *fd, ListBase *list)
static void lib_link_action(FileData *fd, Main *main)
{
- bAction *act;
- bActionChannel *chan;
-
- for (act = main->action.first; act; act = act->id.next) {
+ for (bAction *act = main->action.first; act; act = act->id.next) {
if (act->id.tag & LIB_TAG_NEED_LINK) {
- act->id.tag &= ~LIB_TAG_NEED_LINK;
+ IDP_LibLinkProperty(act->id.properties, fd);
// XXX deprecated - old animation system <<<
- for (chan=act->chanbase.first; chan; chan=chan->next) {
+ for (bActionChannel *chan = act->chanbase.first; chan; chan = chan->next) {
chan->ipo = newlibadr_us(fd, act->id.lib, chan->ipo);
lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels);
}
@@ -2524,6 +2562,8 @@ static void lib_link_action(FileData *fd, Main *main)
marker->camera = newlibadr(fd, act->id.lib, marker->camera);
}
}
+
+ act->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -2710,26 +2750,20 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
static void lib_link_cachefiles(FileData *fd, Main *bmain)
{
- CacheFile *cache_file;
-
/* only link ID pointers */
- for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
+ for (CacheFile *cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
if (cache_file->id.tag & LIB_TAG_NEED_LINK) {
- cache_file->id.tag &= ~LIB_TAG_NEED_LINK;
- }
-
- BLI_listbase_clear(&cache_file->object_paths);
- cache_file->handle = NULL;
- cache_file->handle_mutex = NULL;
-
- if (cache_file->adt) {
+ IDP_LibLinkProperty(cache_file->id.properties, fd);
lib_link_animdata(fd, &cache_file->id, cache_file->adt);
+
+ cache_file->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
static void direct_link_cachefile(FileData *fd, CacheFile *cache_file)
{
+ BLI_listbase_clear(&cache_file->object_paths);
cache_file->handle = NULL;
cache_file->handle_mutex = NULL;
@@ -2753,19 +2787,13 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath)
/* ************ READ NODE TREE *************** */
-static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock)
-{
- /* Link ID Properties -- and copy this comment EXACTLY for easy finding
- * of library blocks that implement this.*/
- IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
-}
-
/* Single node tree (also used for material/scene trees), ntree is not NULL */
static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
+ IDP_LibLinkProperty(ntree->id.properties, fd);
lib_link_animdata(fd, &ntree->id, ntree->adt);
ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd);
@@ -2773,32 +2801,35 @@ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
- IDP_LibLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_LibLinkProperty(node->prop, fd);
- node->id= newlibadr_us(fd, id->lib, node->id);
+ node->id = newlibadr_us(fd, id->lib, node->id);
- for (sock = node->inputs.first; sock; sock = sock->next)
- lib_link_node_socket(fd, id, sock);
- for (sock = node->outputs.first; sock; sock = sock->next)
- lib_link_node_socket(fd, id, sock);
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, fd);
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, fd);
+ }
}
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- lib_link_node_socket(fd, id, sock);
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- lib_link_node_socket(fd, id, sock);
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, fd);
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, fd);
+ }
}
/* library ntree linking after fileread */
static void lib_link_nodetree(FileData *fd, Main *main)
{
- bNodeTree *ntree;
-
/* only link ID pointers */
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+ for (bNodeTree *ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
if (ntree->id.tag & LIB_TAG_NEED_LINK) {
- ntree->id.tag &= ~LIB_TAG_NEED_LINK;
lib_link_ntree(fd, &ntree->id, ntree);
+
+ ntree->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -3089,7 +3120,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
else if (ntree->type==NTREE_COMPOSIT) {
if (ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
direct_link_curvemapping(fd, node->storage);
- else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
((ImageUser *)node->storage)->ok = 1;
}
else if ( ntree->type==NTREE_TEXTURE) {
@@ -3291,6 +3322,8 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name);
+ IDP_LibLinkProperty(pchan->prop, fd);
+
pchan->custom = newlibadr_us(fd, arm->id.lib, pchan->custom);
if (UNLIKELY(pchan->bone == NULL)) {
rebuild = true;
@@ -3311,13 +3344,26 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
}
}
+static void lib_link_bones(FileData *fd, Bone *bone)
+{
+ IDP_LibLinkProperty(bone->prop, fd);
+
+ for (Bone *curbone = bone->childbase.first; curbone; curbone = curbone->next) {
+ lib_link_bones(fd, curbone);
+ }
+}
+
static void lib_link_armature(FileData *fd, Main *main)
{
- bArmature *arm;
-
- for (arm = main->armature.first; arm; arm = arm->id.next) {
+ for (bArmature *arm = main->armature.first; arm; arm = arm->id.next) {
if (arm->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(arm->id.properties, fd);
lib_link_animdata(fd, &arm->id, arm->adt);
+
+ for (Bone *curbone = arm->bonebase.first; curbone; curbone = curbone->next) {
+ lib_link_bones(fd, curbone);
+ }
+
arm->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -3362,14 +3408,13 @@ static void direct_link_armature(FileData *fd, bArmature *arm)
static void lib_link_camera(FileData *fd, Main *main)
{
- Camera *ca;
-
- for (ca = main->camera.first; ca; ca = ca->id.next) {
+ for (Camera *ca = main->camera.first; ca; ca = ca->id.next) {
if (ca->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(ca->id.properties, fd);
lib_link_animdata(fd, &ca->id, ca->adt);
ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX deprecated - old animation system
-
+
ca->dof_ob = newlibadr(fd, ca->id.lib, ca->dof_ob);
ca->id.tag &= ~LIB_TAG_NEED_LINK;
@@ -3388,16 +3433,13 @@ static void direct_link_camera(FileData *fd, Camera *ca)
static void lib_link_lamp(FileData *fd, Main *main)
{
- Lamp *la;
- MTex *mtex;
- int a;
-
- for (la = main->lamp.first; la; la = la->id.next) {
+ for (Lamp *la = main->lamp.first; la; la = la->id.next) {
if (la->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(la->id.properties, fd);
lib_link_animdata(fd, &la->id, la->adt);
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = la->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = la->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, la->id.lib, mtex->tex);
mtex->object = newlibadr(fd, la->id.lib, mtex->object);
@@ -3454,17 +3496,11 @@ void blo_do_versions_key_uidgen(Key *key)
static void lib_link_key(FileData *fd, Main *main)
{
- Key *key;
-
- for (key = main->key.first; key; key = key->id.next) {
- /*check if we need to generate unique ids for the shapekeys*/
- if (!key->uidgen) {
- blo_do_versions_key_uidgen(key);
- }
-
+ for (Key *key = main->key.first; key; key = key->id.next) {
BLI_assert((key->id.tag & LIB_TAG_EXTERN) == 0);
if (key->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(key->id.properties, fd);
lib_link_animdata(fd, &key->id, key->adt);
key->ipo = newlibadr_us(fd, key->id.lib, key->ipo); // XXX deprecated - old animation system
@@ -3527,15 +3563,14 @@ static void direct_link_key(FileData *fd, Key *key)
static void lib_link_mball(FileData *fd, Main *main)
{
- MetaBall *mb;
- int a;
-
- for (mb = main->mball.first; mb; mb = mb->id.next) {
+ for (MetaBall *mb = main->mball.first; mb; mb = mb->id.next) {
if (mb->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(mb->id.properties, fd);
lib_link_animdata(fd, &mb->id, mb->adt);
- for (a = 0; a < mb->totcol; a++)
+ for (int a = 0; a < mb->totcol; a++) {
mb->mat[a] = newlibadr_us(fd, mb->id.lib, mb->mat[a]);
+ }
mb->ipo = newlibadr_us(fd, mb->id.lib, mb->ipo); // XXX deprecated - old animation system
@@ -3564,18 +3599,15 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
static void lib_link_world(FileData *fd, Main *main)
{
- World *wrld;
- MTex *mtex;
- int a;
-
- for (wrld = main->world.first; wrld; wrld = wrld->id.next) {
+ for (World *wrld = main->world.first; wrld; wrld = wrld->id.next) {
if (wrld->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(wrld->id.properties, fd);
lib_link_animdata(fd, &wrld->id, wrld->adt);
wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system
- for (a=0; a < MAX_MTEX; a++) {
- mtex = wrld->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = wrld->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, wrld->id.lib, mtex->tex);
mtex->object = newlibadr(fd, wrld->id.lib, mtex->object);
@@ -3616,12 +3648,12 @@ static void direct_link_world(FileData *fd, World *wrld)
/* ************ READ VFONT ***************** */
-static void lib_link_vfont(FileData *UNUSED(fd), Main *main)
+static void lib_link_vfont(FileData *fd, Main *main)
{
- VFont *vf;
-
- for (vf = main->vfont.first; vf; vf = vf->id.next) {
+ for (VFont *vf = main->vfont.first; vf; vf = vf->id.next) {
if (vf->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(vf->id.properties, fd);
+
vf->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -3636,12 +3668,12 @@ static void direct_link_vfont(FileData *fd, VFont *vf)
/* ************ READ TEXT ****************** */
-static void lib_link_text(FileData *UNUSED(fd), Main *main)
+static void lib_link_text(FileData *fd, Main *main)
{
- Text *text;
-
- for (text = main->text.first; text; text = text->id.next) {
+ for (Text *text = main->text.first; text; text = text->id.next) {
if (text->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(text->id.properties, fd);
+
text->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -3690,11 +3722,9 @@ static void direct_link_text(FileData *fd, Text *text)
static void lib_link_image(FileData *fd, Main *main)
{
- Image *ima;
-
- for (ima = main->image.first; ima; ima = ima->id.next) {
+ for (Image *ima = main->image.first; ima; ima = ima->id.next) {
if (ima->id.tag & LIB_TAG_NEED_LINK) {
- IDP_LibLinkProperty(ima->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_LibLinkProperty(ima->id.properties, fd);
ima->id.tag &= ~LIB_TAG_NEED_LINK;
}
@@ -3759,15 +3789,14 @@ static void direct_link_image(FileData *fd, Image *ima)
static void lib_link_curve(FileData *fd, Main *main)
{
- Curve *cu;
- int a;
-
- for (cu = main->curve.first; cu; cu = cu->id.next) {
+ for (Curve *cu = main->curve.first; cu; cu = cu->id.next) {
if (cu->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(cu->id.properties, fd);
lib_link_animdata(fd, &cu->id, cu->adt);
- for (a = 0; a < cu->totcol; a++)
+ for (int a = 0; a < cu->totcol; a++) {
cu->mat[a] = newlibadr_us(fd, cu->id.lib, cu->mat[a]);
+ }
cu->bevobj = newlibadr(fd, cu->id.lib, cu->bevobj);
cu->taperobj = newlibadr(fd, cu->id.lib, cu->taperobj);
@@ -3852,10 +3881,9 @@ static void direct_link_curve(FileData *fd, Curve *cu)
static void lib_link_texture(FileData *fd, Main *main)
{
- Tex *tex;
-
- for (tex = main->tex.first; tex; tex = tex->id.next) {
+ for (Tex *tex = main->tex.first; tex; tex = tex->id.next) {
if (tex->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(tex->id.properties, fd);
lib_link_animdata(fd, &tex->id, tex->adt);
tex->ima = newlibadr_us(fd, tex->id.lib, tex->ima);
@@ -3931,23 +3959,20 @@ static void direct_link_texture(FileData *fd, Tex *tex)
static void lib_link_material(FileData *fd, Main *main)
{
- Material *ma;
- MTex *mtex;
- int a;
-
- for (ma = main->mat.first; ma; ma = ma->id.next) {
+ for (Material *ma = main->mat.first; ma; ma = ma->id.next) {
if (ma->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(ma->id.properties, fd);
lib_link_animdata(fd, &ma->id, ma->adt);
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
- IDP_LibLinkProperty(ma->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_LibLinkProperty(ma->id.properties, fd);
ma->ipo = newlibadr_us(fd, ma->id.lib, ma->ipo); // XXX deprecated - old animation system
ma->group = newlibadr_us(fd, ma->id.lib, ma->group);
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = ma->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = ma->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, ma->id.lib, mtex->tex);
mtex->object = newlibadr(fd, ma->id.lib, mtex->object);
@@ -4078,14 +4103,11 @@ static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd)
static void lib_link_particlesettings(FileData *fd, Main *main)
{
- ParticleSettings *part;
- ParticleDupliWeight *dw;
- MTex *mtex;
- int a;
-
- for (part = main->particle.first; part; part = part->id.next) {
+ for (ParticleSettings *part = main->particle.first; part; part = part->id.next) {
if (part->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(part->id.properties, fd);
lib_link_animdata(fd, &part->id, part->adt);
+
part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system
part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
@@ -4105,6 +4127,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
}
if (part->dupliweights.first && part->dup_group) {
+ ParticleDupliWeight *dw;
int index_ok = 0;
/* check for old files without indices (all indexes 0) */
if (BLI_listbase_is_single(&part->dupliweights)) {
@@ -4169,8 +4192,8 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
}
}
- for (a = 0; a < MAX_MTEX; a++) {
- mtex= part->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex= part->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, part->id.lib, mtex->tex);
mtex->object = newlibadr(fd, part->id.lib, mtex->object);
@@ -4404,7 +4427,7 @@ static void lib_link_mesh(FileData *fd, Main *main)
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
- IDP_LibLinkProperty(me->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_LibLinkProperty(me->id.properties, fd);
lib_link_animdata(fd, &me->id, me->adt);
/* this check added for python created meshes */
@@ -4677,10 +4700,9 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
static void lib_link_latt(FileData *fd, Main *main)
{
- Lattice *lt;
-
- for (lt = main->latt.first; lt; lt = lt->id.next) {
+ for (Lattice *lt = main->latt.first; lt; lt = lt->id.next) {
if (lt->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(lt->id.properties, fd);
lib_link_animdata(fd, &lt->id, lt->adt);
lt->ipo = newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX deprecated - old animation system
@@ -4724,17 +4746,13 @@ static void lib_link_modifiers(FileData *fd, Object *ob)
static void lib_link_object(FileData *fd, Main *main)
{
- Object *ob;
- PartEff *paf;
- bSensor *sens;
- bController *cont;
- bActuator *act;
- void *poin;
- int warn=0, a;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
+ bool warn = false;
+
+ for (Object *ob = main->object.first; ob; ob = ob->id.next) {
if (ob->id.tag & LIB_TAG_NEED_LINK) {
- IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ int a;
+
+ IDP_LibLinkProperty(ob->id.properties, fd);
lib_link_animdata(fd, &ob->id, ob->adt);
// XXX deprecated - old animation system <<<
@@ -4766,17 +4784,17 @@ static void lib_link_object(FileData *fd, Main *main)
}
ob->proxy_group = newlibadr(fd, ob->id.lib, ob->proxy_group);
- poin = ob->data;
+ void *poin = ob->data;
ob->data = newlibadr_us(fd, ob->id.lib, ob->data);
- if (ob->data==NULL && poin!=NULL) {
+ if (ob->data == NULL && poin != NULL) {
if (ob->id.lib)
printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->name);
else
printf("Object %s lost data.\n", ob->id.name + 2);
ob->type = OB_EMPTY;
- warn = 1;
+ warn = true;
if (ob->pose) {
/* we can't call #BKE_pose_free() here because of library linking
@@ -4822,13 +4840,13 @@ static void lib_link_object(FileData *fd, Main *main)
lib_link_nlastrips(fd, &ob->id, &ob->nlastrips);
// >>> XXX deprecated - old animation system
- for (paf = ob->effect.first; paf; paf = paf->next) {
+ for (PartEff *paf = ob->effect.first; paf; paf = paf->next) {
if (paf->type == EFF_PARTICLE) {
paf->group = newlibadr_us(fd, ob->id.lib, paf->group);
}
}
- for (sens = ob->sensors.first; sens; sens = sens->next) {
+ for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) {
for (a = 0; a < sens->totlinks; a++)
sens->links[a] = newglobadr(fd, sens->links[a]);
@@ -4839,7 +4857,7 @@ static void lib_link_object(FileData *fd, Main *main)
}
}
- for (cont = ob->controllers.first; cont; cont = cont->next) {
+ for (bController *cont = ob->controllers.first; cont; cont = cont->next) {
for (a=0; a < cont->totlinks; a++)
cont->links[a] = newglobadr(fd, cont->links[a]);
@@ -4851,86 +4869,117 @@ static void lib_link_object(FileData *fd, Main *main)
cont->totslinks = 0;
}
- for (act = ob->actuators.first; act; act = act->next) {
- if (act->type == ACT_SOUND) {
- bSoundActuator *sa = act->data;
- sa->sound= newlibadr_us(fd, ob->id.lib, sa->sound);
- }
- else if (act->type == ACT_GAME) {
- /* bGameActuator *ga= act->data; */
- }
- else if (act->type == ACT_CAMERA) {
- bCameraActuator *ca = act->data;
- ca->ob= newlibadr(fd, ob->id.lib, ca->ob);
- }
- /* leave this one, it's obsolete but necessary to read for conversion */
- else if (act->type == ACT_ADD_OBJECT) {
- bAddObjectActuator *eoa = act->data;
- if (eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
- }
- else if (act->type == ACT_OBJECT) {
- bObjectActuator *oa = act->data;
- if (oa == NULL) {
- init_actuator(act);
+ for (bActuator *act = ob->actuators.first; act; act = act->next) {
+ switch (act->type) {
+ case ACT_SOUND:
+ {
+ bSoundActuator *sa = act->data;
+ sa->sound = newlibadr_us(fd, ob->id.lib, sa->sound);
+ break;
}
- else {
- oa->reference = newlibadr(fd, ob->id.lib, oa->reference);
+ case ACT_GAME:
+ /* bGameActuator *ga= act->data; */
+ break;
+ case ACT_CAMERA:
+ {
+ bCameraActuator *ca = act->data;
+ ca->ob = newlibadr(fd, ob->id.lib, ca->ob);
+ break;
}
- }
- else if (act->type == ACT_EDIT_OBJECT) {
- bEditObjectActuator *eoa = act->data;
- if (eoa == NULL) {
- init_actuator(act);
+ /* leave this one, it's obsolete but necessary to read for conversion */
+ case ACT_ADD_OBJECT:
+ {
+ bAddObjectActuator *eoa = act->data;
+ if (eoa)
+ eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob);
+ break;
}
- else {
- eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
- eoa->me= newlibadr(fd, ob->id.lib, eoa->me);
+ case ACT_OBJECT:
+ {
+ bObjectActuator *oa = act->data;
+ if (oa == NULL) {
+ init_actuator(act);
+ }
+ else {
+ oa->reference = newlibadr(fd, ob->id.lib, oa->reference);
+ }
+ break;
}
- }
- else if (act->type == ACT_SCENE) {
- bSceneActuator *sa = act->data;
- sa->camera= newlibadr(fd, ob->id.lib, sa->camera);
- sa->scene= newlibadr(fd, ob->id.lib, sa->scene);
- }
- else if (act->type == ACT_ACTION) {
- bActionActuator *aa = act->data;
- aa->act= newlibadr_us(fd, ob->id.lib, aa->act);
- }
- else if (act->type == ACT_SHAPEACTION) {
- bActionActuator *aa = act->data;
- aa->act= newlibadr_us(fd, ob->id.lib, aa->act);
- }
- else if (act->type == ACT_PROPERTY) {
- bPropertyActuator *pa = act->data;
- pa->ob= newlibadr(fd, ob->id.lib, pa->ob);
- }
- else if (act->type == ACT_MESSAGE) {
- bMessageActuator *ma = act->data;
- ma->toObject= newlibadr(fd, ob->id.lib, ma->toObject);
- }
- else if (act->type == ACT_2DFILTER) {
- bTwoDFilterActuator *_2dfa = act->data;
- _2dfa->text= newlibadr(fd, ob->id.lib, _2dfa->text);
- }
- else if (act->type == ACT_PARENT) {
- bParentActuator *parenta = act->data;
- parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob);
- }
- else if (act->type == ACT_STATE) {
- /* bStateActuator *statea = act->data; */
- }
- else if (act->type == ACT_ARMATURE) {
- bArmatureActuator *arma= act->data;
- arma->target= newlibadr(fd, ob->id.lib, arma->target);
- arma->subtarget= newlibadr(fd, ob->id.lib, arma->subtarget);
- }
- else if (act->type == ACT_STEERING) {
- bSteeringActuator *steeringa = act->data;
- steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target);
- steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh);
- }
- else if (act->type == ACT_MOUSE) {
- /* bMouseActuator *moa= act->data; */
+ case ACT_EDIT_OBJECT:
+ {
+ bEditObjectActuator *eoa = act->data;
+ if (eoa == NULL) {
+ init_actuator(act);
+ }
+ else {
+ eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob);
+ eoa->me = newlibadr(fd, ob->id.lib, eoa->me);
+ }
+ break;
+ }
+ case ACT_SCENE:
+ {
+ bSceneActuator *sa = act->data;
+ sa->camera = newlibadr(fd, ob->id.lib, sa->camera);
+ sa->scene = newlibadr(fd, ob->id.lib, sa->scene);
+ break;
+ }
+ case ACT_ACTION:
+ {
+ bActionActuator *aa = act->data;
+ aa->act = newlibadr_us(fd, ob->id.lib, aa->act);
+ break;
+ }
+ case ACT_SHAPEACTION:
+ {
+ bActionActuator *aa = act->data;
+ aa->act = newlibadr_us(fd, ob->id.lib, aa->act);
+ break;
+ }
+ case ACT_PROPERTY:
+ {
+ bPropertyActuator *pa = act->data;
+ pa->ob = newlibadr(fd, ob->id.lib, pa->ob);
+ break;
+ }
+ case ACT_MESSAGE:
+ {
+ bMessageActuator *ma = act->data;
+ ma->toObject = newlibadr(fd, ob->id.lib, ma->toObject);
+ break;
+ }
+ case ACT_2DFILTER:
+ {
+ bTwoDFilterActuator *_2dfa = act->data;
+ _2dfa->text = newlibadr(fd, ob->id.lib, _2dfa->text);
+ break;
+ }
+ case ACT_PARENT:
+ {
+ bParentActuator *parenta = act->data;
+ parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob);
+ break;
+ }
+ case ACT_STATE:
+ /* bStateActuator *statea = act->data; */
+ break;
+ case ACT_ARMATURE:
+ {
+ bArmatureActuator *arma= act->data;
+ arma->target = newlibadr(fd, ob->id.lib, arma->target);
+ arma->subtarget = newlibadr(fd, ob->id.lib, arma->subtarget);
+ break;
+ }
+ case ACT_STEERING:
+ {
+ bSteeringActuator *steeringa = act->data;
+ steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target);
+ steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh);
+ break;
+ }
+ case ACT_MOUSE:
+ /* bMouseActuator *moa = act->data; */
+ break;
}
}
@@ -5662,23 +5711,16 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
static void lib_link_scene(FileData *fd, Main *main)
{
- Scene *sce;
- Base *base, *next;
- Sequence *seq;
- SceneRenderLayer *srl;
- FreestyleModuleConfig *fmc;
- FreestyleLineSet *fls;
-
#ifdef USE_SETSCENE_CHECK
bool need_check_set = false;
int totscene = 0;
#endif
- for (sce = main->scene.first; sce; sce = sce->id.next) {
+ for (Scene *sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->id.tag & LIB_TAG_NEED_LINK) {
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
- IDP_LibLinkProperty(sce->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_LibLinkProperty(sce->id.properties, fd);
lib_link_animdata(fd, &sce->id, sce->adt);
lib_link_keyingsets(fd, &sce->id, &sce->keyingsets);
@@ -5714,7 +5756,7 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
- for (base = sce->base.first; base; base = next) {
+ for (Base *next, *base = sce->base.first; base; base = next) {
next = base->next;
base->object = newlibadr_us(fd, sce->id.lib, base->object);
@@ -5728,8 +5770,11 @@ static void lib_link_scene(FileData *fd, Main *main)
}
}
+ Sequence *seq;
SEQ_BEGIN (sce->ed, seq)
{
+ IDP_LibLinkProperty(seq->prop, fd);
+
if (seq->ipo) seq->ipo = newlibadr_us(fd, sce->id.lib, seq->ipo); // XXX deprecated - old animation system
seq->scene_sound = NULL;
if (seq->scene) {
@@ -5793,13 +5838,13 @@ static void lib_link_scene(FileData *fd, Main *main)
composite_patch(sce->nodetree, sce);
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override);
srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override);
- for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
fmc->script = newlibadr(fd, sce->id.lib, fmc->script);
}
- for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle);
fls->group = newlibadr_us(fd, sce->id.lib, fls->group);
}
@@ -5833,7 +5878,7 @@ static void lib_link_scene(FileData *fd, Main *main)
#ifdef USE_SETSCENE_CHECK
if (need_check_set) {
- for (sce = main->scene.first; sce; sce = sce->id.next) {
+ for (Scene *sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->id.tag & LIB_TAG_NEED_LINK) {
sce->id.tag &= ~LIB_TAG_NEED_LINK;
if (!scene_validate_setscene__liblink(sce, totscene)) {
@@ -6051,9 +6096,13 @@ static void direct_link_scene(FileData *fd, Scene *sce)
seq->strip->transform = NULL;
}
if (seq->flag & SEQ_USE_PROXY) {
- seq->strip->proxy = newdataadr(
- fd, seq->strip->proxy);
- seq->strip->proxy->anim = NULL;
+ seq->strip->proxy = newdataadr(fd, seq->strip->proxy);
+ if (seq->strip->proxy) {
+ seq->strip->proxy->anim = NULL;
+ }
+ else {
+ BKE_sequencer_proxy_set(seq, true);
+ }
}
else {
seq->strip->proxy = NULL;
@@ -6128,6 +6177,11 @@ static void direct_link_scene(FileData *fd, Scene *sce)
link_list(fd, &(sce->r.layers));
link_list(fd, &(sce->r.views));
+
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ srl->prop = newdataadr(fd, srl->prop);
+ IDP_DirectLinkGroup_OrFree(&srl->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ }
for (srl = sce->r.layers.first; srl; srl = srl->next) {
link_list(fd, &(srl->freestyleConfig.modules));
}
@@ -6243,8 +6297,10 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
for (wm = main->wm.first; wm; wm = wm->id.next) {
if (wm->id.tag & LIB_TAG_NEED_LINK) {
- for (win = wm->windows.first; win; win = win->next)
+ /* Note: WM IDProperties are never written to file, hence no need to read/link them here. */
+ for (win = wm->windows.first; win; win = win->next) {
win->screen = newlibadr(fd, NULL, win->screen);
+ }
wm->id.tag &= ~LIB_TAG_NEED_LINK;
}
@@ -6256,13 +6312,12 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
/* relink's grease pencil data's refs */
static void lib_link_gpencil(FileData *fd, Main *main)
{
- bGPdata *gpd;
-
- for (gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
+ for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
if (gpd->id.tag & LIB_TAG_NEED_LINK) {
- gpd->id.tag &= ~LIB_TAG_NEED_LINK;
-
+ IDP_LibLinkProperty(gpd->id.properties, fd);
lib_link_animdata(fd, &gpd->id, gpd->adt);
+
+ gpd->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -6324,12 +6379,11 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
* check lib pointers in call below */
static void lib_link_screen(FileData *fd, Main *main)
{
- bScreen *sc;
- ScrArea *sa;
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
+ for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) {
if (sc->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(sc->id.properties, fd);
id_us_ensure_real(&sc->id);
+
sc->scene = newlibadr(fd, sc->id.lib, sc->scene);
/* this should not happen, but apparently it does somehow. Until we figure out the cause,
@@ -6340,177 +6394,204 @@ static void lib_link_screen(FileData *fd, Main *main)
sc->animtimer = NULL; /* saved in rare cases */
sc->scrubbing = false;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
-
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
sa->full = newlibadr(fd, sc->id.lib, sa->full);
- for (sl = sa->spacedata.first; sl; sl= sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D*) sl;
- BGpic *bgpic = NULL;
-
- v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
- v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
-
- /* should be do_versions but not easy adding into the listbase */
- if (v3d->bgpic) {
- v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic);
- BLI_addtail(&v3d->bgpicbase, bgpic);
- v3d->bgpic = NULL;
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl= sl->next) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = (View3D*) sl;
+ BGpic *bgpic = NULL;
+
+ v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
+ v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
+
+ /* should be do_versions but not easy adding into the listbase */
+ if (v3d->bgpic) {
+ v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic);
+ BLI_addtail(&v3d->bgpicbase, bgpic);
+ v3d->bgpic = NULL;
+ }
+
+ for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima);
+ bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip);
+ }
+ if (v3d->localvd) {
+ v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera);
+ }
+ break;
}
-
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima);
- bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip);
+ case SPACE_IPO:
+ {
+ SpaceIpo *sipo = (SpaceIpo *)sl;
+ bDopeSheet *ads = sipo->ads;
+
+ if (ads) {
+ ads->source = newlibadr(fd, sc->id.lib, ads->source);
+ ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ }
+ break;
}
- if (v3d->localvd) {
- v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera);
+ case SPACE_BUTS:
+ {
+ SpaceButs *sbuts = (SpaceButs *)sl;
+ sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid);
+ if (sbuts->pinid == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
+ break;
}
- }
- else if (sl->spacetype == SPACE_IPO) {
- SpaceIpo *sipo = (SpaceIpo *)sl;
- bDopeSheet *ads = sipo->ads;
-
- if (ads) {
- ads->source = newlibadr(fd, sc->id.lib, ads->source);
- ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ case SPACE_FILE:
+ break;
+ case SPACE_ACTION:
+ {
+ SpaceAction *saction = (SpaceAction *)sl;
+ bDopeSheet *ads = &saction->ads;
+
+ if (ads) {
+ ads->source = newlibadr(fd, sc->id.lib, ads->source);
+ ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ }
+
+ saction->action = newlibadr(fd, sc->id.lib, saction->action);
+ break;
}
- }
- else if (sl->spacetype == SPACE_BUTS) {
- SpaceButs *sbuts = (SpaceButs *)sl;
- sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid);
- if (sbuts->pinid == NULL) {
- sbuts->flag &= ~SB_PIN_CONTEXT;
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image);
+ sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask);
+
+ /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+ * so fingers crossed this works fine!
+ */
+ sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd);
+ break;
}
- }
- else if (sl->spacetype == SPACE_FILE) {
- ;
- }
- else if (sl->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sl;
- bDopeSheet *ads = &saction->ads;
-
- if (ads) {
- ads->source = newlibadr(fd, sc->id.lib, ads->source);
- ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
+ /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+ * so fingers crossed this works fine!
+ */
+ sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd);
+ break;
}
-
- saction->action = newlibadr(fd, sc->id.lib, saction->action);
- }
- else if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image);
- sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask);
-
- /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
- * so fingers crossed this works fine!
- */
- sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd);
- }
- else if (sl->spacetype == SPACE_SEQ) {
- SpaceSeq *sseq = (SpaceSeq *)sl;
-
- /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
- * so fingers crossed this works fine!
- */
- sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd);
+ case SPACE_NLA:
+ {
+ SpaceNla *snla= (SpaceNla *)sl;
+ bDopeSheet *ads= snla->ads;
+
+ if (ads) {
+ ads->source = newlibadr(fd, sc->id.lib, ads->source);
+ ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ }
+ break;
+ }
+ case SPACE_TEXT:
+ {
+ SpaceText *st= (SpaceText *)sl;
- }
- else if (sl->spacetype == SPACE_NLA) {
- SpaceNla *snla= (SpaceNla *)sl;
- bDopeSheet *ads= snla->ads;
-
- if (ads) {
- ads->source = newlibadr(fd, sc->id.lib, ads->source);
- ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ st->text= newlibadr(fd, sc->id.lib, st->text);
+ break;
}
- }
- else if (sl->spacetype == SPACE_TEXT) {
- SpaceText *st= (SpaceText *)sl;
-
- st->text= newlibadr(fd, sc->id.lib, st->text);
- }
- else if (sl->spacetype == SPACE_SCRIPT) {
- SpaceScript *scpt = (SpaceScript *)sl;
- /*scpt->script = NULL; - 2.45 set to null, better re-run the script */
- if (scpt->script) {
- scpt->script = newlibadr(fd, sc->id.lib, scpt->script);
+ case SPACE_SCRIPT:
+ {
+ SpaceScript *scpt = (SpaceScript *)sl;
+ /*scpt->script = NULL; - 2.45 set to null, better re-run the script */
if (scpt->script) {
- SCRIPT_SET_NULL(scpt->script);
+ scpt->script = newlibadr(fd, sc->id.lib, scpt->script);
+ if (scpt->script) {
+ SCRIPT_SET_NULL(scpt->script);
+ }
}
+ break;
}
- }
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOops *so= (SpaceOops *)sl;
- so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
-
- if (so->treestore) {
- TreeStoreElem *tselem;
- BLI_mempool_iter iter;
+ case SPACE_OUTLINER:
+ {
+ SpaceOops *so= (SpaceOops *)sl;
+ so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
+
+ if (so->treestore) {
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+
+ BLI_mempool_iternew(so->treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ tselem->id = newlibadr(fd, NULL, tselem->id);
+ }
+ if (so->treehash) {
+ /* rebuild hash table, because it depends on ids too */
+ so->storeflag |= SO_TREESTORE_REBUILD;
+ }
+ }
+ break;
+ }
+ case SPACE_NODE:
+ {
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
+ bNodeTree *ntree;
+
+ /* node tree can be stored locally in id too, link this first */
+ snode->id = newlibadr(fd, sc->id.lib, snode->id);
+ snode->from = newlibadr(fd, sc->id.lib, snode->from);
+
+ ntree = snode->id ? ntreeFromID(snode->id) : NULL;
+ snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree);
+
+ for (path = snode->treepath.first; path; path = path->next) {
+ if (path == snode->treepath.first) {
+ /* first nodetree in path is same as snode->nodetree */
+ path->nodetree = snode->nodetree;
+ }
+ else
+ path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree);
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- tselem->id = newlibadr(fd, NULL, tselem->id);
+ if (!path->nodetree)
+ break;
}
- if (so->treehash) {
- /* rebuild hash table, because it depends on ids too */
- so->storeflag |= SO_TREESTORE_REBUILD;
+
+ /* remaining path entries are invalid, remove */
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
}
- }
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
- bNodeTreePath *path, *path_next;
- bNodeTree *ntree;
-
- /* node tree can be stored locally in id too, link this first */
- snode->id = newlibadr(fd, sc->id.lib, snode->id);
- snode->from = newlibadr(fd, sc->id.lib, snode->from);
-
- ntree = snode->id ? ntreeFromID(snode->id) : NULL;
- snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree);
-
- for (path = snode->treepath.first; path; path = path->next) {
- if (path == snode->treepath.first) {
- /* first nodetree in path is same as snode->nodetree */
- path->nodetree = snode->nodetree;
+
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
}
- else
- path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree);
-
- if (!path->nodetree)
- break;
+ else {
+ snode->edittree = NULL;
+ }
+ break;
}
-
- /* remaining path entries are invalid, remove */
- for (; path; path = path_next) {
- path_next = path->next;
-
- BLI_remlink(&snode->treepath, path);
- MEM_freeN(path);
+ case SPACE_CLIP:
+ {
+ SpaceClip *sclip = (SpaceClip *)sl;
+
+ sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip);
+ sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask);
+ break;
}
-
- /* edittree is just the last in the path,
- * set this directly since the path may have been shortened above */
- if (snode->treepath.last) {
- path = snode->treepath.last;
- snode->edittree = path->nodetree;
+ case SPACE_LOGIC:
+ {
+ SpaceLogic *slogic = (SpaceLogic *)sl;
+
+ slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd);
+ break;
}
- else
- snode->edittree = NULL;
- }
- else if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = (SpaceClip *)sl;
-
- sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip);
- sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask);
- }
- else if (sl->spacetype == SPACE_LOGIC) {
- SpaceLogic *slogic = (SpaceLogic *)sl;
-
- slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd);
+ default:
+ break;
}
}
}
@@ -7384,13 +7465,13 @@ static void fix_relpaths_library(const char *basepath, Main *main)
static void lib_link_speaker(FileData *fd, Main *main)
{
- Speaker *spk;
-
- for (spk = main->speaker.first; spk; spk = spk->id.next) {
+ for (Speaker *spk = main->speaker.first; spk; spk = spk->id.next) {
if (spk->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(spk->id.properties, fd);
lib_link_animdata(fd, &spk->id, spk->adt);
spk->sound = newlibadr_us(fd, spk->id.lib, spk->sound);
+
spk->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -7440,14 +7521,15 @@ static void direct_link_sound(FileData *fd, bSound *sound)
static void lib_link_sound(FileData *fd, Main *main)
{
- bSound *sound;
-
- for (sound = main->sound.first; sound; sound = sound->id.next) {
+ for (bSound *sound = main->sound.first; sound; sound = sound->id.next) {
if (sound->id.tag & LIB_TAG_NEED_LINK) {
- sound->id.tag &= ~LIB_TAG_NEED_LINK;
+ IDP_LibLinkProperty(sound->id.properties, fd);
+
sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system
BKE_sound_load(main, sound);
+
+ sound->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -7462,17 +7544,13 @@ static void direct_link_group(FileData *fd, Group *group)
static void lib_link_group(FileData *fd, Main *main)
{
- Group *group;
- GroupObject *go;
- bool add_us;
-
- for (group = main->group.first; group; group = group->id.next) {
+ for (Group *group = main->group.first; group; group = group->id.next) {
if (group->id.tag & LIB_TAG_NEED_LINK) {
- group->id.tag &= ~LIB_TAG_NEED_LINK;
+ IDP_LibLinkProperty(group->id.properties, fd);
- add_us = false;
+ bool add_us = false;
- for (go = group->gobject.first; go; go = go->next) {
+ for (GroupObject *go = group->gobject.first; go; go = go->next) {
go->ob = newlibadr_real_us(fd, group->id.lib, go->ob);
if (go->ob) {
go->ob->flag |= OB_FROMGROUP;
@@ -7484,6 +7562,8 @@ static void lib_link_group(FileData *fd, Main *main)
id_us_ensure_real(&group->id);
}
BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */
+
+ group->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -7588,13 +7668,11 @@ static void lib_link_moviePlaneTracks(FileData *fd, MovieClip *clip, ListBase *t
static void lib_link_movieclip(FileData *fd, Main *main)
{
- MovieClip *clip;
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ for (MovieClip *clip = main->movieclip.first; clip; clip = clip->id.next) {
if (clip->id.tag & LIB_TAG_NEED_LINK) {
MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
+ IDP_LibLinkProperty(clip->id.properties, fd);
lib_link_animdata(fd, &clip->id, clip->adt);
clip->gpd = newlibadr_us(fd, clip->id.lib, clip->gpd);
@@ -7602,7 +7680,7 @@ static void lib_link_movieclip(FileData *fd, Main *main)
lib_link_movieTracks(fd, clip, &tracking->tracks);
lib_link_moviePlaneTracks(fd, clip, &tracking->plane_tracks);
- for (object = tracking->objects.first; object; object = object->next) {
+ for (MovieTrackingObject *object = tracking->objects.first; object; object = object->next) {
lib_link_movieTracks(fd, clip, &object->tracks);
lib_link_moviePlaneTracks(fd, clip, &object->plane_tracks);
}
@@ -7679,16 +7757,12 @@ static void lib_link_mask_parent(FileData *fd, Mask *mask, MaskParent *parent)
static void lib_link_mask(FileData *fd, Main *main)
{
- Mask *mask;
-
- mask = main->mask.first;
- while (mask) {
+ for (Mask *mask = main->mask.first; mask; mask = mask->id.next) {
if (mask->id.tag & LIB_TAG_NEED_LINK) {
- MaskLayer *masklay;
-
+ IDP_LibLinkProperty(mask->id.properties, fd);
lib_link_animdata(fd, &mask->id, mask->adt);
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ for (MaskLayer *masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
spline = masklay->splines.first;
@@ -7709,7 +7783,6 @@ static void lib_link_mask(FileData *fd, Main *main)
mask->id.tag &= ~LIB_TAG_NEED_LINK;
}
- mask = mask->id.next;
}
}
@@ -7717,18 +7790,13 @@ static void lib_link_mask(FileData *fd, Main *main)
static void lib_link_linestyle(FileData *fd, Main *main)
{
- FreestyleLineStyle *linestyle;
- LineStyleModifier *m;
- MTex *mtex;
- int a;
-
- linestyle = main->linestyle.first;
- while (linestyle) {
+ for (FreestyleLineStyle *linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
if (linestyle->id.tag & LIB_TAG_NEED_LINK) {
- linestyle->id.tag &= ~LIB_TAG_NEED_LINK;
+ LineStyleModifier *m;
- IDP_LibLinkProperty(linestyle->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ IDP_LibLinkProperty(linestyle->id.properties, fd);
lib_link_animdata(fd, &linestyle->id, linestyle->adt);
+
for (m = linestyle->color_modifiers.first; m; m = m->next) {
switch (m->type) {
case LS_MODIFIER_DISTANCE_FROM_OBJECT:
@@ -7759,8 +7827,8 @@ static void lib_link_linestyle(FileData *fd, Main *main)
break;
}
}
- for (a=0; a < MAX_MTEX; a++) {
- mtex = linestyle->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = linestyle->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, linestyle->id.lib, mtex->tex);
mtex->object = newlibadr(fd, linestyle->id.lib, mtex->object);
@@ -7770,8 +7838,9 @@ static void lib_link_linestyle(FileData *fd, Main *main)
lib_link_ntree(fd, &linestyle->id, linestyle->nodetree);
linestyle->nodetree->id.lib = linestyle->id.lib;
}
+
+ linestyle->id.tag &= ~LIB_TAG_NEED_LINK;
}
- linestyle = linestyle->id.next;
}
}
@@ -8442,12 +8511,13 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_screen(fd, main);
lib_link_scene(fd, main);
lib_link_object(fd, main);
+ lib_link_mesh(fd, main);
lib_link_curve(fd, main);
lib_link_mball(fd, main);
lib_link_material(fd, main);
lib_link_texture(fd, main);
lib_link_image(fd, main);
- lib_link_ipo(fd, main); // XXX deprecated... still needs to be maintained for version patches still
+ lib_link_ipo(fd, main); /* XXX deprecated... still needs to be maintained for version patches still */
lib_link_key(fd, main);
lib_link_world(fd, main);
lib_link_lamp(fd, main);
@@ -8460,7 +8530,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_armature(fd, main);
lib_link_action(fd, main);
lib_link_vfont(fd, main);
- lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
+ lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
lib_link_brush(fd, main);
lib_link_palette(fd, main);
lib_link_paint_curve(fd, main);
@@ -8471,9 +8541,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_gpencil(fd, main);
lib_link_cachefiles(fd, main);
- lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
-
- lib_link_library(fd, main); /* only init users */
+ lib_link_library(fd, main); /* only init users */
}
static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi)
@@ -8597,7 +8665,12 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
bhead = read_global(bfd, fd, bhead);
break;
case USER:
- bhead = read_userdef(bfd, fd, bhead);
+ if (fd->skip_flags & BLO_READ_SKIP_USERDEF) {
+ bhead = blo_nextbhead(fd, bhead);
+ }
+ else {
+ bhead = read_userdef(bfd, fd, bhead);
+ }
break;
case ENDB:
bhead = NULL;
@@ -8606,15 +8679,25 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
case ID_ID:
/* Always adds to the most recently loaded ID_LI block, see direct_link_library.
* This is part of the file format definition. */
- bhead = read_libblock(fd, mainlist.last, bhead, LIB_TAG_READ | LIB_TAG_EXTERN, NULL);
+ if (fd->skip_flags & BLO_READ_SKIP_DATA) {
+ bhead = blo_nextbhead(fd, bhead);
+ }
+ else {
+ bhead = read_libblock(fd, mainlist.last, bhead, LIB_TAG_READ | LIB_TAG_EXTERN, NULL);
+ }
break;
-
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
case ID_SCRN:
bhead->code = ID_SCR;
- /* deliberate pass on to default */
+ /* pass on to default */
+ ATTR_FALLTHROUGH;
default:
- bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, NULL);
+ if (fd->skip_flags & BLO_READ_SKIP_DATA) {
+ bhead = blo_nextbhead(fd, bhead);
+ }
+ else {
+ bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, NULL);
+ }
}
}
@@ -8879,6 +8962,31 @@ static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *ch
}
}
+static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop)
+{
+ if (!prop)
+ return;
+
+ switch (prop->type) {
+ case IDP_ID:
+ expand_doit(fd, mainvar, IDP_Id(prop));
+ break;
+ case IDP_IDPARRAY:
+ {
+ IDProperty *idp_array = IDP_IDPArray(prop);
+ for (int i = 0; i < prop->len; i++) {
+ expand_idprops(fd, mainvar, &idp_array[i]);
+ }
+ break;
+ }
+ case IDP_GROUP:
+ for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) {
+ expand_idprops(fd, mainvar, loop);
+ }
+ break;
+ }
+}
+
static void expand_fmodifiers(FileData *fd, Main *mainvar, ListBase *list)
{
FModifier *fcm;
@@ -9064,6 +9172,7 @@ static void expand_key(FileData *fd, Main *mainvar, Key *key)
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
{
bNode *node;
+ bNodeSocket *sock;
if (ntree->adt)
expand_animdata(fd, mainvar, ntree->adt);
@@ -9072,10 +9181,22 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
expand_doit(fd, mainvar, ntree->gpd);
for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id && node->type != CMP_NODE_R_LAYERS)
+ if (node->id && node->type != CMP_NODE_R_LAYERS) {
expand_doit(fd, mainvar, node->id);
+ }
+
+ expand_idprops(fd, mainvar, node->prop);
+
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ expand_doit(fd, mainvar, sock->prop);
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ expand_doit(fd, mainvar, sock->prop);
}
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ expand_doit(fd, mainvar, sock->prop);
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ expand_doit(fd, mainvar, sock->prop);
}
static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
@@ -9293,17 +9414,6 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
}
}
-#if 0 /* Disabled as it doesn't actually do anything except recurse... */
-static void expand_bones(FileData *fd, Main *mainvar, Bone *bone)
-{
- Bone *curBone;
-
- for (curBone = bone->childbase.first; curBone; curBone=curBone->next) {
- expand_bones(fd, mainvar, curBone);
- }
-}
-#endif
-
static void expand_pose(FileData *fd, Main *mainvar, bPose *pose)
{
bPoseChannel *chan;
@@ -9313,24 +9423,28 @@ static void expand_pose(FileData *fd, Main *mainvar, bPose *pose)
for (chan = pose->chanbase.first; chan; chan = chan->next) {
expand_constraints(fd, mainvar, &chan->constraints);
+ expand_idprops(fd, mainvar, chan->prop);
expand_doit(fd, mainvar, chan->custom);
}
}
+static void expand_bones(FileData *fd, Main *mainvar, Bone *bone)
+{
+ expand_idprops(fd, mainvar, bone->prop);
+
+ for (Bone *curBone = bone->childbase.first; curBone; curBone = curBone->next) {
+ expand_bones(fd, mainvar, curBone);
+ }
+}
+
static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
-{
+{
if (arm->adt)
expand_animdata(fd, mainvar, arm->adt);
-
-#if 0 /* Disabled as this currently only recurses down the chain doing nothing */
- {
- Bone *curBone;
-
- for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) {
- expand_bones(fd, mainvar, curBone);
- }
+
+ for (Bone *curBone = arm->bonebase.first; curBone; curBone = curBone->next) {
+ expand_bones(fd, mainvar, curBone);
}
-#endif
}
static void expand_object_expandModifiers(
@@ -9558,6 +9672,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
SEQ_BEGIN (sce->ed, seq)
{
+ expand_idprops(fd, mainvar, seq->prop);
+
if (seq->scene) expand_doit(fd, mainvar, seq->scene);
if (seq->scene_camera) expand_doit(fd, mainvar, seq->scene_camera);
if (seq->clip) expand_doit(fd, mainvar, seq->clip);
@@ -9715,6 +9831,8 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
id = lbarray[a]->first;
while (id) {
if (id->tag & LIB_TAG_NEED_EXPAND) {
+ expand_idprops(fd, mainvar, id->properties);
+
switch (GS(id->name)) {
case ID_OB:
expand_object(fd, mainvar, (Object *)id);
@@ -10041,7 +10159,7 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh)
static ID *link_named_part_ex(
Main *mainl, FileData *fd, const short idcode, const char *name, const short flag,
- Scene *scene, View3D *v3d, const bool use_placeholders, const bool force_indirect)
+ Scene *scene, View3D *v3d, const bool use_placeholders, const bool force_indirect)
{
ID *id = link_named_part(mainl, fd, idcode, name, use_placeholders, force_indirect);
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index d97bef13a78..62ce15a640e 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -81,6 +81,8 @@ typedef struct FileData {
int id_name_offs; /* used to retrieve ID names from (bhead+1) */
int globalf, fileflags; /* for do_versions patching */
+ eBLOReadSkip skip_flags; /* skip some data-blocks */
+
struct OldNewMap *datamap;
struct OldNewMap *globmap;
struct OldNewMap *libmap;
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index ab3d14af882..77542d8deb9 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -1000,7 +1000,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
{
/* convert extended ascii to utf-8 for text editor */
Text *text;
- for (text = main->text.first; text; text = text->id.next)
+ for (text = main->text.first; text; text = text->id.next) {
if (!(text->flags & TXT_ISEXT)) {
TextLine *tl;
@@ -1013,6 +1013,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
text->curc = 0;
}
}
+ }
}
{
/* set new dynamic paint values */
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index d3f33cf725f..d2f43a2d79e 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -80,6 +80,7 @@
#include "NOD_common.h"
#include "NOD_socket.h"
+#include "NOD_composite.h"
#include "readfile.h"
@@ -248,6 +249,41 @@ static void do_version_hue_sat_node(bNodeTree *ntree, bNode *node)
node->storage = NULL;
}
+static void do_versions_compositor_render_passes_storage(bNode *node)
+{
+ int pass_index = 0;
+ const char *sockname;
+ for (bNodeSocket *sock = node->outputs.first; sock && pass_index < 31; sock = sock->next, pass_index++) {
+ if (sock->storage == NULL) {
+ NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+ sock->storage = sockdata;
+ BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(pass_index), sizeof(sockdata->pass_name));
+
+ if (pass_index == 0) sockname = "Image";
+ else if (pass_index == 1) sockname = "Alpha";
+ else sockname = node_cmp_rlayers_sock_to_pass(pass_index);
+ BLI_strncpy(sock->name, sockname, sizeof(sock->name));
+ }
+ }
+}
+
+static void do_versions_compositor_render_passes(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS) {
+ /* First we make sure existing sockets have proper names.
+ * This is important because otherwise verification will
+ * drop links from sockets which were renamed.
+ */
+ do_versions_compositor_render_passes_storage(node);
+ /* Make sure new sockets are properly created. */
+ node_verify_socket_templates(ntree, node);
+ /* Make sure all possibly created sockets have proper storage. */
+ do_versions_compositor_render_passes_storage(node);
+ }
+ }
+}
+
void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
{
if (!MAIN_VERSION_ATLEAST(main, 270, 0)) {
@@ -1259,7 +1295,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
for (Camera *camera = main->camera.first; camera != NULL; camera = camera->id.next) {
if (camera->stereo.pole_merge_angle_from == 0.0f &&
- camera->stereo.pole_merge_angle_to == 0.0f)
+ camera->stereo.pole_merge_angle_to == 0.0f)
{
camera->stereo.pole_merge_angle_from = DEG2RADF(60.0f);
camera->stereo.pole_merge_angle_to = DEG2RADF(75.0f);
@@ -1559,8 +1595,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
- /* To be added to next subversion bump! */
- {
+ if (!MAIN_VERSION_ATLEAST(main, 278, 5)) {
/* Mask primitive adding code was not initializing correctly id_type of its points' parent. */
for (Mask *mask = main->mask.first; mask; mask = mask->id.next) {
for (MaskLayer *mlayer = mask->masklayers.first; mlayer; mlayer = mlayer->next) {
@@ -1609,6 +1644,25 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ do_versions_compositor_render_passes(ntree);
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ if (scene->r.im_format.exr_codec == R_IMF_EXR_CODEC_DWAB) {
+ scene->r.im_format.exr_codec = R_IMF_EXR_CODEC_DWAA;
+ }
+ }
+
+ /* Fix related to VGroup modifiers creating named defgroup CD layers! See T51520. */
+ for (Mesh *me = main->mesh.first; me; me = me->id.next) {
+ CustomData_set_layer_name(&me->vdata, CD_MDEFORMVERT, 0, "");
+ }
}
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 99d9e140481..e7e0054e7a1 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -68,6 +68,18 @@ void BLO_update_defaults_userpref_blend(void)
* but take care since some hardware has driver bugs here (T46962).
* Further hardware workarounds should be made in gpu_extensions.c */
U.glalphaclip = (1.0f / 255);
+
+ /* default so DPI is detected automatically */
+ U.dpi = 0;
+ U.ui_scale = 1.0f;
+
+#ifdef WITH_PYTHON_SECURITY
+ /* use alternative setting for security nuts
+ * otherwise we'd need to patch the binary blob - startup.blend.c */
+ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
+#else
+ U.flag &= ~USER_SCRIPT_AUTOEXEC_DISABLE;
+#endif
}
/**
@@ -230,13 +242,13 @@ void BLO_update_defaults_startup_blend(Main *bmain)
/* remove polish brush (flatten/contrast does the same) */
br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Polish");
if (br) {
- BKE_libblock_free(bmain, br);
+ BKE_libblock_delete(bmain, br);
}
/* remove brush brush (huh?) from some modes (draw brushes do the same) */
br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Brush");
if (br) {
- BKE_libblock_free(bmain, br);
+ BKE_libblock_delete(bmain, br);
}
/* remove draw brush from texpaint (draw brushes do the same) */
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index f2d42849bcc..c29ffbb76f2 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -2296,11 +2296,12 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
/* during 2.41 images with this name were used for viewer node output, lets fix that */
if (main->versionfile == 241) {
Image *ima;
- for (ima = main->image.first; ima; ima = ima->id.next)
+ for (ima = main->image.first; ima; ima = ima->id.next) {
if (STREQ(ima->name, "Compositor")) {
strcpy(ima->id.name + 2, "Viewer Node");
strcpy(ima->name, "Viewer Node");
}
+ }
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 01d07e0d774..ee9665dc834 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -797,26 +797,22 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
}
}
-static void write_actions(WriteData *wd, ListBase *idbase)
+static void write_action(WriteData *wd, bAction *act)
{
- for (bAction *act = idbase->first; act; act = act->id.next) {
- if (act->id.us > 0 || wd->current) {
- writestruct(wd, ID_AC, bAction, 1, act);
- write_iddata(wd, &act->id);
+ if (act->id.us > 0 || wd->current) {
+ writestruct(wd, ID_AC, bAction, 1, act);
+ write_iddata(wd, &act->id);
- write_fcurves(wd, &act->curves);
+ write_fcurves(wd, &act->curves);
- for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) {
- writestruct(wd, DATA, bActionGroup, 1, grp);
- }
+ for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) {
+ writestruct(wd, DATA, bActionGroup, 1, grp);
+ }
- for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
- writestruct(wd, DATA, TimeMarker, 1, marker);
- }
+ for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
+ writestruct(wd, DATA, TimeMarker, 1, marker);
}
}
-
- mywrite_flush(wd);
}
static void write_keyingsets(WriteData *wd, ListBase *list)
@@ -965,7 +961,7 @@ static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree),
}
}
/* this is only direct data, tree itself should have been written */
-static void write_nodetree(WriteData *wd, bNodeTree *ntree)
+static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
@@ -1056,7 +1052,7 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
writestruct(wd, DATA, NodeImageMultiFileSocket, 1, sock->storage);
}
}
- if (node->type == CMP_NODE_IMAGE) {
+ if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) {
/* write extra socket info */
for (sock = node->outputs.first; sock; sock = sock->next) {
writestruct(wd, DATA, NodeImageLayer, 1, sock->storage);
@@ -1293,60 +1289,60 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
}
}
}
-static void write_particlesettings(WriteData *wd, ListBase *idbase)
+
+static void write_particlesettings(WriteData *wd, ParticleSettings *part)
{
- for (ParticleSettings *part = idbase->first; part; part = part->id.next) {
- if (part->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_PA, ParticleSettings, 1, part);
- write_iddata(wd, &part->id);
-
- if (part->adt) {
- write_animdata(wd, part->adt);
- }
- writestruct(wd, DATA, PartDeflect, 1, part->pd);
- writestruct(wd, DATA, PartDeflect, 1, part->pd2);
- writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights);
+ if (part->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_PA, ParticleSettings, 1, part);
+ write_iddata(wd, &part->id);
- if (part->clumpcurve) {
- write_curvemapping(wd, part->clumpcurve);
- }
- if (part->roughcurve) {
- write_curvemapping(wd, part->roughcurve);
- }
+ if (part->adt) {
+ write_animdata(wd, part->adt);
+ }
+ writestruct(wd, DATA, PartDeflect, 1, part->pd);
+ writestruct(wd, DATA, PartDeflect, 1, part->pd2);
+ writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights);
- for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
- /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
- if (dw->ob != NULL) {
- dw->index = 0;
- if (part->dup_group) { /* can be NULL if lining fails or set to None */
- for (GroupObject *go = part->dup_group->gobject.first;
- go && go->ob != dw->ob;
- go = go->next, dw->index++);
- }
+ if (part->clumpcurve) {
+ write_curvemapping(wd, part->clumpcurve);
+ }
+ if (part->roughcurve) {
+ write_curvemapping(wd, part->roughcurve);
+ }
+
+ for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
+ /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
+ if (dw->ob != NULL) {
+ dw->index = 0;
+ if (part->dup_group) { /* can be NULL if lining fails or set to None */
+ for (GroupObject *go = part->dup_group->gobject.first;
+ go && go->ob != dw->ob;
+ go = go->next, dw->index++);
}
- writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
}
+ writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
+ }
- if (part->boids && part->phystype == PART_PHYS_BOIDS) {
- writestruct(wd, DATA, BoidSettings, 1, part->boids);
+ if (part->boids && part->phystype == PART_PHYS_BOIDS) {
+ writestruct(wd, DATA, BoidSettings, 1, part->boids);
- for (BoidState *state = part->boids->states.first; state; state = state->next) {
- write_boid_state(wd, state);
- }
- }
- if (part->fluid && part->phystype == PART_PHYS_FLUID) {
- writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
+ for (BoidState *state = part->boids->states.first; state; state = state->next) {
+ write_boid_state(wd, state);
}
+ }
+ if (part->fluid && part->phystype == PART_PHYS_FLUID) {
+ writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
+ }
- for (int a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, part->mtex[a]);
- }
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (part->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, part->mtex[a]);
}
}
}
}
+
static void write_particlesystems(WriteData *wd, ListBase *particles)
{
ParticleSystem *psys = particles->first;
@@ -1866,198 +1862,178 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
}
}
-static void write_objects(WriteData *wd, ListBase *idbase)
+static void write_object(WriteData *wd, Object *ob)
{
- for (Object *ob = idbase->first; ob; ob = ob->id.next) {
- if (ob->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_OB, Object, 1, ob);
- write_iddata(wd, &ob->id);
-
- if (ob->adt) {
- write_animdata(wd, ob->adt);
- }
-
- /* direct data */
- writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat);
- writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits);
- /* write_effects(wd, &ob->effect); */ /* not used anymore */
- write_properties(wd, &ob->prop);
- write_sensors(wd, &ob->sensors);
- write_controllers(wd, &ob->controllers);
- write_actuators(wd, &ob->actuators);
-
- if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
- if (arm && ob->pose && arm->act_bone) {
- BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
- }
- }
+ if (ob->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_OB, Object, 1, ob);
+ write_iddata(wd, &ob->id);
- write_pose(wd, ob->pose);
- write_defgroups(wd, &ob->defbase);
- write_constraints(wd, &ob->constraints);
- write_motionpath(wd, ob->mpath);
+ if (ob->adt) {
+ write_animdata(wd, ob->adt);
+ }
- writestruct(wd, DATA, PartDeflect, 1, ob->pd);
- writestruct(wd, DATA, SoftBody, 1, ob->soft);
- if (ob->soft) {
- write_pointcaches(wd, &ob->soft->ptcaches);
- writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
- }
- writestruct(wd, DATA, BulletSoftBody, 1, ob->bsoft);
+ /* direct data */
+ writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat);
+ writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits);
+ /* write_effects(wd, &ob->effect); */ /* not used anymore */
+ write_properties(wd, &ob->prop);
+ write_sensors(wd, &ob->sensors);
+ write_controllers(wd, &ob->controllers);
+ write_actuators(wd, &ob->actuators);
- if (ob->rigidbody_object) {
- /* TODO: if any extra data is added to handle duplis, will need separate function then */
- writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object);
- }
- if (ob->rigidbody_constraint) {
- writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint);
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+ if (arm && ob->pose && arm->act_bone) {
+ BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
}
+ }
- if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
- writestruct(wd, DATA, ImageUser, 1, ob->iuser);
- }
+ write_pose(wd, ob->pose);
+ write_defgroups(wd, &ob->defbase);
+ write_constraints(wd, &ob->constraints);
+ write_motionpath(wd, ob->mpath);
- write_particlesystems(wd, &ob->particlesystem);
- write_modifiers(wd, &ob->modifiers);
+ writestruct(wd, DATA, PartDeflect, 1, ob->pd);
+ writestruct(wd, DATA, SoftBody, 1, ob->soft);
+ if (ob->soft) {
+ write_pointcaches(wd, &ob->soft->ptcaches);
+ writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
+ }
+ writestruct(wd, DATA, BulletSoftBody, 1, ob->bsoft);
- writelist(wd, DATA, LinkData, &ob->pc_ids);
- writelist(wd, DATA, LodLevel, &ob->lodlevels);
+ if (ob->rigidbody_object) {
+ /* TODO: if any extra data is added to handle duplis, will need separate function then */
+ writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object);
+ }
+ if (ob->rigidbody_constraint) {
+ writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint);
+ }
- write_previews(wd, ob->preview);
+ if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
+ writestruct(wd, DATA, ImageUser, 1, ob->iuser);
}
- }
- mywrite_flush(wd);
+ write_particlesystems(wd, &ob->particlesystem);
+ write_modifiers(wd, &ob->modifiers);
+
+ writelist(wd, DATA, LinkData, &ob->pc_ids);
+ writelist(wd, DATA, LodLevel, &ob->lodlevels);
+
+ write_previews(wd, ob->preview);
+ }
}
-static void write_vfonts(WriteData *wd, ListBase *idbase)
+static void write_vfont(WriteData *wd, VFont *vf)
{
- for (VFont *vf = idbase->first; vf; vf = vf->id.next) {
- if (vf->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_VF, VFont, 1, vf);
- write_iddata(wd, &vf->id);
+ if (vf->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_VF, VFont, 1, vf);
+ write_iddata(wd, &vf->id);
- /* direct data */
- if (vf->packedfile) {
- PackedFile *pf = vf->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
- }
+ /* direct data */
+ if (vf->packedfile) {
+ PackedFile *pf = vf->packedfile;
+ writestruct(wd, DATA, PackedFile, 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
}
}
-
- mywrite_flush(wd);
}
-static void write_keys(WriteData *wd, ListBase *idbase)
+static void write_key(WriteData *wd, Key *key)
{
- for (Key *key = idbase->first; key; key = key->id.next) {
- if (key->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_KE, Key, 1, key);
- write_iddata(wd, &key->id);
-
- if (key->adt) {
- write_animdata(wd, key->adt);
- }
+ if (key->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_KE, Key, 1, key);
+ write_iddata(wd, &key->id);
- /* direct data */
- for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
- writestruct(wd, DATA, KeyBlock, 1, kb);
- if (kb->data) {
- writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
- }
+ if (key->adt) {
+ write_animdata(wd, key->adt);
+ }
+
+ /* direct data */
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ writestruct(wd, DATA, KeyBlock, 1, kb);
+ if (kb->data) {
+ writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
}
}
}
-
- mywrite_flush(wd);
}
-static void write_cameras(WriteData *wd, ListBase *idbase)
+static void write_camera(WriteData *wd, Camera *cam)
{
- for (Camera *cam = idbase->first; cam; cam = cam->id.next) {
- if (cam->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_CA, Camera, 1, cam);
- write_iddata(wd, &cam->id);
-
- if (cam->adt) {
- write_animdata(wd, cam->adt);
- }
+ if (cam->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_CA, Camera, 1, cam);
+ write_iddata(wd, &cam->id);
+
+ if (cam->adt) {
+ write_animdata(wd, cam->adt);
}
}
}
-static void write_mballs(WriteData *wd, ListBase *idbase)
+static void write_mball(WriteData *wd, MetaBall *mb)
{
- for (MetaBall *mb = idbase->first; mb; mb = mb->id.next) {
- if (mb->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_MB, MetaBall, 1, mb);
- write_iddata(wd, &mb->id);
+ if (mb->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_MB, MetaBall, 1, mb);
+ write_iddata(wd, &mb->id);
- /* direct data */
- writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat);
- if (mb->adt) {
- write_animdata(wd, mb->adt);
- }
+ /* direct data */
+ writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat);
+ if (mb->adt) {
+ write_animdata(wd, mb->adt);
+ }
- for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) {
- writestruct(wd, DATA, MetaElem, 1, ml);
- }
+ for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) {
+ writestruct(wd, DATA, MetaElem, 1, ml);
}
}
}
-static void write_curves(WriteData *wd, ListBase *idbase)
+static void write_curve(WriteData *wd, Curve *cu)
{
- for (Curve *cu = idbase->first; cu; cu = cu->id.next) {
- if (cu->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_CU, Curve, 1, cu);
- write_iddata(wd, &cu->id);
+ if (cu->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_CU, Curve, 1, cu);
+ write_iddata(wd, &cu->id);
- /* direct data */
- writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat);
- if (cu->adt) {
- write_animdata(wd, cu->adt);
- }
+ /* direct data */
+ writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat);
+ if (cu->adt) {
+ write_animdata(wd, cu->adt);
+ }
- if (cu->vfont) {
- writedata(wd, DATA, cu->len + 1, cu->str);
- writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo);
- writestruct(wd, DATA, TextBox, cu->totbox, cu->tb);
+ if (cu->vfont) {
+ writedata(wd, DATA, cu->len + 1, cu->str);
+ writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo);
+ writestruct(wd, DATA, TextBox, cu->totbox, cu->tb);
+ }
+ else {
+ /* is also the order of reading */
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+ writestruct(wd, DATA, Nurb, 1, nu);
}
- else {
- /* is also the order of reading */
- for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
- writestruct(wd, DATA, Nurb, 1, nu);
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
}
- for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
+ else {
+ writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp);
+ if (nu->knotsu) {
+ writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu);
}
- else {
- writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp);
- if (nu->knotsu) {
- writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu);
- }
- if (nu->knotsv) {
- writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
- }
+ if (nu->knotsv) {
+ writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
}
}
}
}
}
-
- mywrite_flush(wd);
}
static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
@@ -2174,7 +2150,7 @@ static void write_customdata(
}
}
-static void write_meshes(WriteData *wd, ListBase *idbase)
+static void write_mesh(WriteData *wd, Mesh *mesh)
{
#ifdef USE_BMESH_SAVE_AS_COMPAT
const bool save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */
@@ -2182,365 +2158,342 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
const bool save_for_old_blender = false;
#endif
- for (Mesh *mesh = idbase->first; mesh; mesh = mesh->id.next) {
- CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
-
- if (mesh->id.us > 0 || wd->current) {
- /* write LibData */
- if (!save_for_old_blender) {
- /* write a copy of the mesh, don't modify in place because it is
- * not thread safe for threaded renders that are reading this */
- Mesh *old_mesh = mesh;
- Mesh copy_mesh = *mesh;
- mesh = &copy_mesh;
+ CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+
+ if (mesh->id.us > 0 || wd->current) {
+ /* write LibData */
+ if (!save_for_old_blender) {
+ /* write a copy of the mesh, don't modify in place because it is
+ * not thread safe for threaded renders that are reading this */
+ Mesh *old_mesh = mesh;
+ Mesh copy_mesh = *mesh;
+ mesh = &copy_mesh;
#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
- /* cache only - don't write */
- mesh->mface = NULL;
- mesh->totface = 0;
- memset(&mesh->fdata, 0, sizeof(mesh->fdata));
+ /* cache only - don't write */
+ mesh->mface = NULL;
+ mesh->totface = 0;
+ memset(&mesh->fdata, 0, sizeof(mesh->fdata));
#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
- /**
- * Those calls:
- * - Reduce mesh->xdata.totlayer to number of layers to write.
- * - Fill xlayers with those layers to be written.
- * Note that mesh->xdata is from now on invalid for Blender, but this is why the whole mesh is
- * a temp local copy!
- */
- CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
- CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+ /**
+ * Those calls:
+ * - Reduce mesh->xdata.totlayer to number of layers to write.
+ * - Fill xlayers with those layers to be written.
+ * Note that mesh->xdata is from now on invalid for Blender, but this is why the whole mesh is
+ * a temp local copy!
+ */
+ CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
#ifndef USE_BMESH_SAVE_WITHOUT_MFACE /* Do not copy org fdata in this case!!! */
- CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
+ CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
#else
- flayers = flayers_buff;
+ flayers = flayers_buff;
#endif
- CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
- CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
- writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
- write_iddata(wd, &mesh->id);
+ writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
+ write_iddata(wd, &mesh->id);
- /* direct data */
- if (mesh->adt) {
- write_animdata(wd, mesh->adt);
- }
+ /* direct data */
+ if (mesh->adt) {
+ write_animdata(wd, mesh->adt);
+ }
- writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
- writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
+ writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
+ writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
- write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
- /* fdata is really a dummy - written so slots align */
- write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
+ /* fdata is really a dummy - written so slots align */
+ write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
- /* restore pointer */
- mesh = old_mesh;
- }
- else {
+ /* restore pointer */
+ mesh = old_mesh;
+ }
+ else {
#ifdef USE_BMESH_SAVE_AS_COMPAT
- /* write a copy of the mesh, don't modify in place because it is
- * not thread safe for threaded renders that are reading this */
- Mesh *old_mesh = mesh;
- Mesh copy_mesh = *mesh;
- mesh = &copy_mesh;
-
- mesh->mpoly = NULL;
- mesh->mface = NULL;
- mesh->totface = 0;
- mesh->totpoly = 0;
- mesh->totloop = 0;
- CustomData_reset(&mesh->fdata);
- CustomData_reset(&mesh->pdata);
- CustomData_reset(&mesh->ldata);
- mesh->edit_btmesh = NULL;
-
- /* now fill in polys to mfaces */
- /* XXX This breaks writing design, by using temp allocated memory, which will likely generate
- * duplicates in stored 'old' addresses.
- * This is very bad, but do not see easy way to avoid this, aside from generating those data
- * outside of save process itself.
- * Maybe we can live with this, though?
- */
- mesh->totface = BKE_mesh_mpoly_to_mface(&mesh->fdata, &old_mesh->ldata, &old_mesh->pdata,
- mesh->totface, old_mesh->totloop, old_mesh->totpoly);
+ /* write a copy of the mesh, don't modify in place because it is
+ * not thread safe for threaded renders that are reading this */
+ Mesh *old_mesh = mesh;
+ Mesh copy_mesh = *mesh;
+ mesh = &copy_mesh;
+
+ mesh->mpoly = NULL;
+ mesh->mface = NULL;
+ mesh->totface = 0;
+ mesh->totpoly = 0;
+ mesh->totloop = 0;
+ CustomData_reset(&mesh->fdata);
+ CustomData_reset(&mesh->pdata);
+ CustomData_reset(&mesh->ldata);
+ mesh->edit_btmesh = NULL;
+
+ /* now fill in polys to mfaces */
+ /* XXX This breaks writing design, by using temp allocated memory, which will likely generate
+ * duplicates in stored 'old' addresses.
+ * This is very bad, but do not see easy way to avoid this, aside from generating those data
+ * outside of save process itself.
+ * Maybe we can live with this, though?
+ */
+ mesh->totface = BKE_mesh_mpoly_to_mface(
+ &mesh->fdata, &old_mesh->ldata, &old_mesh->pdata,
+ mesh->totface, old_mesh->totloop, old_mesh->totpoly);
- BKE_mesh_update_customdata_pointers(mesh, false);
+ BKE_mesh_update_customdata_pointers(mesh, false);
- CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
- CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
- CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
+ CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+ CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
#if 0
- CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
- CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
#endif
- writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
- write_iddata(wd, &mesh->id);
+ writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
+ write_iddata(wd, &mesh->id);
- /* direct data */
- if (mesh->adt) {
- write_animdata(wd, mesh->adt);
- }
+ /* direct data */
+ if (mesh->adt) {
+ write_animdata(wd, mesh->adt);
+ }
- writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
- /* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */
+ writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
+ /* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */
- write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
- /* harmless for older blender versioins but _not_ writing these keeps file size down */
+ write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
+ /* harmless for older blender versioins but _not_ writing these keeps file size down */
#if 0
- write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
#endif
- CustomData_free(&mesh->fdata, mesh->totface);
- flayers = NULL;
+ CustomData_free(&mesh->fdata, mesh->totface);
+ flayers = NULL;
- /* restore pointer */
- mesh = old_mesh;
+ /* restore pointer */
+ mesh = old_mesh;
#endif /* USE_BMESH_SAVE_AS_COMPAT */
- }
- }
-
- if (vlayers && vlayers != vlayers_buff) {
- MEM_freeN(vlayers);
- }
- if (elayers && elayers != elayers_buff) {
- MEM_freeN(elayers);
- }
- if (flayers && flayers != flayers_buff) {
- MEM_freeN(flayers);
- }
- if (llayers && llayers != llayers_buff) {
- MEM_freeN(llayers);
- }
- if (players && players != players_buff) {
- MEM_freeN(players);
}
}
- mywrite_flush(wd);
+ if (vlayers && vlayers != vlayers_buff) {
+ MEM_freeN(vlayers);
+ }
+ if (elayers && elayers != elayers_buff) {
+ MEM_freeN(elayers);
+ }
+ if (flayers && flayers != flayers_buff) {
+ MEM_freeN(flayers);
+ }
+ if (llayers && llayers != llayers_buff) {
+ MEM_freeN(llayers);
+ }
+ if (players && players != players_buff) {
+ MEM_freeN(players);
+ }
}
-static void write_lattices(WriteData *wd, ListBase *idbase)
+static void write_lattice(WriteData *wd, Lattice *lt)
{
- for (Lattice *lt = idbase->first; lt; lt = lt->id.next) {
- if (lt->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_LT, Lattice, 1, lt);
- write_iddata(wd, &lt->id);
-
- /* write animdata */
- if (lt->adt) {
- write_animdata(wd, lt->adt);
- }
-
- /* direct data */
- writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+ if (lt->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_LT, Lattice, 1, lt);
+ write_iddata(wd, &lt->id);
- write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
+ /* write animdata */
+ if (lt->adt) {
+ write_animdata(wd, lt->adt);
}
- }
- mywrite_flush(wd);
+ /* direct data */
+ writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+
+ write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
+ }
}
-static void write_images(WriteData *wd, ListBase *idbase)
+static void write_image(WriteData *wd, Image *ima)
{
- for (Image *ima = idbase->first; ima; ima = ima->id.next) {
- if (ima->id.us > 0 || wd->current) {
- ImagePackedFile *imapf;
-
- /* Some trickery to keep forward compatibility of packed images. */
- BLI_assert(ima->packedfile == NULL);
- if (ima->packedfiles.first != NULL) {
- imapf = ima->packedfiles.first;
- ima->packedfile = imapf->packedfile;
- }
-
- /* write LibData */
- writestruct(wd, ID_IM, Image, 1, ima);
- write_iddata(wd, &ima->id);
+ if (ima->id.us > 0 || wd->current) {
+ ImagePackedFile *imapf;
- for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
- writestruct(wd, DATA, ImagePackedFile, 1, imapf);
- if (imapf->packedfile) {
- PackedFile *pf = imapf->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
- }
- }
+ /* Some trickery to keep forward compatibility of packed images. */
+ BLI_assert(ima->packedfile == NULL);
+ if (ima->packedfiles.first != NULL) {
+ imapf = ima->packedfiles.first;
+ ima->packedfile = imapf->packedfile;
+ }
- write_previews(wd, ima->preview);
+ /* write LibData */
+ writestruct(wd, ID_IM, Image, 1, ima);
+ write_iddata(wd, &ima->id);
- for (ImageView *iv = ima->views.first; iv; iv = iv->next) {
- writestruct(wd, DATA, ImageView, 1, iv);
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ writestruct(wd, DATA, ImagePackedFile, 1, imapf);
+ if (imapf->packedfile) {
+ PackedFile *pf = imapf->packedfile;
+ writestruct(wd, DATA, PackedFile, 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
}
- writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
+ }
+
+ write_previews(wd, ima->preview);
- ima->packedfile = NULL;
+ for (ImageView *iv = ima->views.first; iv; iv = iv->next) {
+ writestruct(wd, DATA, ImageView, 1, iv);
}
- }
+ writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
- mywrite_flush(wd);
+ ima->packedfile = NULL;
+ }
}
-static void write_textures(WriteData *wd, ListBase *idbase)
+static void write_texture(WriteData *wd, Tex *tex)
{
- for (Tex *tex = idbase->first; tex; tex = tex->id.next) {
- if (tex->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_TE, Tex, 1, tex);
- write_iddata(wd, &tex->id);
-
- if (tex->adt) {
- write_animdata(wd, tex->adt);
- }
+ if (tex->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_TE, Tex, 1, tex);
+ write_iddata(wd, &tex->id);
- /* direct data */
- if (tex->coba) {
- writestruct(wd, DATA, ColorBand, 1, tex->coba);
- }
- if (tex->type == TEX_ENVMAP && tex->env) {
- writestruct(wd, DATA, EnvMap, 1, tex->env);
- }
- if (tex->type == TEX_POINTDENSITY && tex->pd) {
- writestruct(wd, DATA, PointDensity, 1, tex->pd);
- if (tex->pd->coba) {
- writestruct(wd, DATA, ColorBand, 1, tex->pd->coba);
- }
- if (tex->pd->falloff_curve) {
- write_curvemapping(wd, tex->pd->falloff_curve);
- }
- }
- if (tex->type == TEX_VOXELDATA) {
- writestruct(wd, DATA, VoxelData, 1, tex->vd);
- }
- if (tex->type == TEX_OCEAN && tex->ot) {
- writestruct(wd, DATA, OceanTex, 1, tex->ot);
- }
+ if (tex->adt) {
+ write_animdata(wd, tex->adt);
+ }
- /* nodetree is integral part of texture, no libdata */
- if (tex->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, tex->nodetree);
- write_nodetree(wd, tex->nodetree);
+ /* direct data */
+ if (tex->coba) {
+ writestruct(wd, DATA, ColorBand, 1, tex->coba);
+ }
+ if (tex->type == TEX_ENVMAP && tex->env) {
+ writestruct(wd, DATA, EnvMap, 1, tex->env);
+ }
+ if (tex->type == TEX_POINTDENSITY && tex->pd) {
+ writestruct(wd, DATA, PointDensity, 1, tex->pd);
+ if (tex->pd->coba) {
+ writestruct(wd, DATA, ColorBand, 1, tex->pd->coba);
}
+ if (tex->pd->falloff_curve) {
+ write_curvemapping(wd, tex->pd->falloff_curve);
+ }
+ }
+ if (tex->type == TEX_VOXELDATA) {
+ writestruct(wd, DATA, VoxelData, 1, tex->vd);
+ }
+ if (tex->type == TEX_OCEAN && tex->ot) {
+ writestruct(wd, DATA, OceanTex, 1, tex->ot);
+ }
- write_previews(wd, tex->preview);
+ /* nodetree is integral part of texture, no libdata */
+ if (tex->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, tex->nodetree);
+ write_nodetree_nolib(wd, tex->nodetree);
}
- }
- mywrite_flush(wd);
+ write_previews(wd, tex->preview);
+ }
}
-static void write_materials(WriteData *wd, ListBase *idbase)
+static void write_material(WriteData *wd, Material *ma)
{
- for (Material *ma = idbase->first; ma; ma = ma->id.next) {
- if (ma->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_MA, Material, 1, ma);
- write_iddata(wd, &ma->id);
-
- if (ma->adt) {
- write_animdata(wd, ma->adt);
- }
+ if (ma->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_MA, Material, 1, ma);
+ write_iddata(wd, &ma->id);
- for (int a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, ma->mtex[a]);
- }
- }
+ if (ma->adt) {
+ write_animdata(wd, ma->adt);
+ }
- if (ma->ramp_col) {
- writestruct(wd, DATA, ColorBand, 1, ma->ramp_col);
- }
- if (ma->ramp_spec) {
- writestruct(wd, DATA, ColorBand, 1, ma->ramp_spec);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (ma->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, ma->mtex[a]);
}
+ }
- /* nodetree is integral part of material, no libdata */
- if (ma->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, ma->nodetree);
- write_nodetree(wd, ma->nodetree);
- }
+ if (ma->ramp_col) {
+ writestruct(wd, DATA, ColorBand, 1, ma->ramp_col);
+ }
+ if (ma->ramp_spec) {
+ writestruct(wd, DATA, ColorBand, 1, ma->ramp_spec);
+ }
- write_previews(wd, ma->preview);
+ /* nodetree is integral part of material, no libdata */
+ if (ma->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, ma->nodetree);
+ write_nodetree_nolib(wd, ma->nodetree);
}
+
+ write_previews(wd, ma->preview);
}
}
-static void write_worlds(WriteData *wd, ListBase *idbase)
+static void write_world(WriteData *wd, World *wrld)
{
- for (World *wrld = idbase->first; wrld; wrld = wrld->id.next) {
- if (wrld->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_WO, World, 1, wrld);
- write_iddata(wd, &wrld->id);
-
- if (wrld->adt) {
- write_animdata(wd, wrld->adt);
- }
+ if (wrld->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_WO, World, 1, wrld);
+ write_iddata(wd, &wrld->id);
- for (int a = 0; a < MAX_MTEX; a++) {
- if (wrld->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, wrld->mtex[a]);
- }
- }
+ if (wrld->adt) {
+ write_animdata(wd, wrld->adt);
+ }
- /* nodetree is integral part of world, no libdata */
- if (wrld->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree);
- write_nodetree(wd, wrld->nodetree);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (wrld->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, wrld->mtex[a]);
}
+ }
- write_previews(wd, wrld->preview);
+ /* nodetree is integral part of world, no libdata */
+ if (wrld->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree);
+ write_nodetree_nolib(wd, wrld->nodetree);
}
+
+ write_previews(wd, wrld->preview);
}
}
-static void write_lamps(WriteData *wd, ListBase *idbase)
+static void write_lamp(WriteData *wd, Lamp *la)
{
- for (Lamp *la = idbase->first; la; la = la->id.next) {
- if (la->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_LA, Lamp, 1, la);
- write_iddata(wd, &la->id);
-
- if (la->adt) {
- write_animdata(wd, la->adt);
- }
+ if (la->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_LA, Lamp, 1, la);
+ write_iddata(wd, &la->id);
- /* direct data */
- for (int a = 0; a < MAX_MTEX; a++) {
- if (la->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, la->mtex[a]);
- }
- }
+ if (la->adt) {
+ write_animdata(wd, la->adt);
+ }
- if (la->curfalloff) {
- write_curvemapping(wd, la->curfalloff);
+ /* direct data */
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (la->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, la->mtex[a]);
}
+ }
- /* nodetree is integral part of lamps, no libdata */
- if (la->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, la->nodetree);
- write_nodetree(wd, la->nodetree);
- }
+ if (la->curfalloff) {
+ write_curvemapping(wd, la->curfalloff);
+ }
- write_previews(wd, la->preview);
+ /* nodetree is integral part of lamps, no libdata */
+ if (la->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, la->nodetree);
+ write_nodetree_nolib(wd, la->nodetree);
}
- }
- mywrite_flush(wd);
+ write_previews(wd, la->preview);
+ }
}
static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
@@ -2584,267 +2537,256 @@ static void write_paint(WriteData *wd, Paint *p)
}
}
-static void write_scenes(WriteData *wd, ListBase *scebase)
+static void write_scene(WriteData *wd, Scene *sce)
{
- for (Scene *sce = scebase->first; sce; sce = sce->id.next) {
- /* write LibData */
- writestruct(wd, ID_SCE, Scene, 1, sce);
- write_iddata(wd, &sce->id);
+ /* write LibData */
+ writestruct(wd, ID_SCE, Scene, 1, sce);
+ write_iddata(wd, &sce->id);
- if (sce->adt) {
- write_animdata(wd, sce->adt);
- }
- write_keyingsets(wd, &sce->keyingsets);
+ if (sce->adt) {
+ write_animdata(wd, sce->adt);
+ }
+ write_keyingsets(wd, &sce->keyingsets);
- /* direct data */
- for (Base *base = sce->base.first; base; base = base->next) {
- writestruct(wd, DATA, Base, 1, base);
- }
+ /* direct data */
+ for (Base *base = sce->base.first; base; base = base->next) {
+ writestruct(wd, DATA, Base, 1, base);
+ }
- ToolSettings *tos = sce->toolsettings;
- writestruct(wd, DATA, ToolSettings, 1, tos);
- if (tos->vpaint) {
- writestruct(wd, DATA, VPaint, 1, tos->vpaint);
- write_paint(wd, &tos->vpaint->paint);
- }
- if (tos->wpaint) {
- writestruct(wd, DATA, VPaint, 1, tos->wpaint);
- write_paint(wd, &tos->wpaint->paint);
- }
- if (tos->sculpt) {
- writestruct(wd, DATA, Sculpt, 1, tos->sculpt);
- write_paint(wd, &tos->sculpt->paint);
- }
- if (tos->uvsculpt) {
- writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt);
- write_paint(wd, &tos->uvsculpt->paint);
+ ToolSettings *tos = sce->toolsettings;
+ writestruct(wd, DATA, ToolSettings, 1, tos);
+ if (tos->vpaint) {
+ writestruct(wd, DATA, VPaint, 1, tos->vpaint);
+ write_paint(wd, &tos->vpaint->paint);
+ }
+ if (tos->wpaint) {
+ writestruct(wd, DATA, VPaint, 1, tos->wpaint);
+ write_paint(wd, &tos->wpaint->paint);
+ }
+ if (tos->sculpt) {
+ writestruct(wd, DATA, Sculpt, 1, tos->sculpt);
+ write_paint(wd, &tos->sculpt->paint);
+ }
+ if (tos->uvsculpt) {
+ writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt);
+ write_paint(wd, &tos->uvsculpt->paint);
+ }
+ /* write grease-pencil drawing brushes to file */
+ writelist(wd, DATA, bGPDbrush, &tos->gp_brushes);
+ for (bGPDbrush *brush = tos->gp_brushes.first; brush; brush = brush->next) {
+ if (brush->cur_sensitivity) {
+ write_curvemapping(wd, brush->cur_sensitivity);
}
- /* write grease-pencil drawing brushes to file */
- writelist(wd, DATA, bGPDbrush, &tos->gp_brushes);
- for (bGPDbrush *brush = tos->gp_brushes.first; brush; brush = brush->next) {
- if (brush->cur_sensitivity) {
- write_curvemapping(wd, brush->cur_sensitivity);
- }
- if (brush->cur_strength) {
- write_curvemapping(wd, brush->cur_strength);
- }
- if (brush->cur_jitter) {
- write_curvemapping(wd, brush->cur_jitter);
- }
+ if (brush->cur_strength) {
+ write_curvemapping(wd, brush->cur_strength);
}
- /* write grease-pencil custom ipo curve to file */
- if (tos->gp_interpolate.custom_ipo) {
- write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
+ if (brush->cur_jitter) {
+ write_curvemapping(wd, brush->cur_jitter);
}
-
+ }
+ /* write grease-pencil custom ipo curve to file */
+ if (tos->gp_interpolate.custom_ipo) {
+ write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
+ }
- write_paint(wd, &tos->imapaint.paint);
- Editing *ed = sce->ed;
- if (ed) {
- Sequence *seq;
+ write_paint(wd, &tos->imapaint.paint);
- writestruct(wd, DATA, Editing, 1, ed);
+ Editing *ed = sce->ed;
+ if (ed) {
+ Sequence *seq;
- /* reset write flags too */
+ writestruct(wd, DATA, Editing, 1, ed);
- SEQ_BEGIN(ed, seq)
- {
- if (seq->strip) {
- seq->strip->done = false;
- }
- writestruct(wd, DATA, Sequence, 1, seq);
- }
- SEQ_END
+ /* reset write flags too */
- SEQ_BEGIN(ed, seq)
- {
- if (seq->strip && seq->strip->done == 0) {
- /* write strip with 'done' at 0 because readfile */
-
- if (seq->effectdata) {
- switch (seq->type) {
- case SEQ_TYPE_COLOR:
- writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_SPEED:
- writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_WIPE:
- writestruct(wd, DATA, WipeVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_GLOW:
- writestruct(wd, DATA, GlowVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_TRANSFORM:
- writestruct(wd, DATA, TransformVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_GAUSSIAN_BLUR:
- writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_TEXT:
- writestruct(wd, DATA, TextVars, 1, seq->effectdata);
- break;
- }
- }
+ SEQ_BEGIN(ed, seq)
+ {
+ if (seq->strip) {
+ seq->strip->done = false;
+ }
+ writestruct(wd, DATA, Sequence, 1, seq);
+ }
+ SEQ_END
- writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
+ SEQ_BEGIN(ed, seq)
+ {
+ if (seq->strip && seq->strip->done == 0) {
+ /* write strip with 'done' at 0 because readfile */
- Strip *strip = seq->strip;
- writestruct(wd, DATA, Strip, 1, strip);
- if (seq->flag & SEQ_USE_CROP && strip->crop) {
- writestruct(wd, DATA, StripCrop, 1, strip->crop);
- }
- if (seq->flag & SEQ_USE_TRANSFORM && strip->transform) {
- writestruct(wd, DATA, StripTransform, 1, strip->transform);
- }
- if (seq->flag & SEQ_USE_PROXY && strip->proxy) {
- writestruct(wd, DATA, StripProxy, 1, strip->proxy);
- }
- if (seq->type == SEQ_TYPE_IMAGE) {
- writestruct(wd, DATA, StripElem,
- MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem),
- strip->stripdata);
- }
- else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
- writestruct(wd, DATA, StripElem, 1, strip->stripdata);
+ if (seq->effectdata) {
+ switch (seq->type) {
+ case SEQ_TYPE_COLOR:
+ writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_SPEED:
+ writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_WIPE:
+ writestruct(wd, DATA, WipeVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_GLOW:
+ writestruct(wd, DATA, GlowVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_TRANSFORM:
+ writestruct(wd, DATA, TransformVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_TEXT:
+ writestruct(wd, DATA, TextVars, 1, seq->effectdata);
+ break;
}
-
- strip->done = true;
}
- if (seq->prop) {
- IDP_WriteProperty(seq->prop, wd);
+ writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
+
+ Strip *strip = seq->strip;
+ writestruct(wd, DATA, Strip, 1, strip);
+ if (seq->flag & SEQ_USE_CROP && strip->crop) {
+ writestruct(wd, DATA, StripCrop, 1, strip->crop);
+ }
+ if (seq->flag & SEQ_USE_TRANSFORM && strip->transform) {
+ writestruct(wd, DATA, StripTransform, 1, strip->transform);
+ }
+ if (seq->flag & SEQ_USE_PROXY && strip->proxy) {
+ writestruct(wd, DATA, StripProxy, 1, strip->proxy);
+ }
+ if (seq->type == SEQ_TYPE_IMAGE) {
+ writestruct(wd, DATA, StripElem,
+ MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem),
+ strip->stripdata);
+ }
+ else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
+ writestruct(wd, DATA, StripElem, 1, strip->stripdata);
}
- write_sequence_modifiers(wd, &seq->modifiers);
+ strip->done = true;
}
- SEQ_END
- /* new; meta stack too, even when its nasty restore code */
- for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) {
- writestruct(wd, DATA, MetaStack, 1, ms);
+ if (seq->prop) {
+ IDP_WriteProperty(seq->prop, wd);
}
+
+ write_sequence_modifiers(wd, &seq->modifiers);
}
+ SEQ_END
- if (sce->r.avicodecdata) {
- writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata);
- if (sce->r.avicodecdata->lpFormat) {
- writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
- }
- if (sce->r.avicodecdata->lpParms) {
- writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
- }
+ /* new; meta stack too, even when its nasty restore code */
+ for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) {
+ writestruct(wd, DATA, MetaStack, 1, ms);
}
+ }
- if (sce->r.qtcodecdata) {
- writestruct(wd, DATA, QuicktimeCodecData, 1, sce->r.qtcodecdata);
- if (sce->r.qtcodecdata->cdParms) {
- writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms);
- }
+ if (sce->r.avicodecdata) {
+ writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata);
+ if (sce->r.avicodecdata->lpFormat) {
+ writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
}
- if (sce->r.ffcodecdata.properties) {
- IDP_WriteProperty(sce->r.ffcodecdata.properties, wd);
+ if (sce->r.avicodecdata->lpParms) {
+ writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
}
+ }
- /* writing dynamic list of TimeMarkers to the blend file */
- for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) {
- writestruct(wd, DATA, TimeMarker, 1, marker);
+ if (sce->r.qtcodecdata) {
+ writestruct(wd, DATA, QuicktimeCodecData, 1, sce->r.qtcodecdata);
+ if (sce->r.qtcodecdata->cdParms) {
+ writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms);
}
+ }
+ if (sce->r.ffcodecdata.properties) {
+ IDP_WriteProperty(sce->r.ffcodecdata.properties, wd);
+ }
- /* writing dynamic list of TransformOrientations to the blend file */
- for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
- writestruct(wd, DATA, TransformOrientation, 1, ts);
- }
+ /* writing dynamic list of TimeMarkers to the blend file */
+ for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) {
+ writestruct(wd, DATA, TimeMarker, 1, marker);
+ }
- for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
- writestruct(wd, DATA, SceneRenderLayer, 1, srl);
- for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
- writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
- }
- for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
- writestruct(wd, DATA, FreestyleLineSet, 1, fls);
- }
- }
+ /* writing dynamic list of TransformOrientations to the blend file */
+ for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
+ writestruct(wd, DATA, TransformOrientation, 1, ts);
+ }
- /* writing MultiView to the blend file */
- for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
- writestruct(wd, DATA, SceneRenderView, 1, srv);
+ for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
+ writestruct(wd, DATA, SceneRenderLayer, 1, srl);
+ if (srl->prop) {
+ IDP_WriteProperty(srl->prop, wd);
}
-
- if (sce->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, sce->nodetree);
- write_nodetree(wd, sce->nodetree);
+ for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
+ }
+ for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ writestruct(wd, DATA, FreestyleLineSet, 1, fls);
}
+ }
- write_view_settings(wd, &sce->view_settings);
+ /* writing MultiView to the blend file */
+ for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
+ writestruct(wd, DATA, SceneRenderView, 1, srv);
+ }
- /* writing RigidBodyWorld data to the blend file */
- if (sce->rigidbody_world) {
- writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
- writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
- write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
- }
+ if (sce->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, sce->nodetree);
+ write_nodetree_nolib(wd, sce->nodetree);
+ }
- write_previews(wd, sce->preview);
- write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
+ write_view_settings(wd, &sce->view_settings);
+
+ /* writing RigidBodyWorld data to the blend file */
+ if (sce->rigidbody_world) {
+ writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
+ writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
+ write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
}
- mywrite_flush(wd);
+ write_previews(wd, sce->preview);
+ write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
}
-static void write_gpencils(WriteData *wd, ListBase *lb)
+static void write_gpencil(WriteData *wd, bGPdata *gpd)
{
- for (bGPdata *gpd = lb->first; gpd; gpd = gpd->id.next) {
- if (gpd->id.us > 0 || wd->current) {
- /* write gpd data block to file */
- writestruct(wd, ID_GD, bGPdata, 1, gpd);
- write_iddata(wd, &gpd->id);
-
- if (gpd->adt) {
- write_animdata(wd, gpd->adt);
- }
-
- /* write grease-pencil layers to file */
- writelist(wd, DATA, bGPDlayer, &gpd->layers);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* write this layer's frames to file */
- writelist(wd, DATA, bGPDframe, &gpl->frames);
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- /* write strokes */
- writelist(wd, DATA, bGPDstroke, &gpf->strokes);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
- }
+ if (gpd->id.us > 0 || wd->current) {
+ /* write gpd data block to file */
+ writestruct(wd, ID_GD, bGPdata, 1, gpd);
+ write_iddata(wd, &gpd->id);
+
+ if (gpd->adt) {
+ write_animdata(wd, gpd->adt);
+ }
+
+ /* write grease-pencil layers to file */
+ writelist(wd, DATA, bGPDlayer, &gpd->layers);
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* write this layer's frames to file */
+ writelist(wd, DATA, bGPDframe, &gpl->frames);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* write strokes */
+ writelist(wd, DATA, bGPDstroke, &gpf->strokes);
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
}
}
+ }
- /* write grease-pencil palettes */
- writelist(wd, DATA, bGPDpalette, &gpd->palettes);
- for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
- writelist(wd, DATA, bGPDpalettecolor, &palette->colors);
- }
+ /* write grease-pencil palettes */
+ writelist(wd, DATA, bGPDpalette, &gpd->palettes);
+ for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
+ writelist(wd, DATA, bGPDpalettecolor, &palette->colors);
}
}
-
- mywrite_flush(wd);
}
-static void write_windowmanagers(WriteData *wd, ListBase *lb)
+static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
{
- for (wmWindowManager *wm = lb->first; wm; wm = wm->id.next) {
- writestruct(wd, ID_WM, wmWindowManager, 1, wm);
- write_iddata(wd, &wm->id);
+ writestruct(wd, ID_WM, wmWindowManager, 1, wm);
+ write_iddata(wd, &wm->id);
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- writestruct(wd, DATA, wmWindow, 1, win);
- writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
- }
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ writestruct(wd, DATA, wmWindow, 1, win);
+ writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
}
-
- /* typically flushing wouldn't be needed however this data _always_ changes,
- * so flush here for more efficient undo. */
- mywrite_flush(wd);
}
static void write_region(WriteData *wd, ARegion *ar, int spacetype)
@@ -2927,172 +2869,168 @@ static void write_soops(WriteData *wd, SpaceOops *so)
}
}
-static void write_screens(WriteData *wd, ListBase *scrbase)
+static void write_screen(WriteData *wd, bScreen *sc)
{
- for (bScreen *sc = scrbase->first; sc; sc = sc->id.next) {
- /* write LibData */
- /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
- writestruct(wd, ID_SCRN, bScreen, 1, sc);
- write_iddata(wd, &sc->id);
-
- /* direct data */
- for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
- writestruct(wd, DATA, ScrVert, 1, sv);
- }
+ /* write LibData */
+ /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
+ writestruct(wd, ID_SCRN, bScreen, 1, sc);
+ write_iddata(wd, &sc->id);
- for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
- writestruct(wd, DATA, ScrEdge, 1, se);
- }
-
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- Panel *pa;
- uiList *ui_list;
- uiPreview *ui_preview;
- PanelCategoryStack *pc_act;
- ARegion *ar;
-
- writestruct(wd, DATA, ScrArea, 1, sa);
+ /* direct data */
+ for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
+ writestruct(wd, DATA, ScrVert, 1, sv);
+ }
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- write_region(wd, ar, sa->spacetype);
+ for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
+ writestruct(wd, DATA, ScrEdge, 1, se);
+ }
- for (pa = ar->panels.first; pa; pa = pa->next) {
- writestruct(wd, DATA, Panel, 1, pa);
- }
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ Panel *pa;
+ uiList *ui_list;
+ uiPreview *ui_preview;
+ PanelCategoryStack *pc_act;
+ ARegion *ar;
- for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
- writestruct(wd, DATA, PanelCategoryStack, 1, pc_act);
- }
+ writestruct(wd, DATA, ScrArea, 1, sa);
- for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
- write_uilist(wd, ui_list);
- }
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ write_region(wd, ar, sa->spacetype);
- for (ui_preview = ar->ui_previews.first; ui_preview; ui_preview = ui_preview->next) {
- writestruct(wd, DATA, uiPreview, 1, ui_preview);
- }
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ writestruct(wd, DATA, Panel, 1, pa);
}
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- for (ar = sl->regionbase.first; ar; ar = ar->next) {
- write_region(wd, ar, sl->spacetype);
- }
-
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- BGpic *bgpic;
- writestruct(wd, DATA, View3D, 1, v3d);
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- writestruct(wd, DATA, BGpic, 1, bgpic);
- }
- if (v3d->localvd) {
- writestruct(wd, DATA, View3D, 1, v3d->localvd);
- }
+ for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
+ writestruct(wd, DATA, PanelCategoryStack, 1, pc_act);
+ }
- if (v3d->fx_settings.ssao) {
- writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao);
- }
- if (v3d->fx_settings.dof) {
- writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
- }
- }
- else if (sl->spacetype == SPACE_IPO) {
- SpaceIpo *sipo = (SpaceIpo *)sl;
- ListBase tmpGhosts = sipo->ghostCurves;
+ for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
+ write_uilist(wd, ui_list);
+ }
- /* temporarily disable ghost curves when saving */
- sipo->ghostCurves.first = sipo->ghostCurves.last = NULL;
+ for (ui_preview = ar->ui_previews.first; ui_preview; ui_preview = ui_preview->next) {
+ writestruct(wd, DATA, uiPreview, 1, ui_preview);
+ }
+ }
- writestruct(wd, DATA, SpaceIpo, 1, sl);
- if (sipo->ads) {
- writestruct(wd, DATA, bDopeSheet, 1, sipo->ads);
- }
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ for (ar = sl->regionbase.first; ar; ar = ar->next) {
+ write_region(wd, ar, sl->spacetype);
+ }
- /* reenable ghost curves */
- sipo->ghostCurves = tmpGhosts;
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ BGpic *bgpic;
+ writestruct(wd, DATA, View3D, 1, v3d);
+ for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ writestruct(wd, DATA, BGpic, 1, bgpic);
}
- else if (sl->spacetype == SPACE_BUTS) {
- writestruct(wd, DATA, SpaceButs, 1, sl);
+ if (v3d->localvd) {
+ writestruct(wd, DATA, View3D, 1, v3d->localvd);
}
- else if (sl->spacetype == SPACE_FILE) {
- SpaceFile *sfile = (SpaceFile *)sl;
- writestruct(wd, DATA, SpaceFile, 1, sl);
- if (sfile->params) {
- writestruct(wd, DATA, FileSelectParams, 1, sfile->params);
- }
- }
- else if (sl->spacetype == SPACE_SEQ) {
- writestruct(wd, DATA, SpaceSeq, 1, sl);
- }
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOops *so = (SpaceOops *)sl;
- write_soops(wd, so);
- }
- else if (sl->spacetype == SPACE_IMAGE) {
- writestruct(wd, DATA, SpaceImage, 1, sl);
- }
- else if (sl->spacetype == SPACE_TEXT) {
- writestruct(wd, DATA, SpaceText, 1, sl);
+ if (v3d->fx_settings.ssao) {
+ writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao);
}
- else if (sl->spacetype == SPACE_SCRIPT) {
- SpaceScript *scr = (SpaceScript *)sl;
- scr->but_refs = NULL;
- writestruct(wd, DATA, SpaceScript, 1, sl);
+ if (v3d->fx_settings.dof) {
+ writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
}
- else if (sl->spacetype == SPACE_ACTION) {
- writestruct(wd, DATA, SpaceAction, 1, sl);
- }
- else if (sl->spacetype == SPACE_NLA) {
- SpaceNla *snla = (SpaceNla *)sl;
+ }
+ else if (sl->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo = (SpaceIpo *)sl;
+ ListBase tmpGhosts = sipo->ghostCurves;
- writestruct(wd, DATA, SpaceNla, 1, snla);
- if (snla->ads) {
- writestruct(wd, DATA, bDopeSheet, 1, snla->ads);
- }
- }
- else if (sl->spacetype == SPACE_TIME) {
- writestruct(wd, DATA, SpaceTime, 1, sl);
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
- bNodeTreePath *path;
- writestruct(wd, DATA, SpaceNode, 1, snode);
+ /* temporarily disable ghost curves when saving */
+ sipo->ghostCurves.first = sipo->ghostCurves.last = NULL;
- for (path = snode->treepath.first; path; path = path->next) {
- writestruct(wd, DATA, bNodeTreePath, 1, path);
- }
- }
- else if (sl->spacetype == SPACE_LOGIC) {
- writestruct(wd, DATA, SpaceLogic, 1, sl);
+ writestruct(wd, DATA, SpaceIpo, 1, sl);
+ if (sipo->ads) {
+ writestruct(wd, DATA, bDopeSheet, 1, sipo->ads);
}
- else if (sl->spacetype == SPACE_CONSOLE) {
- SpaceConsole *con = (SpaceConsole *)sl;
- ConsoleLine *cl;
-
- for (cl = con->history.first; cl; cl = cl->next) {
- /* 'len_alloc' is invalid on write, set from 'len' on read */
- writestruct(wd, DATA, ConsoleLine, 1, cl);
- writedata(wd, DATA, cl->len + 1, cl->line);
- }
- writestruct(wd, DATA, SpaceConsole, 1, sl);
+ /* reenable ghost curves */
+ sipo->ghostCurves = tmpGhosts;
+ }
+ else if (sl->spacetype == SPACE_BUTS) {
+ writestruct(wd, DATA, SpaceButs, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_FILE) {
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ writestruct(wd, DATA, SpaceFile, 1, sl);
+ if (sfile->params) {
+ writestruct(wd, DATA, FileSelectParams, 1, sfile->params);
}
- else if (sl->spacetype == SPACE_USERPREF) {
- writestruct(wd, DATA, SpaceUserPref, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_SEQ) {
+ writestruct(wd, DATA, SpaceSeq, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOops *so = (SpaceOops *)sl;
+ write_soops(wd, so);
+ }
+ else if (sl->spacetype == SPACE_IMAGE) {
+ writestruct(wd, DATA, SpaceImage, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_TEXT) {
+ writestruct(wd, DATA, SpaceText, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_SCRIPT) {
+ SpaceScript *scr = (SpaceScript *)sl;
+ scr->but_refs = NULL;
+ writestruct(wd, DATA, SpaceScript, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_ACTION) {
+ writestruct(wd, DATA, SpaceAction, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_NLA) {
+ SpaceNla *snla = (SpaceNla *)sl;
+
+ writestruct(wd, DATA, SpaceNla, 1, snla);
+ if (snla->ads) {
+ writestruct(wd, DATA, bDopeSheet, 1, snla->ads);
}
- else if (sl->spacetype == SPACE_CLIP) {
- writestruct(wd, DATA, SpaceClip, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_TIME) {
+ writestruct(wd, DATA, SpaceTime, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path;
+ writestruct(wd, DATA, SpaceNode, 1, snode);
+
+ for (path = snode->treepath.first; path; path = path->next) {
+ writestruct(wd, DATA, bNodeTreePath, 1, path);
}
- else if (sl->spacetype == SPACE_INFO) {
- writestruct(wd, DATA, SpaceInfo, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_LOGIC) {
+ writestruct(wd, DATA, SpaceLogic, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_CONSOLE) {
+ SpaceConsole *con = (SpaceConsole *)sl;
+ ConsoleLine *cl;
+
+ for (cl = con->history.first; cl; cl = cl->next) {
+ /* 'len_alloc' is invalid on write, set from 'len' on read */
+ writestruct(wd, DATA, ConsoleLine, 1, cl);
+ writedata(wd, DATA, cl->len + 1, cl->line);
}
+ writestruct(wd, DATA, SpaceConsole, 1, sl);
+
+ }
+ else if (sl->spacetype == SPACE_USERPREF) {
+ writestruct(wd, DATA, SpaceUserPref, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_CLIP) {
+ writestruct(wd, DATA, SpaceClip, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_INFO) {
+ writestruct(wd, DATA, SpaceInfo, 1, sl);
}
}
}
-
- mywrite_flush(wd);
}
static void write_bone(WriteData *wd, Bone *bone)
@@ -3115,121 +3053,101 @@ static void write_bone(WriteData *wd, Bone *bone)
}
}
-static void write_armatures(WriteData *wd, ListBase *idbase)
+static void write_armature(WriteData *wd, bArmature *arm)
{
- for (bArmature *arm = idbase->first; arm; arm = arm->id.next) {
- if (arm->id.us > 0 || wd->current) {
- writestruct(wd, ID_AR, bArmature, 1, arm);
- write_iddata(wd, &arm->id);
+ if (arm->id.us > 0 || wd->current) {
+ writestruct(wd, ID_AR, bArmature, 1, arm);
+ write_iddata(wd, &arm->id);
- if (arm->adt) {
- write_animdata(wd, arm->adt);
- }
+ if (arm->adt) {
+ write_animdata(wd, arm->adt);
+ }
- /* Direct data */
- for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
- write_bone(wd, bone);
- }
+ /* Direct data */
+ for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
+ write_bone(wd, bone);
}
}
-
- mywrite_flush(wd);
}
-static void write_texts(WriteData *wd, ListBase *idbase)
+static void write_text(WriteData *wd, Text *text)
{
- for (Text *text = idbase->first; text; text = text->id.next) {
- if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
- text->flags &= ~TXT_ISEXT;
- }
+ if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
+ text->flags &= ~TXT_ISEXT;
+ }
- /* write LibData */
- writestruct(wd, ID_TXT, Text, 1, text);
- write_iddata(wd, &text->id);
+ /* write LibData */
+ writestruct(wd, ID_TXT, Text, 1, text);
+ write_iddata(wd, &text->id);
- if (text->name) {
- writedata(wd, DATA, strlen(text->name) + 1, text->name);
- }
+ if (text->name) {
+ writedata(wd, DATA, strlen(text->name) + 1, text->name);
+ }
- if (!(text->flags & TXT_ISEXT)) {
- /* now write the text data, in two steps for optimization in the readfunction */
- for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
- writestruct(wd, DATA, TextLine, 1, tmp);
- }
+ if (!(text->flags & TXT_ISEXT)) {
+ /* now write the text data, in two steps for optimization in the readfunction */
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
+ writestruct(wd, DATA, TextLine, 1, tmp);
+ }
- for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
- writedata(wd, DATA, tmp->len + 1, tmp->line);
- }
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
+ writedata(wd, DATA, tmp->len + 1, tmp->line);
}
}
-
- mywrite_flush(wd);
}
-static void write_speakers(WriteData *wd, ListBase *idbase)
+static void write_speaker(WriteData *wd, Speaker *spk)
{
- for (Speaker *spk = idbase->first; spk; spk = spk->id.next) {
- if (spk->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_SPK, Speaker, 1, spk);
- write_iddata(wd, &spk->id);
-
- if (spk->adt) {
- write_animdata(wd, spk->adt);
- }
+ if (spk->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_SPK, Speaker, 1, spk);
+ write_iddata(wd, &spk->id);
+
+ if (spk->adt) {
+ write_animdata(wd, spk->adt);
}
}
}
-static void write_sounds(WriteData *wd, ListBase *idbase)
+static void write_sound(WriteData *wd, bSound *sound)
{
- for (bSound *sound = idbase->first; sound; sound = sound->id.next) {
- if (sound->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_SO, bSound, 1, sound);
- write_iddata(wd, &sound->id);
-
- if (sound->packedfile) {
- PackedFile *pf = sound->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
- }
+ if (sound->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_SO, bSound, 1, sound);
+ write_iddata(wd, &sound->id);
+
+ if (sound->packedfile) {
+ PackedFile *pf = sound->packedfile;
+ writestruct(wd, DATA, PackedFile, 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
}
}
-
- mywrite_flush(wd);
}
-static void write_groups(WriteData *wd, ListBase *idbase)
+static void write_group(WriteData *wd, Group *group)
{
- for (Group *group = idbase->first; group; group = group->id.next) {
- if (group->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_GR, Group, 1, group);
- write_iddata(wd, &group->id);
+ if (group->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_GR, Group, 1, group);
+ write_iddata(wd, &group->id);
- write_previews(wd, group->preview);
+ write_previews(wd, group->preview);
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- writestruct(wd, DATA, GroupObject, 1, go);
- }
+ for (GroupObject *go = group->gobject.first; go; go = go->next) {
+ writestruct(wd, DATA, GroupObject, 1, go);
}
}
-
- mywrite_flush(wd);
}
-static void write_nodetrees(WriteData *wd, ListBase *idbase)
+static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
- for (bNodeTree *ntree = idbase->first; ntree; ntree = ntree->id.next) {
- if (ntree->id.us > 0 || wd->current) {
- writestruct(wd, ID_NT, bNodeTree, 1, ntree);
- /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
- * be linked, etc., so we write actual id data here only, for 'real' ID trees. */
- write_iddata(wd, &ntree->id);
+ if (ntree->id.us > 0 || wd->current) {
+ writestruct(wd, ID_NT, bNodeTree, 1, ntree);
+ /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
+ * be linked, etc., so we write actual id data here only, for 'real' ID trees. */
+ write_iddata(wd, &ntree->id);
- write_nodetree(wd, ntree);
- }
+ write_nodetree_nolib(wd, ntree);
}
}
@@ -3303,47 +3221,41 @@ static void customnodes_free_deprecated_data(Main *mainvar)
}
#endif
-static void write_brushes(WriteData *wd, ListBase *idbase)
+static void write_brush(WriteData *wd, Brush *brush)
{
- for (Brush *brush = idbase->first; brush; brush = brush->id.next) {
- if (brush->id.us > 0 || wd->current) {
- writestruct(wd, ID_BR, Brush, 1, brush);
- write_iddata(wd, &brush->id);
+ if (brush->id.us > 0 || wd->current) {
+ writestruct(wd, ID_BR, Brush, 1, brush);
+ write_iddata(wd, &brush->id);
- if (brush->curve) {
- write_curvemapping(wd, brush->curve);
- }
- if (brush->gradient) {
- writestruct(wd, DATA, ColorBand, 1, brush->gradient);
- }
+ if (brush->curve) {
+ write_curvemapping(wd, brush->curve);
+ }
+ if (brush->gradient) {
+ writestruct(wd, DATA, ColorBand, 1, brush->gradient);
}
}
}
-static void write_palettes(WriteData *wd, ListBase *idbase)
+static void write_palette(WriteData *wd, Palette *palette)
{
- for (Palette *palette = idbase->first; palette; palette = palette->id.next) {
- if (palette->id.us > 0 || wd->current) {
- PaletteColor *color;
- writestruct(wd, ID_PAL, Palette, 1, palette);
- write_iddata(wd, &palette->id);
-
- for (color = palette->colors.first; color; color = color->next) {
- writestruct(wd, DATA, PaletteColor, 1, color);
- }
+ if (palette->id.us > 0 || wd->current) {
+ PaletteColor *color;
+ writestruct(wd, ID_PAL, Palette, 1, palette);
+ write_iddata(wd, &palette->id);
+
+ for (color = palette->colors.first; color; color = color->next) {
+ writestruct(wd, DATA, PaletteColor, 1, color);
}
}
}
-static void write_paintcurves(WriteData *wd, ListBase *idbase)
+static void write_paintcurve(WriteData *wd, PaintCurve *pc)
{
- for (PaintCurve *pc = idbase->first; pc; pc = pc->id.next) {
- if (pc->id.us > 0 || wd->current) {
- writestruct(wd, ID_PC, PaintCurve, 1, pc);
- write_iddata(wd, &pc->id);
+ if (pc->id.us > 0 || wd->current) {
+ writestruct(wd, ID_PC, PaintCurve, 1, pc);
+ write_iddata(wd, &pc->id);
- writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points);
- }
+ writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points);
}
}
@@ -3385,93 +3297,85 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction
}
}
-static void write_movieclips(WriteData *wd, ListBase *idbase)
+static void write_movieclip(WriteData *wd, MovieClip *clip)
{
- for (MovieClip *clip = idbase->first; clip; clip = clip->id.next) {
- if (clip->id.us > 0 || wd->current) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
+ if (clip->id.us > 0 || wd->current) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
- writestruct(wd, ID_MC, MovieClip, 1, clip);
- write_iddata(wd, &clip->id);
+ writestruct(wd, ID_MC, MovieClip, 1, clip);
+ write_iddata(wd, &clip->id);
- if (clip->adt) {
- write_animdata(wd, clip->adt);
- }
+ if (clip->adt) {
+ write_animdata(wd, clip->adt);
+ }
- write_movieTracks(wd, &tracking->tracks);
- write_moviePlaneTracks(wd, &tracking->plane_tracks);
- write_movieReconstruction(wd, &tracking->reconstruction);
+ write_movieTracks(wd, &tracking->tracks);
+ write_moviePlaneTracks(wd, &tracking->plane_tracks);
+ write_movieReconstruction(wd, &tracking->reconstruction);
- object = tracking->objects.first;
- while (object) {
- writestruct(wd, DATA, MovieTrackingObject, 1, object);
+ object = tracking->objects.first;
+ while (object) {
+ writestruct(wd, DATA, MovieTrackingObject, 1, object);
- write_movieTracks(wd, &object->tracks);
- write_moviePlaneTracks(wd, &object->plane_tracks);
- write_movieReconstruction(wd, &object->reconstruction);
+ write_movieTracks(wd, &object->tracks);
+ write_moviePlaneTracks(wd, &object->plane_tracks);
+ write_movieReconstruction(wd, &object->reconstruction);
- object = object->next;
- }
+ object = object->next;
}
}
-
- mywrite_flush(wd);
}
-static void write_masks(WriteData *wd, ListBase *idbase)
+static void write_mask(WriteData *wd, Mask *mask)
{
- for (Mask *mask = idbase->first; mask; mask = mask->id.next) {
- if (mask->id.us > 0 || wd->current) {
- MaskLayer *masklay;
+ if (mask->id.us > 0 || wd->current) {
+ MaskLayer *masklay;
- writestruct(wd, ID_MSK, Mask, 1, mask);
- write_iddata(wd, &mask->id);
+ writestruct(wd, ID_MSK, Mask, 1, mask);
+ write_iddata(wd, &mask->id);
- if (mask->adt) {
- write_animdata(wd, mask->adt);
- }
+ if (mask->adt) {
+ write_animdata(wd, mask->adt);
+ }
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- MaskLayerShape *masklay_shape;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ MaskLayerShape *masklay_shape;
- writestruct(wd, DATA, MaskLayer, 1, masklay);
+ writestruct(wd, DATA, MaskLayer, 1, masklay);
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
- void *points_deform = spline->points_deform;
- spline->points_deform = NULL;
+ void *points_deform = spline->points_deform;
+ spline->points_deform = NULL;
- writestruct(wd, DATA, MaskSpline, 1, spline);
- writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points);
+ writestruct(wd, DATA, MaskSpline, 1, spline);
+ writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points);
- spline->points_deform = points_deform;
+ spline->points_deform = points_deform;
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- if (point->tot_uw) {
- writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw);
- }
+ if (point->tot_uw) {
+ writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw);
}
}
+ }
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
- writestruct(wd, DATA, MaskLayerShape, 1, masklay_shape);
- writedata(wd, DATA,
- masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE,
- masklay_shape->data);
- }
+ for (masklay_shape = masklay->splines_shapes.first;
+ masklay_shape;
+ masklay_shape = masklay_shape->next)
+ {
+ writestruct(wd, DATA, MaskLayerShape, 1, masklay_shape);
+ writedata(wd, DATA,
+ masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE,
+ masklay_shape->data);
}
}
}
-
- mywrite_flush(wd);
}
static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers)
@@ -3728,43 +3632,39 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
}
}
-static void write_linestyles(WriteData *wd, ListBase *idbase)
+static void write_linestyle(WriteData *wd, FreestyleLineStyle *linestyle)
{
- for (FreestyleLineStyle *linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
- if (linestyle->id.us > 0 || wd->current) {
- writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
- write_iddata(wd, &linestyle->id);
+ if (linestyle->id.us > 0 || wd->current) {
+ writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
+ write_iddata(wd, &linestyle->id);
- if (linestyle->adt) {
- write_animdata(wd, linestyle->adt);
- }
+ if (linestyle->adt) {
+ write_animdata(wd, linestyle->adt);
+ }
- write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
- write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
- write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
- write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
- for (int a = 0; a < MAX_MTEX; a++) {
- if (linestyle->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
- }
- }
- if (linestyle->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree);
- write_nodetree(wd, linestyle->nodetree);
+ write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
+ write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
+ write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
+ write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (linestyle->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
}
}
+ if (linestyle->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree);
+ write_nodetree_nolib(wd, linestyle->nodetree);
+ }
}
}
-static void write_cachefiles(WriteData *wd, ListBase *idbase)
+static void write_cachefile(WriteData *wd, CacheFile *cache_file)
{
- for (CacheFile *cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) {
- if (cache_file->id.us > 0 || wd->current) {
- writestruct(wd, ID_CF, CacheFile, 1, cache_file);
+ if (cache_file->id.us > 0 || wd->current) {
+ writestruct(wd, ID_CF, CacheFile, 1, cache_file);
- if (cache_file->adt) {
- write_animdata(wd, cache_file->adt);
- }
+ if (cache_file->adt) {
+ write_animdata(wd, cache_file->adt);
}
}
}
@@ -3931,38 +3831,131 @@ static bool write_file_handle(
* avoid thumbnail detecting changes because of this. */
mywrite_flush(wd);
- write_windowmanagers(wd, &mainvar->wm);
- write_screens(wd, &mainvar->screen);
- write_movieclips(wd, &mainvar->movieclip);
- write_masks(wd, &mainvar->mask);
- write_scenes(wd, &mainvar->scene);
- write_curves(wd, &mainvar->curve);
- write_mballs(wd, &mainvar->mball);
- write_images(wd, &mainvar->image);
- write_cameras(wd, &mainvar->camera);
- write_lamps(wd, &mainvar->lamp);
- write_lattices(wd, &mainvar->latt);
- write_vfonts(wd, &mainvar->vfont);
- write_keys(wd, &mainvar->key);
- write_worlds(wd, &mainvar->world);
- write_texts(wd, &mainvar->text);
- write_speakers(wd, &mainvar->speaker);
- write_sounds(wd, &mainvar->sound);
- write_groups(wd, &mainvar->group);
- write_armatures(wd, &mainvar->armature);
- write_actions(wd, &mainvar->action);
- write_objects(wd, &mainvar->object);
- write_materials(wd, &mainvar->mat);
- write_textures(wd, &mainvar->tex);
- write_meshes(wd, &mainvar->mesh);
- write_particlesettings(wd, &mainvar->particle);
- write_nodetrees(wd, &mainvar->nodetree);
- write_brushes(wd, &mainvar->brush);
- write_palettes(wd, &mainvar->palettes);
- write_paintcurves(wd, &mainvar->paintcurves);
- write_gpencils(wd, &mainvar->gpencil);
- write_linestyles(wd, &mainvar->linestyle);
- write_cachefiles(wd, &mainvar->cachefiles);
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a = set_listbasepointers(mainvar, lbarray);
+ while (a--) {
+ ID *id = lbarray[a]->first;
+
+ if (id && GS(id->name) == ID_LI) {
+ continue; /* Libraries are handled separately below. */
+ }
+
+ for (; id; id = id->next) {
+ switch ((ID_Type)GS(id->name)) {
+ case ID_WM:
+ write_windowmanager(wd, (wmWindowManager *)id);
+ break;
+ case ID_SCR:
+ write_screen(wd, (bScreen *)id);
+ break;
+ case ID_MC:
+ write_movieclip(wd, (MovieClip *)id);
+ break;
+ case ID_MSK:
+ write_mask(wd, (Mask *)id);
+ break;
+ case ID_SCE:
+ write_scene(wd, (Scene *)id);
+ break;
+ case ID_CU:
+ write_curve(wd, (Curve *)id);
+ break;
+ case ID_MB:
+ write_mball(wd, (MetaBall *)id);
+ break;
+ case ID_IM:
+ write_image(wd, (Image *)id);
+ break;
+ case ID_CA:
+ write_camera(wd, (Camera *)id);
+ break;
+ case ID_LA:
+ write_lamp(wd, (Lamp *)id);
+ break;
+ case ID_LT:
+ write_lattice(wd, (Lattice *)id);
+ break;
+ case ID_VF:
+ write_vfont(wd, (VFont *)id);
+ break;
+ case ID_KE:
+ write_key(wd, (Key *)id);
+ break;
+ case ID_WO:
+ write_world(wd, (World *)id);
+ break;
+ case ID_TXT:
+ write_text(wd, (Text *)id);
+ break;
+ case ID_SPK:
+ write_speaker(wd, (Speaker *)id);
+ break;
+ case ID_SO:
+ write_sound(wd, (bSound *)id);
+ break;
+ case ID_GR:
+ write_group(wd, (Group *)id);
+ break;
+ case ID_AR:
+ write_armature(wd, (bArmature *)id);
+ break;
+ case ID_AC:
+ write_action(wd, (bAction *)id);
+ break;
+ case ID_OB:
+ write_object(wd, (Object *)id);
+ break;
+ case ID_MA:
+ write_material(wd, (Material *)id);
+ break;
+ case ID_TE:
+ write_texture(wd, (Tex *)id);
+ break;
+ case ID_ME:
+ write_mesh(wd, (Mesh *)id);
+ break;
+ case ID_PA:
+ write_particlesettings(wd, (ParticleSettings *)id);
+ break;
+ case ID_NT:
+ write_nodetree(wd, (bNodeTree *)id);
+ break;
+ case ID_BR:
+ write_brush(wd, (Brush *)id);
+ break;
+ case ID_PAL:
+ write_palette(wd, (Palette *)id);
+ break;
+ case ID_PC:
+ write_paintcurve(wd, (PaintCurve *)id);
+ break;
+ case ID_GD:
+ write_gpencil(wd, (bGPdata *)id);
+ break;
+ case ID_LS:
+ write_linestyle(wd, (FreestyleLineStyle *)id);
+ break;
+ case ID_CF:
+ write_cachefile(wd, (CacheFile *)id);
+ break;
+ case ID_LI:
+ /* Do nothing, handled below - and should never be reached. */
+ BLI_assert(0);
+ break;
+ case ID_IP:
+ /* Do nothing, deprecated. */
+ break;
+ default:
+ /* Should never be reached. */
+ BLI_assert(0);
+ break;
+ }
+ }
+
+ mywrite_flush(wd);
+ }
+
+ /* Special handling, operating over split Mains... */
write_libraries(wd, mainvar->next);
/* So changes above don't cause a 'DNA1' to be detected as changed on undo. */
diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt
index a3e85344027..c0dce5b4f0d 100644
--- a/source/blender/blentranslation/CMakeLists.txt
+++ b/source/blender/blentranslation/CMakeLists.txt
@@ -60,3 +60,5 @@ if(WIN32)
endif()
blender_add_lib(bf_blentranslation "${SRC}" "${INC}" "${INC_SYS}")
+
+add_subdirectory(msgfmt)
diff --git a/source/blender/blentranslation/msgfmt/CMakeLists.txt b/source/blender/blentranslation/msgfmt/CMakeLists.txt
new file mode 100644
index 00000000000..d2cb6f5a03b
--- /dev/null
+++ b/source/blender/blentranslation/msgfmt/CMakeLists.txt
@@ -0,0 +1,50 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2017, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Bastien Montagne.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+# -----------------------------------------------------------------------------
+# Build msgfmt executable
+
+blender_include_dirs(
+ ../../../../intern/guardedalloc
+ ../../blenlib
+)
+
+set(SRC
+ msgfmt.c
+)
+
+add_cc_flags_custom_test(msgfmt)
+
+add_executable(msgfmt ${SRC})
+
+target_link_libraries(msgfmt bf_blenlib)
+target_link_libraries(msgfmt bf_intern_guardedalloc)
+
+if(WIN32)
+ target_link_libraries(msgfmt bf_intern_utfconv)
+endif()
+
+target_link_libraries(msgfmt ${ZLIB_LIBRARIES})
+target_link_libraries(msgfmt ${PLATFORM_LINKLIBS})
diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c
new file mode 100644
index 00000000000..487d9fee7b4
--- /dev/null
+++ b/source/blender/blentranslation/msgfmt/msgfmt.c
@@ -0,0 +1,464 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/*
+ * Based on C++ version by Sergey Sharybin <sergey.vfx@gmail.com>.
+ * Based on Python script msgfmt.py from Python source code tree, which was written by
+ * Martin v. Löwis <loewis@informatik.hu-berlin.de>
+ *
+ * Generate binary message catalog from textual translation description.
+ *
+ * This program converts a textual Uniforum-style message catalog (.po file) into a binary GNU catalog (.mo file).
+ * This is essentially the same function as the GNU msgfmt program, however, it is a simpler implementation.
+ *
+ * Usage: msgfmt input.po output.po
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_dynstr.h"
+#include "BLI_fileops.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+
+#include "MEM_guardedalloc.h"
+
+
+/* Stupid stub necessary because some BLI files includes winstuff.h, which uses G a bit... */
+#ifdef WIN32
+ typedef struct Global {
+ void *dummy;
+ } Global;
+
+ Global G;
+#endif
+
+
+/* We cannot use NULL char until ultimate step, would give nightmare to our C string processing...
+ * Using one of the UTF-8 invalid bytes (as per our BLI string_utf8.c) */
+#define NULLSEP_STR "\xff"
+#define NULLSEP_CHR '\xff'
+
+typedef enum {
+ SECTION_NONE = 0,
+ SECTION_CTX = 1,
+ SECTION_ID = 2,
+ SECTION_STR = 3,
+} eSectionType;
+
+typedef struct Message {
+ DynStr *ctxt;
+ DynStr *id;
+ DynStr *str;
+
+ bool is_fuzzy;
+} Message;
+
+static char *trim(char *str)
+{
+ const size_t len = strlen(str);
+ size_t i;
+
+ if (len == 0) {
+ return str;
+ }
+
+ for (i = 0; i < len && ELEM(str[0], ' ', '\t', '\n'); str++, i++);
+
+ char *end = &str[len - 1 - i];
+ for (i = len; i > 0 && ELEM(end[0], ' ', '\t', '\n'); end--, i--);
+ end[1] = '\0';
+
+ return str;
+}
+
+static char *unescape(char *str)
+{
+ char *curr, *next;
+ for (curr = next = str; next[0] != '\0'; curr++, next++) {
+ if (next[0] == '\\') {
+ switch (next[1]) {
+ case '\0':
+ /* Get rid of trailing escape char... */
+ curr--;
+ break;
+ case '\\':
+ *curr = '\\';
+ next++;
+ break;
+ case 'n':
+ *curr = '\n';
+ next++;
+ break;
+ case 't':
+ *curr = '\t';
+ next++;
+ break;
+ default:
+ /* Get rid of useless escape char. */
+ next++;
+ *curr = *next;
+ }
+ }
+ else if (curr != next) {
+ *curr = *next;
+ }
+ }
+ *curr = '\0';
+
+ if (str[0] == '"' && *(curr - 1) == '"') {
+ *(curr - 1) = '\0';
+ return str + 1;
+ }
+ return str;
+}
+
+static int qsort_str_cmp(const void *a, const void *b)
+{
+ return strcmp(*(const char **)a, *(const char **)b);
+}
+
+static char **get_keys_sorted(GHash *messages, const uint32_t num_keys)
+{
+ GHashIterator iter;
+
+ char **keys = MEM_mallocN(sizeof(*keys) * num_keys, __func__);
+ char **k = keys;
+
+ GHASH_ITER(iter, messages) {
+ *k = BLI_ghashIterator_getKey(&iter);
+ k++;
+ }
+
+ qsort(keys, num_keys, sizeof(*keys), qsort_str_cmp);
+
+ return keys;
+}
+
+BLI_INLINE size_t uint32_to_bytes(const int value, char *bytes) {
+ size_t i;
+ for (i = 0; i < sizeof(value); i++) {
+ bytes[i] = (char) ((value >> ((int)i * 8)) & 0xff);
+ }
+ return i;
+}
+
+BLI_INLINE size_t msg_to_bytes(char *msg, char *bytes, uint32_t size) {
+ /* Note that we also perform replacing of our NULLSEP placeholder by real NULL char... */
+ size_t i;
+ for (i = 0; i < size; i++, msg++, bytes++) {
+ *bytes = (*msg == NULLSEP_CHR) ? '\0' : *msg;
+ }
+ return i;
+}
+
+typedef struct Offset {
+ uint32_t key_offset, key_len, val_offset, val_len;
+} Offset;
+
+/* Return the generated binary output. */
+static char *generate(GHash *messages, size_t *r_output_size) {
+ const uint32_t num_keys = BLI_ghash_size(messages);
+
+ /* Get list of sorted keys. */
+ char **keys = get_keys_sorted(messages, num_keys);
+ char **vals = MEM_mallocN(sizeof(*vals) * num_keys, __func__);
+ uint32_t tot_keys_len = 0;
+ uint32_t tot_vals_len = 0;
+
+ Offset *offsets = MEM_mallocN(sizeof(*offsets) * num_keys, __func__);
+
+ for (int i = 0; i < num_keys; i++) {
+ Offset *off = &offsets[i];
+
+ vals[i] = BLI_ghash_lookup(messages, keys[i]);
+
+ /* For each string, we need size and file offset.
+ * Each string is NULL terminated; the NULL does not count into the size. */
+ off->key_offset = tot_keys_len;
+ off->key_len = (uint32_t)strlen(keys[i]);
+ tot_keys_len += off->key_len + 1;
+
+ off->val_offset = tot_vals_len;
+ off->val_len = (uint32_t)strlen(vals[i]);
+ tot_vals_len += off->val_len + 1;
+ }
+
+ /* The header is 7 32-bit unsigned integers. then comes the keys index table, then the values index table. */
+ const uint32_t idx_keystart = 7 * 4;
+ const uint32_t idx_valstart = idx_keystart + 8 * num_keys;
+ /* We don't use hash tables, so the keys start right after the index tables. */
+ const uint32_t keystart = idx_valstart + 8 * num_keys;
+ /* and the values start after the keys */
+ const uint32_t valstart = keystart + tot_keys_len;
+
+ /* Final buffer representing the binary MO file. */
+ *r_output_size = valstart + tot_vals_len;
+ char *output = MEM_mallocN(*r_output_size, __func__);
+ char *h = output;
+ char *ik = output + idx_keystart;
+ char *iv = output + idx_valstart;
+ char *k = output + keystart;
+ char *v = output + valstart;
+
+ h += uint32_to_bytes(0x950412de, h); /* Magic */
+ h += uint32_to_bytes(0x0, h); /* Version */
+ h += uint32_to_bytes(num_keys, h); /* Number of entries */
+ h += uint32_to_bytes(idx_keystart, h); /* Start of key index */
+ h += uint32_to_bytes(idx_valstart, h); /* Start of value index */
+ h += uint32_to_bytes(0, h); /* Size of hash table */
+ h += uint32_to_bytes(0, h); /* Offset of hash table */
+
+ BLI_assert(h == ik);
+
+ for (int i = 0; i < num_keys; i++) {
+ Offset *off = &offsets[i];
+
+ /* The index table first has the list of keys, then the list of values.
+ * Each entry has first the size of the string, then the file offset. */
+ ik += uint32_to_bytes(off->key_len, ik);
+ ik += uint32_to_bytes(off->key_offset + keystart, ik);
+ iv += uint32_to_bytes(off->val_len, iv);
+ iv += uint32_to_bytes(off->val_offset + valstart, iv);
+
+ k += msg_to_bytes(keys[i], k, off->key_len + 1);
+ v += msg_to_bytes(vals[i], v, off->val_len + 1);
+ }
+
+ BLI_assert(ik == output + idx_valstart);
+ BLI_assert(iv == output + keystart);
+ BLI_assert(k == output + valstart);
+
+ MEM_freeN(keys);
+ MEM_freeN(vals);
+ MEM_freeN(offsets);
+
+ return output;
+}
+
+/* Add a non-fuzzy translation to the dictionary. */
+static void add(GHash *messages, MemArena *memarena, const Message *msg)
+{
+ const size_t msgctxt_len = (size_t)BLI_dynstr_get_len(msg->ctxt);
+ const size_t msgid_len = (size_t)BLI_dynstr_get_len(msg->id);
+ const size_t msgstr_len = (size_t)BLI_dynstr_get_len(msg->str);
+ const size_t msgkey_len = msgid_len + ((msgctxt_len == 0) ? 0 : msgctxt_len + 1);
+
+ if (!msg->is_fuzzy && msgstr_len != 0) {
+ char *msgkey = BLI_memarena_alloc(memarena, sizeof(*msgkey) * (msgkey_len + 1));
+ char *msgstr = BLI_memarena_alloc(memarena, sizeof(*msgstr) * (msgstr_len + 1));
+
+ if (msgctxt_len != 0) {
+ BLI_dynstr_get_cstring_ex(msg->ctxt, msgkey);
+ msgkey[msgctxt_len] = '\x04'; /* Context/msgid separator */
+ BLI_dynstr_get_cstring_ex(msg->id, &msgkey[msgctxt_len + 1]);
+ }
+ else {
+ BLI_dynstr_get_cstring_ex(msg->id, msgkey);
+ }
+
+ BLI_dynstr_get_cstring_ex(msg->str, msgstr);
+
+ BLI_ghash_insert(messages, msgkey, msgstr);
+ }
+}
+
+
+static void clear(Message *msg)
+{
+ BLI_dynstr_clear(msg->ctxt);
+ BLI_dynstr_clear(msg->id);
+ BLI_dynstr_clear(msg->str);
+ msg->is_fuzzy = false;
+}
+
+static int make(const char *input_file_name, const char *output_file_name)
+{
+ GHash *messages = BLI_ghash_new(BLI_ghashutil_strhash_p_murmur, BLI_ghashutil_strcmp, __func__);
+ MemArena *msgs_memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
+ const char *msgctxt_kw = "msgctxt";
+ const char *msgid_kw = "msgid";
+ const char *msgid_plural_kw = "msgid_plural";
+ const char *msgstr_kw = "msgstr";
+ const size_t msgctxt_len = strlen(msgctxt_kw);
+ const size_t msgid_len = strlen(msgid_kw);
+ const size_t msgid_plural_len = strlen(msgid_plural_kw);
+ const size_t msgstr_len = strlen(msgstr_kw);
+
+ /* Note: For now, we assume file encoding is always utf-8. */
+
+ eSectionType section = SECTION_NONE;
+ bool is_plural = false;
+
+ Message msg = {
+ .ctxt = BLI_dynstr_new_memarena(),
+ .id = BLI_dynstr_new_memarena(),
+ .str = BLI_dynstr_new_memarena(),
+ .is_fuzzy = false,
+ };
+
+ LinkNode *input_file_lines = BLI_file_read_as_lines(input_file_name);
+ LinkNode *ifl = input_file_lines;
+
+ /* Parse the catalog. */
+ for (int lno = 1; ifl; ifl = ifl->next, lno++) {
+ char *l = ifl->link;
+ const bool is_comment = (l[0] == '#');
+ /* If we get a comment line after a msgstr, this is a new entry. */
+ if (is_comment) {
+ if (section == SECTION_STR) {
+ add(messages, msgs_memarena, &msg);
+ clear(&msg);
+ section = SECTION_NONE;
+ }
+ /* Record a fuzzy mark. */
+ if (l[1] == ',' && strstr(l, "fuzzy") != NULL) {
+ msg.is_fuzzy = true;
+ }
+ /* Skip comments */
+ continue;
+ }
+ if (strstr(l, msgctxt_kw) == l) {
+ if (section == SECTION_STR) {
+ /* New message, output previous section. */
+ add(messages, msgs_memarena, &msg);
+ }
+ if (!ELEM(section, SECTION_NONE, SECTION_STR)) {
+ printf("msgctxt not at start of new message on %s:%d\n", input_file_name, lno);
+ return EXIT_FAILURE;
+ }
+ section = SECTION_CTX;
+ l = l + msgctxt_len;
+ clear(&msg);
+ }
+ else if (strstr(l, msgid_plural_kw) == l) {
+ /* This is a message with plural forms. */
+ if (section != SECTION_ID) {
+ printf("msgid_plural not preceeded by msgid on %s:%d\n", input_file_name, lno);
+ return EXIT_FAILURE;
+ }
+ l = l + msgid_plural_len;
+ BLI_dynstr_append(msg.id, NULLSEP_STR); /* separator of singular and plural */
+ is_plural = true;
+ }
+ else if (strstr(l, msgid_kw) == l) {
+ if (section == SECTION_STR) {
+ add(messages, msgs_memarena, &msg);
+ }
+ if (section != SECTION_CTX) {
+ clear(&msg);
+ }
+ section = SECTION_ID;
+ l = l + msgid_len;
+ is_plural = false;
+ }
+ else if (strstr(l, msgstr_kw) == l) {
+ l = l + msgstr_len;
+ // Now we are in a msgstr section
+ section = SECTION_STR;
+ if (l[0] == '[') {
+ if (!is_plural) {
+ printf("plural without msgid_plural on %s:%d\n", input_file_name, lno);
+ return EXIT_FAILURE;
+ }
+ if ((l = strchr(l, ']')) == NULL) {
+ printf("Syntax error on %s:%d\n", input_file_name, lno);
+ return EXIT_FAILURE;
+ }
+ if (BLI_dynstr_get_len(msg.str) != 0) {
+ BLI_dynstr_append(msg.str, NULLSEP_STR); /* Separator of the various plural forms. */
+ }
+ }
+ else {
+ if (is_plural) {
+ printf("indexed msgstr required for plural on %s:%d\n", input_file_name, lno);
+ return EXIT_FAILURE;
+ }
+ }
+ }
+ /* Skip empty lines. */
+ l = trim(l);
+ if (l[0] == '\0') {
+ if (section == SECTION_STR) {
+ add(messages, msgs_memarena, &msg);
+ clear(&msg);
+ }
+ section = SECTION_NONE;
+ continue;
+ }
+ l = unescape(l);
+ if (section == SECTION_CTX) {
+ BLI_dynstr_append(msg.ctxt, l);
+ }
+ else if (section == SECTION_ID) {
+ BLI_dynstr_append(msg.id, l);
+ }
+ else if (section == SECTION_STR) {
+ BLI_dynstr_append(msg.str, l);
+ }
+ else {
+ printf("Syntax error on %s:%d\n", input_file_name, lno);
+ return EXIT_FAILURE;
+ }
+ }
+ /* Add last entry */
+ if (section == SECTION_STR) {
+ add(messages, msgs_memarena, &msg);
+ }
+
+ BLI_dynstr_free(msg.ctxt);
+ BLI_dynstr_free(msg.id);
+ BLI_dynstr_free(msg.str);
+ BLI_file_free_lines(input_file_lines);
+
+ /* Compute output */
+ size_t output_size;
+ char *output = generate(messages, &output_size);
+
+ FILE *fp = BLI_fopen(output_file_name, "wb");
+ fwrite(output, 1, output_size, fp);
+ fclose(fp);
+
+ MEM_freeN(output);
+ BLI_ghash_free(messages, NULL, NULL);
+ BLI_memarena_free(msgs_memarena);
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv) {
+ if (argc != 3) {
+ printf("Usage: %s <input.po> <output.mo>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ const char *input_file = argv[1];
+ const char *output_file = argv[2];
+
+ return make(input_file, output_file);
+}
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index f29d280d071..b84a3d5e559 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -192,9 +192,10 @@
*
* These conventions should be used throughout the bmesh module.
*
- * - ``BM_***()`` - High level BMesh API function for use anywhere.
- * - ``bmesh_***()`` - Low level API function.
+ * - ``bmesh_kernel_*()`` - Low level API, for primitive functions that others are built ontop of.
+ * - ``bmesh_***()`` - Low level API function.
* - ``bm_***()`` - 'static' functions, not apart of the API at all, but use prefix since they operate on BMesh data.
+ * - ``BM_***()`` - High level BMesh API function for use anywhere.
* - ``BMO_***()`` - High level operator API function for use anywhere.
* - ``bmo_***()`` - Low level / internal operator API functions.
* - ``_bm_***()`` - Functions which are called via macros only.
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 104df625ee6..64a5cad812a 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -225,7 +225,7 @@ typedef struct BMesh {
/* operator api stuff (must be all NULL or all alloc'd) */
struct BLI_mempool *vtoolflagpool, *etoolflagpool, *ftoolflagpool;
- unsigned int use_toolflags : 1;
+ uint use_toolflags : 1;
int toolflag_index;
struct BMOperator *currentop;
@@ -382,7 +382,7 @@ typedef bool (*BMLoopFilterFunc)(const BMLoop *, void *user_data);
(assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
#define BM_ELEM_CD_GET_FLOAT_AS_UCHAR(ele, offset) \
- (assert(offset != -1), (unsigned char)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f))
+ (assert(offset != -1), (uchar)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f))
/*forward declarations*/
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.c b/source/blender/bmesh/intern/bmesh_callback_generic.c
index 913255bfb33..e9304e8536f 100644
--- a/source/blender/bmesh/intern/bmesh_callback_generic.c
+++ b/source/blender/bmesh/intern/bmesh_callback_generic.c
@@ -32,7 +32,7 @@
bool BM_elem_cb_check_hflag_ex(BMElem *ele, void *user_data)
{
- const unsigned int hflag_pair = GET_INT_FROM_POINTER(user_data);
+ const uint hflag_pair = GET_INT_FROM_POINTER(user_data);
const char hflag_p = (hflag_pair & 0xff);
const char hflag_n = (hflag_pair >> 8);
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index e46a31cb2e9..f8ecbe1756b 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -154,7 +154,7 @@ void BM_face_copy_shared(
if (l_other && l_other != l_iter) {
BMLoop *l_src[2];
BMLoop *l_dst[2] = {l_iter, l_iter->next};
- unsigned int j;
+ uint j;
if (l_other->v == l_iter->v) {
l_src[0] = l_other;
@@ -311,7 +311,7 @@ BMFace *BM_face_create_ngon_verts(
const bool calc_winding, const bool create_edges)
{
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
- unsigned int winding[2] = {0, 0};
+ uint winding[2] = {0, 0};
int i, i_prev = len - 1;
BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 68cacf55efe..4fe14fdf5c9 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -1021,7 +1021,7 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l)
* \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp,
* (use when flipping normals, disable when mirroring, eg: symmetrize).
*/
-void bmesh_loop_reverse(
+void bmesh_kernel_loop_reverse(
BMesh *bm, BMFace *f,
const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
{
@@ -1438,7 +1438,7 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
*
* \return A BMFace pointer
*/
-BMFace *bmesh_sfme(
+BMFace *bmesh_kernel_split_face_make_edge(
BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
BMLoop **r_l,
#ifdef USE_BMESH_HOLES
@@ -1584,7 +1584,7 @@ BMFace *bmesh_sfme(
*
* \return The newly created BMVert pointer.
*/
-BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
+BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
{
BMLoop *l_next;
BMEdge *e_new;
@@ -1766,7 +1766,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
* faces with just 2 edges. It is up to the caller to decide what to do with
* these faces.
*/
-BMEdge *bmesh_jekv(
+BMEdge *bmesh_kernel_join_edge_kill_vert(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_double,
const bool kill_degenerate_faces)
@@ -1920,7 +1920,7 @@ BMEdge *bmesh_jekv(
*
* Collapse an edge, merging surrounding data.
*
- * Unlike #BM_vert_collapse_edge & #bmesh_jekv which only handle 2 valence verts,
+ * Unlike #BM_vert_collapse_edge & #bmesh_kernel_join_edge_kill_vert which only handle 2 valence verts,
* this can handle any number of connected edges/faces.
*
* <pre>
@@ -1932,7 +1932,7 @@ BMEdge *bmesh_jekv(
* +-+-+-+ +-+-+-+
* </pre>
*/
-BMVert *bmesh_jvke(
+BMVert *bmesh_kernel_join_vert_kill_edge(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_double,
const bool kill_degenerate_faces)
@@ -2035,7 +2035,7 @@ BMVert *bmesh_jvke(
* In the example A, faces \a f1 and \a f2 are joined by a single edge,
* and the euler can safely be used.
* In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error.
- * The caller in this case should call #bmesh_jekv on the extra edges
+ * The caller in this case should call #bmesh_kernel_join_edge_kill_vert on the extra edges
* before attempting to fuse \a f1 and \a f2.
*
* \note The order of arguments decides whether or not certain per-face attributes are present
@@ -2044,7 +2044,7 @@ BMVert *bmesh_jvke(
*
* \return A BMFace pointer
*/
-BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
{
BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL;
int newlen = 0, i, f1len = 0, f2len = 0;
@@ -2249,7 +2249,7 @@ bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
}
-/** \name BM_vert_separate, bmesh_vert_separate and friends
+/** \name BM_vert_separate, bmesh_kernel_vert_separate and friends
* \{ */
/* BM_edge_face_count(e) >= 1 */
@@ -2269,7 +2269,7 @@ BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e)
*
* \return Success
*/
-void bmesh_vert_separate(
+void bmesh_kernel_vert_separate(
BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
const bool copy_select)
{
@@ -2385,7 +2385,7 @@ void bmesh_vert_separate(
*
* Takes a list of edges, which have been split from their original.
*
- * Any edges which failed to split off in #bmesh_vert_separate will be merged back into the original edge.
+ * Any edges which failed to split off in #bmesh_kernel_vert_separate will be merged back into the original edge.
*
* \param edges_separate
* A list-of-lists, each list is from a single original edge (the first edge is the original),
@@ -2398,27 +2398,32 @@ void bmesh_vert_separate(
* \note this function looks like it could become slow,
* but in common cases its only going to iterate a few times.
*/
-static void bmesh_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate)
+static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate)
{
do {
LinkNode *n_orig = edges_separate->link;
do {
- BMEdge *e_orig = n_orig->link;
+ LinkNode *n_prev = n_orig;
LinkNode *n_step = n_orig->next;
+ BMEdge *e_orig = n_orig->link;
do {
BMEdge *e = n_step->link;
BLI_assert(e != e_orig);
- if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2)) {
- BM_edge_splice(bm, e_orig, e);
+ if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2) &&
+ BM_edge_splice(bm, e_orig, e))
+ {
+ /* don't visit again */
+ n_prev->next = n_step->next;
}
- } while ((n_step = n_step->next));
+ } while ((n_prev = n_step),
+ (n_step = n_step->next));
} while ((n_orig = n_orig->next) && n_orig->next);
} while ((edges_separate = edges_separate->next));
}
/**
- * High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate
+ * High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate
*/
void BM_vert_separate(
BMesh *bm, BMVert *v,
@@ -2435,7 +2440,7 @@ void BM_vert_separate(
LinkNode *edges_orig = NULL;
do {
BMLoop *l_sep = e->l;
- bmesh_edge_separate(bm, e, l_sep, copy_select);
+ bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
BLI_assert(e != l_sep->e);
} while (bm_edge_supports_separate(e));
@@ -2444,10 +2449,10 @@ void BM_vert_separate(
}
}
- bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+ bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
if (edges_separate) {
- bmesh_vert_separate__cleanup(bm, edges_separate);
+ bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
}
}
@@ -2472,7 +2477,7 @@ void BM_vert_separate_hflag(
LinkNode *edges_orig = NULL;
do {
BMLoop *l_sep = e->l;
- bmesh_edge_separate(bm, e, l_sep, copy_select);
+ bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
/* trick to avoid looping over separated edges */
if (edges_separate == NULL && edges_orig == NULL) {
e_first = l_sep->e;
@@ -2486,10 +2491,10 @@ void BM_vert_separate_hflag(
}
} while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
- bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+ bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
if (edges_separate) {
- bmesh_vert_separate__cleanup(bm, edges_separate);
+ bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
}
}
@@ -2574,7 +2579,7 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
* \note Does nothing if \a l_sep is already the only loop in the
* edge radial.
*/
-void bmesh_edge_separate(
+void bmesh_kernel_edge_separate(
BMesh *bm, BMEdge *e, BMLoop *l_sep,
const bool copy_select)
{
@@ -2620,7 +2625,7 @@ void bmesh_edge_separate(
*
* \note Will be a no-op and return original vertex if only two edges at that vertex.
*/
-BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
+BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep)
{
BMVert *v_new = NULL;
BMVert *v_sep = l_sep->v;
@@ -2630,10 +2635,12 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
/* peel the face from the edge radials on both sides of the
* loop vert, disconnecting the face from its fan */
- if (!BM_edge_is_boundary(l_sep->e))
- bmesh_edge_separate(bm, l_sep->e, l_sep, false);
- if (!BM_edge_is_boundary(l_sep->prev->e))
- bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
+ if (!BM_edge_is_boundary(l_sep->e)) {
+ bmesh_kernel_edge_separate(bm, l_sep->e, l_sep, false);
+ }
+ if (!BM_edge_is_boundary(l_sep->prev->e)) {
+ bmesh_kernel_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
+ }
/* do inline, below */
#if 0
@@ -2681,13 +2688,13 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
}
/**
- * A version of #bmesh_urmv_loop that disconnects multiple loops at once.
+ * A version of #bmesh_kernel_unglue_region_make_vert that disconnects multiple loops at once.
* The loops must all share the same vertex, can be in any order
* and are all moved to use a single new vertex - which is returned.
*
* This function handles the details of finding fans boundaries.
*/
-BMVert *bmesh_urmv_loop_multi(
+BMVert *bmesh_kernel_unglue_region_make_vert_multi(
BMesh *bm, BMLoop **larr, int larr_len)
{
BMVert *v_sep = larr[0]->v;
@@ -2756,7 +2763,8 @@ BMVert *bmesh_urmv_loop_multi(
}
STACK_PUSH(edges, e_iter);
- } else {
+ }
+ else {
/* at least one edge attached isn't connected to our loops */
is_mixed_edge_any = true;
}
@@ -2870,9 +2878,9 @@ static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_
/**
* This function assumes l_sep is apart of a larger fan which has already been
- * isolated by calling bmesh_edge_separate to segregate it radially.
+ * isolated by calling #bmesh_kernel_edge_separate to segregate it radially.
*/
-BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep)
+BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep)
{
BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP);
/* passing either 'l_sep->e', 'l_sep->prev->e' will work */
@@ -2881,20 +2889,6 @@ BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep)
return v_new;
}
-
-/**
- * \brief Unglue Region Make Vert (URMV)
- *
- * Disconnects f_sep from the vertex fan at \a v_sep
- *
- * \return The newly created BMVert
- */
-BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep)
-{
- BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep);
- return bmesh_urmv_loop(bm, l);
-}
-
/**
* Avoid calling this where possible,
* low level function so both face pointers remain intact but point to swapped data.
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index f72e9d7b198..fb6b66809f3 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -64,21 +64,16 @@ void BM_face_kill(BMesh *bm, BMFace *f);
void BM_edge_kill(BMesh *bm, BMEdge *e);
void BM_vert_kill(BMesh *bm, BMVert *v);
-void bmesh_edge_separate(
- BMesh *bm, BMEdge *e, BMLoop *l_sep,
- const bool copy_select);
bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src);
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src);
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
-void bmesh_vert_separate(
- BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- const bool copy_select);
-
-void bmesh_loop_reverse(
+void bmesh_kernel_loop_reverse(
BMesh *bm, BMFace *f,
const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip);
+void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
+
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del);
void BM_vert_separate(
BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select,
@@ -90,34 +85,43 @@ void BM_vert_separate_wire_hflag(
BMesh *bm, BMVert *v_dst, BMVert *v_src,
const char hflag);
-/* EULER API - For modifying structure */
-BMFace *bmesh_sfme(
+/**
+ * BMesh Kernel: For modifying structure.
+ *
+ * Names are on the verbose side but these are only for low-level access.
+ */
+void bmesh_kernel_vert_separate(
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+ const bool copy_select);
+void bmesh_kernel_edge_separate(
+ BMesh *bm, BMEdge *e, BMLoop *l_sep,
+ const bool copy_select);
+
+BMFace *bmesh_kernel_split_face_make_edge(
BMesh *bm, BMFace *f,
BMLoop *l1, BMLoop *l2,
BMLoop **r_l,
#ifdef USE_BMESH_HOLES
- ListBase *holes,
+ ListBase *holes,
#endif
- BMEdge *example,
- const bool no_double
- );
+ BMEdge *example,
+ const bool no_double
+ );
-BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
-BMEdge *bmesh_jekv(
+BMVert *bmesh_kernel_split_edge_make_vert(
+ BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
+BMEdge *bmesh_kernel_join_edge_kill_vert(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_splice,
const bool kill_degenerate_faces);
-BMVert *bmesh_jvke(
+BMVert *bmesh_kernel_join_vert_kill_edge(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_double,
const bool kill_degenerate_faces);
-BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
-BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep);
-BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep);
-BMVert *bmesh_urmv_loop_multi(
- BMesh *bm, BMLoop **larr, int larr_len);
-BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep);
+BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
-void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
+BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep);
+BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len);
+BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep);
#endif /* __BMESH_CORE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index 5e1d9c3a98d..5780dc57d78 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -58,7 +58,7 @@ static int bm_vert_other_tag(
{
BMIter iter;
BMEdge *e, *e_next = NULL;
- unsigned int count = 0;
+ uint count = 0;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) {
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 0551d824131..ab066682081 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -211,12 +211,12 @@ void *BMO_iter_as_arrayN(
int BM_iter_mesh_bitmap_from_filter(
const char itype, BMesh *bm,
- unsigned int *bitmap,
+ uint *bitmap,
bool (*test_fn)(BMElem *, void *user_data),
void *user_data);
int BM_iter_mesh_bitmap_from_filter_tessface(
BMesh *bm,
- unsigned int *bitmap,
+ uint *bitmap,
bool (*test_fn)(BMFace *, void *user_data),
void *user_data);
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 2591c33fc73..1d16dbc1836 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -88,7 +88,7 @@ struct BMLog {
/* Mapping from unique IDs to vertices and faces
*
- * Each vertex and face in the log gets a unique unsigned integer
+ * Each vertex and face in the log gets a unique uinteger
* assigned. That ID is taken from the set managed by the
* unused_ids range tree.
*
@@ -120,7 +120,7 @@ typedef struct {
} BMLogVert;
typedef struct {
- unsigned int v_ids[3];
+ uint v_ids[3];
char hflag;
} BMLogFace;
@@ -131,14 +131,14 @@ typedef struct {
#define logkey_cmp BLI_ghashutil_intcmp
/* Get the vertex's unique ID from the log */
-static unsigned int bm_log_vert_id_get(BMLog *log, BMVert *v)
+static uint bm_log_vert_id_get(BMLog *log, BMVert *v)
{
BLI_assert(BLI_ghash_haskey(log->elem_to_id, v));
return GET_UINT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, v));
}
/* Set the vertex's unique ID in the log */
-static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id)
+static void bm_log_vert_id_set(BMLog *log, BMVert *v, uint id)
{
void *vid = SET_UINT_IN_POINTER(id);
@@ -147,7 +147,7 @@ static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id)
}
/* Get a vertex from its unique ID */
-static BMVert *bm_log_vert_from_id(BMLog *log, unsigned int id)
+static BMVert *bm_log_vert_from_id(BMLog *log, uint id)
{
void *key = SET_UINT_IN_POINTER(id);
BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
@@ -155,14 +155,14 @@ static BMVert *bm_log_vert_from_id(BMLog *log, unsigned int id)
}
/* Get the face's unique ID from the log */
-static unsigned int bm_log_face_id_get(BMLog *log, BMFace *f)
+static uint bm_log_face_id_get(BMLog *log, BMFace *f)
{
BLI_assert(BLI_ghash_haskey(log->elem_to_id, f));
return GET_UINT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, f));
}
/* Set the face's unique ID in the log */
-static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id)
+static void bm_log_face_id_set(BMLog *log, BMFace *f, uint id)
{
void *fid = SET_UINT_IN_POINTER(id);
@@ -171,7 +171,7 @@ static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id)
}
/* Get a face from its unique ID */
-static BMFace *bm_log_face_from_id(BMLog *log, unsigned int id)
+static BMFace *bm_log_face_from_id(BMLog *log, uint id)
{
void *key = SET_UINT_IN_POINTER(id);
BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
@@ -255,7 +255,7 @@ static void bm_log_verts_unmake(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);
- unsigned int id = GET_UINT_FROM_POINTER(key);
+ uint id = GET_UINT_FROM_POINTER(key);
BMVert *v = bm_log_vert_from_id(log, id);
/* Ensure the log has the final values of the vertex before
@@ -271,7 +271,7 @@ static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces)
GHashIterator gh_iter;
GHASH_ITER (gh_iter, faces) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
- unsigned int id = GET_UINT_FROM_POINTER(key);
+ uint id = GET_UINT_FROM_POINTER(key);
BMFace *f = bm_log_face_from_id(log, id);
BMEdge *e_tri[3];
BMLoop *l_iter;
@@ -333,7 +333,7 @@ static void bm_log_vert_values_swap(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);
- unsigned int id = GET_UINT_FROM_POINTER(key);
+ uint id = GET_UINT_FROM_POINTER(key);
BMVert *v = bm_log_vert_from_id(log, id);
float mask;
short normal[3];
@@ -355,7 +355,7 @@ static void bm_log_face_values_swap(BMLog *log, GHash *faces)
GHASH_ITER (gh_iter, faces) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
- unsigned int id = GET_UINT_FROM_POINTER(key);
+ uint id = GET_UINT_FROM_POINTER(key);
BMFace *f = bm_log_face_from_id(log, id);
SWAP(char, f->head.hflag, lf->hflag);
@@ -374,13 +374,13 @@ static void bm_log_assign_ids(BMesh *bm, BMLog *log)
/* Generate vertex IDs */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- unsigned int id = range_tree_uint_take_any(log->unused_ids);
+ uint id = range_tree_uint_take_any(log->unused_ids);
bm_log_vert_id_set(log, v, id);
}
/* Generate face IDs */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- unsigned int id = range_tree_uint_take_any(log->unused_ids);
+ uint id = range_tree_uint_take_any(log->unused_ids);
bm_log_face_id_set(log, f, id);
}
}
@@ -425,7 +425,7 @@ static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
GHASH_ITER (gh_iter, id_ghash) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
- unsigned int id = GET_UINT_FROM_POINTER(key);
+ uint id = GET_UINT_FROM_POINTER(key);
range_tree_uint_retake(unused_ids, id);
}
@@ -433,8 +433,8 @@ static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
static int uint_compare(const void *a_v, const void *b_v)
{
- const unsigned int *a = a_v;
- const unsigned int *b = b_v;
+ const uint *a = a_v;
+ const uint *b = b_v;
return (*a) < (*b);
}
@@ -446,10 +446,10 @@ static int uint_compare(const void *a_v, const void *b_v)
* 10 -> 3
* 3 -> 1
*/
-static GHash *bm_log_compress_ids_to_indices(unsigned int *ids, unsigned int totid)
+static GHash *bm_log_compress_ids_to_indices(uint *ids, uint totid)
{
GHash *map = BLI_ghash_int_new_ex(__func__, totid);
- unsigned int i;
+ uint i;
qsort(ids, totid, sizeof(*ids), uint_compare);
@@ -469,7 +469,7 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
GHASH_ITER (gh_iter, id_ghash) {
void *key = BLI_ghashIterator_getKey(&gh_iter);
- unsigned int id = GET_UINT_FROM_POINTER(key);
+ uint id = GET_UINT_FROM_POINTER(key);
range_tree_uint_release(log->unused_ids, id);
}
}
@@ -480,7 +480,7 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
BMLog *BM_log_create(BMesh *bm)
{
BMLog *log = MEM_callocN(sizeof(*log), __func__);
- const unsigned int reserve_num = (unsigned int)(bm->totvert + bm->totface);
+ const uint reserve_num = (uint)(bm->totvert + bm->totface);
log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
@@ -593,8 +593,8 @@ int BM_log_length(const BMLog *log)
/* Apply a consistent ordering to BMesh vertices */
void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
{
- unsigned int *varr;
- unsigned int *farr;
+ uint *varr;
+ uint *farr;
GHash *id_to_idx;
@@ -602,7 +602,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
BMVert *v;
BMFace *f;
- unsigned int i;
+ uint i;
/* Put all vertex IDs into an array */
varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__);
@@ -617,7 +617,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
}
/* Create BMVert index remap array */
- id_to_idx = bm_log_compress_ids_to_indices(varr, (unsigned int)bm->totvert);
+ id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert);
BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
const unsigned id = bm_log_vert_id_get(log, v);
const void *key = SET_UINT_IN_POINTER(id);
@@ -627,7 +627,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
BLI_ghash_free(id_to_idx, NULL, NULL);
/* Create BMFace index remap array */
- id_to_idx = bm_log_compress_ids_to_indices(farr, (unsigned int)bm->totface);
+ id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface);
BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
const unsigned id = bm_log_face_id_get(log, f);
const void *key = SET_UINT_IN_POINTER(id);
@@ -835,7 +835,7 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o
{
BMLogEntry *entry = log->current_entry;
BMLogVert *lv;
- unsigned int v_id = bm_log_vert_id_get(log, v);
+ uint v_id = bm_log_vert_id_get(log, v);
void *key = SET_UINT_IN_POINTER(v_id);
void **val_p;
@@ -859,7 +859,7 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o
void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
BMLogVert *lv;
- unsigned int v_id = range_tree_uint_take_any(log->unused_ids);
+ uint v_id = range_tree_uint_take_any(log->unused_ids);
void *key = SET_UINT_IN_POINTER(v_id);
bm_log_vert_id_set(log, v, v_id);
@@ -876,7 +876,7 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
void BM_log_face_modified(BMLog *log, BMFace *f)
{
BMLogFace *lf;
- unsigned int f_id = bm_log_face_id_get(log, f);
+ uint f_id = bm_log_face_id_get(log, f);
void *key = SET_UINT_IN_POINTER(f_id);
lf = bm_log_face_alloc(log, f);
@@ -892,7 +892,7 @@ void BM_log_face_modified(BMLog *log, BMFace *f)
void BM_log_face_added(BMLog *log, BMFace *f)
{
BMLogFace *lf;
- unsigned int f_id = range_tree_uint_take_any(log->unused_ids);
+ uint f_id = range_tree_uint_take_any(log->unused_ids);
void *key = SET_UINT_IN_POINTER(f_id);
/* Only triangles are supported for now */
@@ -922,7 +922,7 @@ void BM_log_face_added(BMLog *log, BMFace *f)
void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
BMLogEntry *entry = log->current_entry;
- unsigned int v_id = bm_log_vert_id_get(log, v);
+ uint v_id = bm_log_vert_id_get(log, v);
void *key = SET_UINT_IN_POINTER(v_id);
/* if it has a key, it shouldn't be NULL */
@@ -963,7 +963,7 @@ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
void BM_log_face_removed(BMLog *log, BMFace *f)
{
BMLogEntry *entry = log->current_entry;
- unsigned int f_id = bm_log_face_id_get(log, f);
+ uint f_id = bm_log_face_id_get(log, f);
void *key = SET_UINT_IN_POINTER(f_id);
/* if it has a key, it shouldn't be NULL */
@@ -991,11 +991,11 @@ void BM_log_all_added(BMesh *bm, BMLog *log)
/* avoid unnecessary resizing on initialization */
if (BLI_ghash_size(log->current_entry->added_verts) == 0) {
- BLI_ghash_reserve(log->current_entry->added_verts, (unsigned int)bm->totvert);
+ BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert);
}
if (BLI_ghash_size(log->current_entry->added_faces) == 0) {
- BLI_ghash_reserve(log->current_entry->added_faces, (unsigned int)bm->totface);
+ BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface);
}
/* Log all vertices as newly created */
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 57a6d8d2e1a..d5d9e4abe2c 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -486,8 +486,7 @@ static void bm_mesh_edges_sharp_tag(
BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle,
float (*r_lnos)[3])
{
- BMIter eiter, viter;
- BMVert *v;
+ BMIter eiter;
BMEdge *e;
int i;
@@ -498,19 +497,13 @@ static void bm_mesh_edges_sharp_tag(
}
{
- char htype = BM_LOOP;
+ char htype = BM_VERT | BM_LOOP;
if (fnos) {
htype |= BM_FACE;
}
BM_mesh_elem_index_ensure(bm, htype);
}
- /* Clear all vertices' tags (means they are all smooth for now). */
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_index_set(v, i); /* set_inline */
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
-
/* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were
* all smooth).
*/
@@ -551,20 +544,45 @@ static void bm_mesh_edges_sharp_tag(
no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no;
copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no);
}
- else {
- /* Sharp edge, tag its verts as such. */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+
+ bm->elem_index_dirty &= ~BM_EDGE;
+}
+
+/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not.
+ * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */
+static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
+{
+ BMLoop *lfan_pivot_next = l_curr;
+ BMEdge *e_next = l_curr->e;
+
+ BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG));
+ BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
+
+ while (true) {
+ /* Much simpler than in sibling code with basic Mesh data! */
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next);
+
+ if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) {
+ /* Sharp loop/edge, so not a cyclic smooth fan... */
+ return false;
+ }
+ /* Smooth loop/edge... */
+ else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) {
+ if (lfan_pivot_next == l_curr) {
+ /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can
+ * use initial l_curr/l_prev edge as start for this smooth fan. */
+ return true;
}
+ /* ... already checked in some previous looping, we can abort. */
+ return false;
}
else {
- /* Sharp edge, tag its verts as such. */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ /* ... we can skip it in future, and keep checking the smooth fan. */
+ BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
}
}
-
- bm->elem_index_dirty &= ~(BM_EDGE | BM_VERT);
}
/* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c
@@ -587,13 +605,11 @@ static void bm_mesh_loops_calc_normals(
BLI_Stack *edge_vectors = NULL;
{
- char htype = BM_LOOP;
+ char htype = 0;
if (vcos) {
htype |= BM_VERT;
}
- if (fnos) {
- htype |= BM_FACE;
- }
+ /* Face/Loop indices are set inline below. */
BM_mesh_elem_index_ensure(bm, htype);
}
@@ -606,6 +622,21 @@ static void bm_mesh_loops_calc_normals(
edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
}
+ /* Clear all loops' tags (means none are to be skipped for now). */
+ int index_face, index_loop = 0;
+ BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) {
+ BMLoop *l_curr, *l_first;
+
+ BM_elem_index_set(f_curr, index_face); /* set_inline */
+
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
+ do {
+ BM_elem_index_set(l_curr, index_loop++); /* set_inline */
+ BM_elem_flag_disable(l_curr, BM_ELEM_TAG);
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+ bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
+
/* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't).
* Now, time to generate the normals.
*/
@@ -614,16 +645,16 @@ static void bm_mesh_loops_calc_normals(
l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
do {
+ /* A smooth edge, we have to check for cyclic smooth fan case.
+ * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as
+ * 'entry point', otherwise we can skip it. */
+ /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack,
+ * to avoid having to fan again around the vert during actual computation of clnor & clnorspace.
+ * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop()
+ * is quite cheap in term of CPU cycles, so really think it's not worth it. */
if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- (!r_lnors_spacearr || BM_elem_flag_test(l_curr->v, BM_ELEM_TAG)))
+ (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !bm_mesh_loop_check_cyclic_smooth_fan(l_curr)))
{
- /* A smooth edge, and we are not generating lnors_spacearr, or the related vertex is sharp.
- * We skip it because it is either:
- * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
- * one of its ends, i.e. one of its two sharp edges), or...
- * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex
- * are just fine!
- */
}
else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
!BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG))
@@ -1481,23 +1512,6 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
}
}
-/**
- * Special case: Python uses custom-data layers to hold PyObject references.
- * These have to be kept in-place, else the PyObject's we point to, wont point back to us.
- *
- * \note ``ele_src`` Is a duplicate, so we don't need to worry about getting in a feedback loop.
- *
- * \note If there are other customdata layers which need this functionality, it should be generalized.
- * However #BM_mesh_remap is currently the only place where this is done.
- */
-static void bm_mesh_remap_cd_update(
- BMHeader *ele_dst, BMHeader *ele_src,
- const int cd_elem_pyptr)
-{
- void **pyptr_dst_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_dst), cd_elem_pyptr);
- void **pyptr_src_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_src), cd_elem_pyptr);
- *pyptr_dst_p = *pyptr_src_p;
-}
/**
* Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
@@ -1513,9 +1527,9 @@ static void bm_mesh_remap_cd_update(
*/
void BM_mesh_remap(
BMesh *bm,
- const unsigned int *vert_idx,
- const unsigned int *edge_idx,
- const unsigned int *face_idx)
+ const uint *vert_idx,
+ const uint *edge_idx,
+ const uint *face_idx)
{
/* Mapping old to new pointers. */
GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL;
@@ -1538,7 +1552,9 @@ void BM_mesh_remap(
if (vert_idx) {
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
- const unsigned int *new_idx;
+ const uint *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
@@ -1547,9 +1563,14 @@ void BM_mesh_remap(
/* Make a copy of all vertices. */
verts_pool = bm->vtable;
verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
+ void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL;
for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
*ve = **vep;
/* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/
+ if (cd_vert_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr);
+ pyptrs[i] = *pyptr;
+ }
}
/* Copy back verts to their new place, and update old2new pointers mapping. */
@@ -1562,20 +1583,26 @@ void BM_mesh_remap(
/* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
BLI_ghash_insert(vptr_map, *vep, new_vep);
if (cd_vert_pyptr != -1) {
- bm_mesh_remap_cd_update(&(*vep)->head, &new_vep->head, cd_vert_pyptr);
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr);
+ *pyptr = pyptrs[*new_idx];
}
}
bm->elem_index_dirty |= BM_VERT;
bm->elem_table_dirty |= BM_VERT;
MEM_freeN(verts_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
}
/* Remap Edges */
if (edge_idx) {
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
- const unsigned int *new_idx;
+ const uint *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
@@ -1584,8 +1611,13 @@ void BM_mesh_remap(
/* Make a copy of all vertices. */
edges_pool = bm->etable;
edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
+ void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL;
for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
*ed = **edp;
+ if (cd_edge_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr);
+ pyptrs[i] = *pyptr;
+ }
}
/* Copy back verts to their new place, and update old2new pointers mapping. */
@@ -1598,20 +1630,26 @@ void BM_mesh_remap(
BLI_ghash_insert(eptr_map, *edp, new_edp);
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
if (cd_edge_pyptr != -1) {
- bm_mesh_remap_cd_update(&(*edp)->head, &new_edp->head, cd_edge_pyptr);
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr);
+ *pyptr = pyptrs[*new_idx];
}
}
bm->elem_index_dirty |= BM_EDGE;
bm->elem_table_dirty |= BM_EDGE;
MEM_freeN(edges_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
}
/* Remap Faces */
if (face_idx) {
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
- const unsigned int *new_idx;
+ const uint *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
@@ -1620,8 +1658,13 @@ void BM_mesh_remap(
/* Make a copy of all vertices. */
faces_pool = bm->ftable;
faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
+ void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL;
for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
*fa = **fap;
+ if (cd_poly_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr);
+ pyptrs[i] = *pyptr;
+ }
}
/* Copy back verts to their new place, and update old2new pointers mapping. */
@@ -1633,7 +1676,8 @@ void BM_mesh_remap(
*new_fap = *fa;
BLI_ghash_insert(fptr_map, *fap, new_fap);
if (cd_poly_pyptr != -1) {
- bm_mesh_remap_cd_update(&(*fap)->head, &new_fap->head, cd_poly_pyptr);
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr);
+ *pyptr = pyptrs[*new_idx];
}
}
@@ -1641,6 +1685,9 @@ void BM_mesh_remap(
bm->elem_table_dirty |= BM_FACE;
MEM_freeN(faces_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
}
/* And now, fix all vertices/edges/faces/loops pointers! */
@@ -2008,4 +2055,4 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
vpool_dst, epool_dst, NULL, fpool_dst);
bm->use_toolflags = use_toolflags;
-} \ No newline at end of file
+}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 6a9540c3b60..01f11f6f942 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -34,7 +34,7 @@ void BM_mesh_elem_toolflags_ensure(BMesh *bm);
void BM_mesh_elem_toolflags_clear(BMesh *bm);
struct BMeshCreateParams {
- unsigned int use_toolflags : 1;
+ uint use_toolflags : 1;
};
BMesh *BM_mesh_create(
@@ -88,9 +88,9 @@ int BM_mesh_elem_count(BMesh *bm, const char htype);
void BM_mesh_remap(
BMesh *bm,
- const unsigned int *vert_idx,
- const unsigned int *edge_idx,
- const unsigned int *face_idx);
+ const uint *vert_idx,
+ const uint *edge_idx,
+ const uint *face_idx);
void BM_mesh_rebuild(
BMesh *bm, const struct BMeshCreateParams *params,
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h
index 7cbfe2d9210..1974d364171 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h
@@ -41,11 +41,11 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm);
struct BMeshFromMeshParams {
- unsigned int calc_face_normal : 1;
+ uint calc_face_normal : 1;
/* add a vertex CD_SHAPE_KEYINDEX layer */
- unsigned int add_key_index : 1;
+ uint add_key_index : 1;
/* set vertex coordinates from the shapekey */
- unsigned int use_shapekey : 1;
+ uint use_shapekey : 1;
/* define the active shape key (index + 1) */
int active_shapekey;
};
@@ -55,7 +55,7 @@ void BM_mesh_bm_from_me(
ATTR_NONNULL(1, 3);
struct BMeshToMeshParams {
- unsigned int calc_tessface : 1;
+ uint calc_tessface : 1;
int64_t cd_mask_extra;
};
void BM_mesh_bm_to_me(
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 500da6b8788..1cd51528e06 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -234,7 +234,7 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_de
if (l_a->v == l_b->v) {
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- bmesh_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true);
+ bmesh_kernel_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true);
}
BMFace *faces[2] = {l_a->f, l_b->f};
@@ -288,9 +288,9 @@ BMFace *BM_face_split(
}
#ifdef USE_BMESH_HOLES
- f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, NULL, example, no_double);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, NULL, example, no_double);
#else
- f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, example, no_double);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, example, no_double);
#endif
if (f_new) {
@@ -370,19 +370,19 @@ BMFace *BM_face_split_n(
f_tmp = BM_face_copy(bm, bm, f, true, true);
#ifdef USE_BMESH_HOLES
- f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, NULL, example, false);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, NULL, example, false);
#else
- f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, example, false);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, example, false);
#endif
- /* bmesh_sfme returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'.
+ /* bmesh_kernel_split_face_make_edge returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'.
* The radial_next is for 'f' and goes from 'v_b' to 'v_a' */
if (f_new) {
e = l_new->e;
for (i = 0; i < n; i++) {
- v_new = bmesh_semv(bm, v_b, e, &e_new);
+ v_new = bmesh_kernel_split_edge_make_vert(bm, v_b, e, &e_new);
BLI_assert(v_new != NULL);
- /* bmesh_semv returns in 'e_new' the edge going from 'v_new' to 'v_b' */
+ /* bmesh_kernel_split_edge_make_vert returns in 'e_new' the edge going from 'v_new' to 'v_b' */
copy_v3_v3(v_new->co, cos[i]);
/* interpolate the loop data for the loops with (v == v_new), using orig face */
@@ -507,7 +507,7 @@ BMEdge *BM_vert_collapse_faces(
/* single face or no faces */
/* same as BM_vert_collapse_edge() however we already
* have vars to perform this operation so don't call. */
- e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
/* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
}
@@ -542,7 +542,7 @@ BMEdge *BM_vert_collapse_edge(
BMVert *tv2 = BM_edge_other_vert(e2, v_kill);
if (tv2) {
/* only action, other calls here only get the edge to return */
- e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
}
}
}
@@ -564,7 +564,7 @@ BMVert *BM_edge_collapse(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool kill_degenerate_faces)
{
- return bmesh_jvke(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
}
/**
@@ -616,7 +616,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
}
v_other = BM_edge_other_vert(e, v);
- v_new = bmesh_semv(bm, v, e, &e_new);
+ v_new = bmesh_kernel_split_edge_make_vert(bm, v, e, &e_new);
if (r_e != NULL) {
*r_e = e_new;
}
@@ -1090,23 +1090,18 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f
/**
* \brief Rip a single face from a vertex fan
*/
-BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv)
+BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep)
{
- return bmesh_urmv(bm, sf, sv);
+ return bmesh_kernel_unglue_region_make_vert(bm, l_sep);
}
-/**
- * \brief Rip a single face from a vertex fan
- *
- * \note same as #BM_face_vert_separate but faster (avoids a loop lookup)
- */
-BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl)
+BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep)
{
- return bmesh_urmv_loop(bm, sl);
+ return bmesh_kernel_unglue_region_make_vert_multi_isolated(bm, l_sep);
}
-BMVert *BM_face_loop_separate_multi(
- BMesh *bm, BMLoop **larr, int larr_len)
+BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len)
{
- return bmesh_urmv_loop_multi(bm, larr, larr_len);
+ return bmesh_kernel_unglue_region_make_vert_multi(bm, larr, larr_len);
}
+
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 5e95e9a2cc7..330a714418d 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -86,9 +86,8 @@ enum {
};
-BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv);
-BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl);
-BMVert *BM_face_loop_separate_multi(
- BMesh *bm, BMLoop **larr, int larr_len);
+BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep);
+BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep);
+BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len);
#endif /* __BMESH_MODS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 0d0fdda2c4c..200a31b1a57 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1284,7 +1284,7 @@ static BMOpDefine bmo_bisect_plane_def = {
{"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */
{{'\0'}},
},
- {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output new geometry from the cut */
+ {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */
{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */
{{'\0'}}},
bmo_bisect_plane_exec,
@@ -1741,6 +1741,8 @@ static BMOpDefine bmo_bevel_def = {
},
/* slots_out */
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
+ {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
{{'\0'}},
},
@@ -1912,7 +1914,6 @@ static BMOpDefine bmo_wireframe_def = {
{"use_even_offset", BMO_OP_SLOT_BOOL},
{"use_crease", BMO_OP_SLOT_BOOL},
{"crease_weight", BMO_OP_SLOT_FLT},
- {"thickness", BMO_OP_SLOT_FLT},
{"use_relative_offset", BMO_OP_SLOT_BOOL},
{"material_offset", BMO_OP_SLOT_INT},
{{'\0'}},
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 706a7f74ed2..44445aae25a 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -128,7 +128,7 @@ void BMO_pop(BMesh *bm)
static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args)
{
BMOpSlot *slot;
- unsigned int i;
+ uint i;
for (i = 0; slot_types[i].type; i++) {
slot = &slot_args[i];
slot->slot_name = slot_types[i].name;
@@ -149,7 +149,7 @@ static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args
static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args)
{
BMOpSlot *slot;
- unsigned int i;
+ uint i;
for (i = 0; slot_types[i].type; i++) {
slot = &slot_args[i];
switch (slot->slot_type) {
@@ -311,9 +311,9 @@ void _bmo_slot_copy(
}
else {
/* check types */
- const unsigned int tot = slot_src->len;
- unsigned int i;
- unsigned int out = 0;
+ const uint tot = slot_src->len;
+ uint i;
+ uint out = 0;
BMElem **ele_src = (BMElem **)slot_src->data.buf;
for (i = 0; i < tot; i++, ele_src++) {
if ((*ele_src)->head.htype & dst_elem_flag) {
@@ -333,8 +333,8 @@ void _bmo_slot_copy(
}
else {
/* only copy compatible elements */
- const unsigned int tot = slot_src->len;
- unsigned int i;
+ const uint tot = slot_src->len;
+ uint i;
BMElem **ele_src = (BMElem **)slot_src->data.buf;
BMElem **ele_dst = (BMElem **)slot_dst->data.buf;
for (i = 0; i < tot; i++, ele_src++) {
@@ -1639,8 +1639,8 @@ static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], cons
int BMO_opcode_from_opname(const char *opname)
{
- const unsigned int tot = bmo_opdefines_total;
- unsigned int i;
+ const uint tot = bmo_opdefines_total;
+ uint i;
for (i = 0; i < tot; i++) {
if (STREQ(bmo_opdefines[i]->opname, opname)) {
return i;
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index 0a4fb1d56a4..b670f31ad9f 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -141,12 +141,19 @@ void BM_mesh_esubdivide(
const short use_only_quads,
const int seed);
-void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag);
-void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag);
-void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], const float radius, const short oflag);
+void BM_mesh_calc_uvs_grid(
+ BMesh *bm, const uint x_segments, const uint y_segments,
+ const short oflag, const int cd_loop_uv_offset);
+void BM_mesh_calc_uvs_sphere(
+ BMesh *bm,
+ const short oflag, const int cd_loop_uv_offset);
+void BM_mesh_calc_uvs_circle(
+ BMesh *bm, float mat[4][4], const float radius,
+ const short oflag, const int cd_loop_uv_offset);
void BM_mesh_calc_uvs_cone(
BMesh *bm, float mat[4][4],
- const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag);
+ const float radius_top, const float radius_bottom, const int segments, const bool cap_ends,
+ const short oflag, const int cd_loop_uv_offset);
void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag);
#include "intern/bmesh_operator_api_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 6acd790fc0c..a4621b45fe6 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -132,7 +132,7 @@ static void bm_face_calc_poly_center_mean_vertex_cos(
*/
void BM_face_calc_tessellation(
const BMFace *f, const bool use_fixed_quad,
- BMLoop **r_loops, unsigned int (*r_index)[3])
+ BMLoop **r_loops, uint (*r_index)[3])
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter;
@@ -196,7 +196,7 @@ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
* but without this we can't be sure the point is inside a concave face. */
const int tottri = f->len - 2;
BMLoop **loops = BLI_array_alloca(loops, f->len);
- unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
+ uint (*index)[3] = BLI_array_alloca(index, tottri);
int j;
int j_best = 0; /* use as fallback when unset */
float area_best = -1.0f;
@@ -575,11 +575,11 @@ void BM_face_calc_center_mean_weighted(const BMFace *f, float r_cent[3])
* Rotates a polygon so that it's
* normal is pointing towards the mesh Z axis
*/
-void poly_rotate_plane(const float normal[3], float (*verts)[3], const unsigned int nverts)
+void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts)
{
float mat[3][3];
float co[3];
- unsigned int i;
+ uint i;
co[2] = 0.0f;
@@ -844,7 +844,7 @@ void BM_face_normal_flip_ex(
BMesh *bm, BMFace *f,
const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
{
- bmesh_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
+ bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
negate_v3(f->no);
}
@@ -941,7 +941,7 @@ void BM_face_triangulate(
{
BMLoop **loops = BLI_array_alloca(loops, f->len);
- unsigned int (*tris)[3] = BLI_array_alloca(tris, f->len);
+ uint (*tris)[3] = BLI_array_alloca(tris, f->len);
const int totfilltri = f->len - 2;
const int last_tri = f->len - 3;
int i;
@@ -1425,7 +1425,7 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptri
float axis_mat[3][3];
float (*projverts)[2];
- unsigned int (*tris)[3];
+ uint (*tris)[3];
const int totfilltri = efa->len - 2;
@@ -1451,7 +1451,7 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptri
for (j = 0; j < totfilltri; j++) {
BMLoop **l_ptr = looptris[i++];
- unsigned int *tri = tris[j];
+ uint *tri = tris[j];
l_ptr[0] = l_arr[tri[0]];
l_ptr[1] = l_arr[tri[1]];
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 1e50a504875..d944f3a8bc5 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -36,7 +36,7 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr
void BM_face_calc_tessellation(
const BMFace *f, const bool use_fixed_quad,
- BMLoop **r_loops, unsigned int (*r_index)[3]);
+ BMLoop **r_loops, uint (*r_index)[3]);
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]);
float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
float BM_face_calc_normal_vcos(
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 6ce7c100b0d..e515f9af63f 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -62,15 +62,16 @@
#define EDGE_NET _FLAG_WALK
/* tag verts we've visit */
#define VERT_VISIT _FLAG_WALK
+#define VERT_IN_QUEUE _FLAG_WALK_ALT
struct VertOrder {
float angle;
BMVert *v;
};
-static unsigned int bm_edge_flagged_radial_count(BMEdge *e)
+static uint bm_edge_flagged_radial_count(BMEdge *e)
{
- unsigned int count = 0;
+ uint count = 0;
BMLoop *l;
if ((l = e->l)) {
@@ -133,7 +134,7 @@ static bool bm_face_split_edgenet_find_loop_pair(
e = e_first = v_init->e;
do {
if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
- const unsigned int count = bm_edge_flagged_radial_count(e);
+ const uint count = bm_edge_flagged_radial_count(e);
if (count == 1) {
BLI_SMALLSTACK_PUSH(edges_boundary, e);
edges_boundary_len++;
@@ -238,7 +239,7 @@ static bool bm_face_split_edgenet_find_loop_pair_exists(
e = e_first = v_init->e;
do {
if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
- const unsigned int count = bm_edge_flagged_radial_count(e);
+ const uint count = bm_edge_flagged_radial_count(e);
if (count == 1) {
edges_boundary_len++;
}
@@ -274,7 +275,7 @@ static bool bm_face_split_edgenet_find_loop_pair_exists(
static bool bm_face_split_edgenet_find_loop_walk(
BMVert *v_init, const float face_normal[3],
/* cache to avoid realloc every time */
- struct VertOrder *edge_order, const unsigned int edge_order_len,
+ struct VertOrder *edge_order, const uint edge_order_len,
BMEdge *e_pair[2])
{
/* fast-path for the common case (avoid push-pop).
@@ -381,7 +382,7 @@ walk_nofork:
/* sort by angle if needed */
if (STACK_SIZE(edge_order) > 1) {
- unsigned int j;
+ uint j;
BMVert *v_prev = BM_edge_other_vert(v->e, v);
for (j = 0; j < STACK_SIZE(edge_order); j++) {
@@ -420,7 +421,7 @@ finally:
static bool bm_face_split_edgenet_find_loop(
BMVert *v_init, const float face_normal[3], float face_normal_matrix[3][3],
/* cache to avoid realloc every time */
- struct VertOrder *edge_order, const unsigned int edge_order_len,
+ struct VertOrder *edge_order, const uint edge_order_len,
BMVert **r_face_verts, int *r_face_verts_len)
{
BMEdge *e_pair[2];
@@ -434,7 +435,7 @@ static bool bm_face_split_edgenet_find_loop(
(bm_edge_flagged_radial_count(e_pair[1]) == 1));
if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) {
- unsigned int i = 0;
+ uint i = 0;
r_face_verts[i++] = v_init;
v = BM_edge_other_vert(e_pair[1], v_init);
@@ -474,7 +475,7 @@ bool BM_face_split_edgenet(
int i;
struct VertOrder *edge_order;
- const unsigned int edge_order_len = edge_net_len + 2;
+ const uint edge_order_len = edge_net_len + 2;
BMVert *v;
@@ -512,13 +513,21 @@ bool BM_face_split_edgenet(
} while ((l_iter = l_iter->next) != l_first);
#endif
+ /* Note: 'VERT_IN_QUEUE' is often not needed at all,
+ * however in rare cases verts are added multiple times to the queue,
+ * that on it's own is harmless but in _very_ rare cases,
+ * the queue will overflow its maximum size,
+ * so we better be strict about this! see: T51539 */
for (i = 0; i < edge_net_len; i++) {
BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_IN_QUEUE);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_IN_QUEUE);
}
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
+ BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_IN_QUEUE);
} while ((l_iter = l_iter->next) != l_first);
float face_normal_matrix[3][3];
@@ -527,8 +536,10 @@ bool BM_face_split_edgenet(
/* any vert can be used to begin with */
STACK_PUSH(vert_queue, l_first->v);
+ BM_ELEM_API_FLAG_ENABLE(l_first->v, VERT_IN_QUEUE);
while ((v = STACK_POP(vert_queue))) {
+ BM_ELEM_API_FLAG_DISABLE(v, VERT_IN_QUEUE);
if (bm_face_split_edgenet_find_loop(
v, f->no, face_normal_matrix,
edge_order, edge_order_len, face_verts, &face_verts_len))
@@ -558,8 +569,12 @@ bool BM_face_split_edgenet(
* (verts between boundary and manifold edges) */
l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
do {
- if (bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) {
+ /* Avoid adding to queue multiple times (not common but happens). */
+ if (!BM_ELEM_API_FLAG_TEST(l_iter->v, VERT_IN_QUEUE) &&
+ bm_face_split_edgenet_find_loop_pair_exists(l_iter->v))
+ {
STACK_PUSH(vert_queue, l_iter->v);
+ BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_IN_QUEUE);
}
} while ((l_iter = l_iter->next) != l_first);
}
@@ -721,13 +736,13 @@ BLI_INLINE bool edge_isect_verts_point_2d(
*/
struct EdgeGroupIsland {
LinkNode edge_links; /* keep first */
- unsigned int vert_len, edge_len;
+ uint vert_len, edge_len;
/* Set the following vars once we have >1 groups */
/* when when an edge in a previous group connects to this one,
* so theres no need to create one pointing back. */
- unsigned int has_prev_edge : 1;
+ uint has_prev_edge : 1;
/* verts in the group which has the lowest & highest values,
* the lower vertex is connected to the first edge */
@@ -758,7 +773,7 @@ struct Edges_VertVert_BVHTreeTest {
BMVert *v_origin;
BMVert *v_other;
- const unsigned int *vert_range;
+ const uint *vert_range;
};
struct Edges_VertRay_BVHTreeTest {
@@ -766,7 +781,7 @@ struct Edges_VertRay_BVHTreeTest {
BMVert *v_origin;
- const unsigned int *vert_range;
+ const uint *vert_range;
};
static void bvhtree_test_edges_isect_2d_vert_cb(
@@ -831,12 +846,12 @@ static void bvhtree_test_edges_isect_2d_ray_cb(
struct EdgeGroup_FindConnection_Args {
BVHTree *bvhtree;
BMEdge **edge_arr;
- unsigned int edge_arr_len;
+ uint edge_arr_len;
BMEdge **edge_arr_new;
- unsigned int edge_arr_new_len;
+ uint edge_arr_new_len;
- const unsigned int *vert_range;
+ const uint *vert_range;
};
static BMEdge *test_edges_isect_2d_vert(
@@ -869,7 +884,7 @@ static BMEdge *test_edges_isect_2d_vert(
/* check existing connections (no spatial optimization here since we're continually adding). */
if (LIKELY(index == -1)) {
float t_best = 1.0f;
- for (unsigned int i = 0; i < args->edge_arr_new_len; i++) {
+ for (uint i = 0; i < args->edge_arr_new_len; i++) {
float co_isect[2];
if (UNLIKELY(edge_isect_verts_point_2d(args->edge_arr_new[i], v_origin, v_other, co_isect))) {
const float t_test = line_point_factor_v2(co_isect, v_origin->co, v_other->co);
@@ -914,7 +929,7 @@ static BMEdge *test_edges_isect_2d_ray(
/* check existing connections (no spatial optimization here since we're continually adding). */
if (LIKELY(index != -1)) {
- for (unsigned int i = 0; i < args->edge_arr_new_len; i++) {
+ for (uint i = 0; i < args->edge_arr_new_len; i++) {
BMEdge *e = args->edge_arr_new[i];
float dist_new;
if (isect_ray_seg_v2(v_origin->co, dir, e->v1->co, e->v2->co, &dist_new, NULL)) {
@@ -1031,7 +1046,7 @@ static BMVert *bm_face_split_edgenet_partial_connect(BMesh *bm, BMVert *v_delimi
/* initial check - see if we have 3+ flagged edges attached to 'v_delimit'
* if not, we can early exit */
LinkNode *e_delimit_list = NULL;
- unsigned int e_delimit_list_len = 0;
+ uint e_delimit_list_len = 0;
#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
@@ -1169,10 +1184,10 @@ static bool bm_vert_partial_connect_check_overlap(
*/
bool BM_face_split_edgenet_connect_islands(
BMesh *bm,
- BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len,
+ BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len,
bool use_partial_connect,
MemArena *mem_arena,
- BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len)
+ BMEdge ***r_edge_net_new, uint *r_edge_net_new_len)
{
/* -------------------------------------------------------------------- */
/* This function has 2 main parts.
@@ -1186,7 +1201,7 @@ bool BM_face_split_edgenet_connect_islands(
* (avoid thrashing the area when the initial check isn't so intensive on the stack).
*/
- const unsigned int edge_arr_len = (unsigned int)edge_net_init_len + (unsigned int)f->len;
+ const uint edge_arr_len = (uint)edge_net_init_len + (uint)f->len;
BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
bool ok = false;
@@ -1197,7 +1212,7 @@ bool BM_face_split_edgenet_connect_islands(
#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
{
- unsigned int i = edge_net_init_len;
+ uint i = edge_net_init_len;
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
@@ -1206,7 +1221,7 @@ bool BM_face_split_edgenet_connect_islands(
BLI_assert(i == edge_arr_len);
}
- for (unsigned int i = 0; i < edge_arr_len; i++) {
+ for (uint i = 0; i < edge_arr_len; i++) {
BM_elem_flag_enable(edge_arr[i], EDGE_NOT_IN_STACK);
BM_elem_flag_enable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
BM_elem_flag_enable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
@@ -1224,12 +1239,12 @@ bool BM_face_split_edgenet_connect_islands(
struct {
struct TempVertPair *list;
- unsigned int len;
+ uint len;
int *remap; /* temp -> orig mapping */
} temp_vert_pairs = {NULL};
if (use_partial_connect) {
- for (unsigned int i = 0; i < edge_net_init_len; i++) {
+ for (uint i = 0; i < edge_net_init_len; i++) {
for (unsigned j = 0; j < 2; j++) {
BMVert *v_delimit = (&edge_arr[i]->v1)[j];
BMVert *v_other;
@@ -1254,19 +1269,19 @@ bool BM_face_split_edgenet_connect_islands(
- unsigned int group_arr_len = 0;
+ uint group_arr_len = 0;
LinkNode *group_head = NULL;
{
/* scan 'edge_arr' backwards so the outer face boundary is handled first
* (since its likely to be the largest) */
- unsigned int edge_index = (edge_arr_len - 1);
- unsigned int edge_in_group_tot = 0;
+ uint edge_index = (edge_arr_len - 1);
+ uint edge_in_group_tot = 0;
BLI_SMALLSTACK_DECLARE(vstack, BMVert *);
while (true) {
LinkNode *edge_links = NULL;
- unsigned int unique_verts_in_group = 0, unique_edges_in_group = 0;
+ uint unique_verts_in_group = 0, unique_edges_in_group = 0;
/* list of groups */
BLI_assert(BM_elem_flag_test(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK));
@@ -1333,7 +1348,7 @@ bool BM_face_split_edgenet_connect_islands(
#define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG
struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena, sizeof(*group_arr) * group_arr_len);
- unsigned int vert_arr_len = 0;
+ uint vert_arr_len = 0;
/* sort groups by lowest value vertex */
{
/* fill 'groups_arr' in reverse order so the boundary face is first */
@@ -1389,7 +1404,7 @@ bool BM_face_split_edgenet_connect_islands(
/* we don't know how many unique verts there are connecting the edges, so over-alloc */
BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len);
/* map vertex -> group index */
- unsigned int *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len);
+ uint *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len);
float (*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena, sizeof(*vert_coords_backup) * vert_arr_len);
@@ -1398,7 +1413,7 @@ bool BM_face_split_edgenet_connect_islands(
const float f_co_ref[3] = {UNPACK3(BM_FACE_FIRST_LOOP(f)->v->co)};
int v_index = 0; /* global vert index */
- for (unsigned int g_index = 0; g_index < group_arr_len; g_index++) {
+ for (uint g_index = 0; g_index < group_arr_len; g_index++) {
LinkNode *edge_links = group_arr[g_index]->edge_links.link;
do {
BMEdge *e = edge_links->link;
@@ -1436,7 +1451,7 @@ bool BM_face_split_edgenet_connect_islands(
/* Now create bvh tree*/
BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 0.0f, 8, 8);
- for (unsigned int i = 0; i < edge_arr_len; i++) {
+ for (uint i = 0; i < edge_arr_len; i++) {
const float e_cos[2][3] = {
{UNPACK2(edge_arr[i]->v1->co), 0.0f},
{UNPACK2(edge_arr[i]->v2->co), 0.0f},
@@ -1465,15 +1480,15 @@ bool BM_face_split_edgenet_connect_islands(
/* Create connections between groups */
/* may be an over-alloc, but not by much */
- unsigned int edge_net_new_len = (unsigned int)edge_net_init_len + ((group_arr_len - 1) * 2);
+ uint edge_net_new_len = (uint)edge_net_init_len + ((group_arr_len - 1) * 2);
BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len);
memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len);
{
- unsigned int edge_net_new_index = edge_net_init_len;
+ uint edge_net_new_index = edge_net_init_len;
/* start-end of the verts in the current group */
- unsigned int vert_range[2];
+ uint vert_range[2];
vert_range[0] = 0;
vert_range[1] = group_arr[0]->vert_len;
@@ -1492,7 +1507,7 @@ bool BM_face_split_edgenet_connect_islands(
.vert_range = vert_range,
};
- for (unsigned int g_index = 1; g_index < group_arr_len; g_index++) {
+ for (uint g_index = 1; g_index < group_arr_len; g_index++) {
struct EdgeGroupIsland *g = group_arr[g_index];
/* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */
@@ -1551,7 +1566,7 @@ bool BM_face_split_edgenet_connect_islands(
}
/* tell the 'next' group it doesn't need to create its own back-link */
- unsigned int g_index_other = verts_group_table[index_other];
+ uint g_index_other = verts_group_table[index_other];
group_arr[g_index_other]->has_prev_edge = true;
}
}
@@ -1567,7 +1582,7 @@ bool BM_face_split_edgenet_connect_islands(
*r_edge_net_new_len = edge_net_new_len;
ok = true;
- for (unsigned int i = 0; i < vert_arr_len; i++) {
+ for (uint i = 0; i < vert_arr_len; i++) {
copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]);
}
@@ -1600,7 +1615,7 @@ finally:
/* Remove edges which have become doubles since splicing vertices together,
* its less trouble then detecting future-doubles on edge-creation. */
- for (unsigned int i = edge_net_init_len; i < edge_net_new_len; i++) {
+ for (uint i = edge_net_init_len; i < edge_net_new_len; i++) {
while (BM_edge_find_double(edge_net_new[i])) {
BM_edge_kill(bm, edge_net_new[i]);
edge_net_new_len--;
@@ -1616,7 +1631,7 @@ finally:
#endif
- for (unsigned int i = 0; i < edge_arr_len; i++) {
+ for (uint i = 0; i < edge_arr_len; i++) {
BM_elem_flag_disable(edge_arr[i], EDGE_NOT_IN_STACK);
BM_elem_flag_disable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
BM_elem_flag_disable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
index 72ae7695f0f..bf5cea59e30 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
@@ -32,10 +32,10 @@ bool BM_face_split_edgenet(
bool BM_face_split_edgenet_connect_islands(
BMesh *bm,
- BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len,
+ BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len,
bool use_partial_connect,
struct MemArena *arena,
- BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len)
+ BMEdge ***r_edge_net_new, uint *r_edge_net_new_len)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 6, 7, 8);
#endif /* __BMESH_POLYGON_EDGENET_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index d8d297c9298..4161fbe90fb 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -73,7 +73,7 @@ enum {
};
#define BM_ELEM_API_FLAG_ENABLE(element, f) { ((element)->head.api_flag |= (f)); } (void)0
-#define BM_ELEM_API_FLAG_DISABLE(element, f) { ((element)->head.api_flag &= (unsigned char)~(f)); } (void)0
+#define BM_ELEM_API_FLAG_DISABLE(element, f) { ((element)->head.api_flag &= (uchar)~(f)); } (void)0
#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f))
#define BM_ELEM_API_FLAG_CLEAR(element) { ((element)->head.api_flag = 0); } (void)0
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 7ca5640578a..f5c14304ea3 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -1515,16 +1515,30 @@ float BM_loop_calc_face_angle(const BMLoop *l)
*/
void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
{
- if (normal_tri_v3(r_normal,
- l->prev->v->co,
- l->v->co,
- l->next->v->co) != 0.0f)
- {
- /* pass */
+#define FEPSILON 1e-5f
+
+ /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line)
+ * from zero value, because it does not normalize both vectors before making crossproduct.
+ * Instead of adding two costly normalize computations, just check ourselves for colinear case. */
+ /* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */
+ float v1[3], v2[3], v_tmp[3];
+ sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(v2, l->next->v->co, l->v->co);
+
+ const float fac = (v2[0] == 0.0f) ? ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0];
+
+ mul_v3_v3fl(v_tmp, v2, fac);
+ sub_v3_v3(v_tmp, v1);
+ if (fac != 0.0f && !is_zero_v3(v1) && len_manhattan_v3(v_tmp) > FEPSILON) {
+ /* Not co-linear, we can compute crossproduct and normalize it into normal. */
+ cross_v3_v3v3(r_normal, v1, v2);
+ normalize_v3(r_normal);
}
else {
copy_v3_v3(r_normal, l->f->no);
}
+
+#undef FEPSILON
}
/**
@@ -2326,7 +2340,7 @@ static void bm_mesh_calc_volume_face(const BMFace *f, float *r_vol)
{
const int tottri = f->len - 2;
BMLoop **loops = BLI_array_alloca(loops, f->len);
- unsigned int (*index)[3] = BLI_array_alloca(index, tottri);
+ uint (*index)[3] = BLI_array_alloca(index, tottri);
int j;
BM_face_calc_tessellation(f, false, loops, index);
@@ -2395,8 +2409,8 @@ int BM_mesh_calc_face_groups(
int group_curr = 0;
- unsigned int tot_faces = 0;
- unsigned int tot_touch = 0;
+ uint tot_faces = 0;
+ uint tot_touch = 0;
BMFace **stack;
STACK_DECLARE(stack);
@@ -2553,8 +2567,8 @@ int BM_mesh_calc_edge_groups(
int group_curr = 0;
- unsigned int tot_edges = 0;
- unsigned int tot_touch = 0;
+ uint tot_edges = 0;
+ uint tot_touch = 0;
BMEdge **stack;
STACK_DECLARE(stack);
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index d5afb39d7b7..2ae87b64286 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -66,5 +66,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material, loop_slide);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "verts.out", BM_VERT, BM_ELEM_TAG);
}
}
diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c
index bed1ea5cb94..2c80ff651b8 100644
--- a/source/blender/bmesh/operators/bmo_bisect_plane.c
+++ b/source/blender/bmesh/operators/bmo_bisect_plane.c
@@ -38,7 +38,8 @@
#include "intern/bmesh_operators_private.h" /* own include */
#define ELE_NEW 1
-#define ELE_INPUT 2
+#define ELE_CUT 2
+#define ELE_INPUT 4
void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
{
@@ -69,7 +70,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
BM_mesh_bisect_plane(bm, plane, use_snap_center, true,
- ELE_NEW, dist);
+ ELE_CUT, ELE_NEW, dist);
if (clear_outer || clear_inner) {
@@ -108,5 +109,5 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
}
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_NEW);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_CUT);
}
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index 5c9cd8dc3fa..c5c4ac959a9 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -55,7 +55,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera
BMLoop *l_tag_prev = NULL, *l_tag_first = NULL;
BMLoop *l_iter, *l_first;
- unsigned int i;
+ uint i;
STACK_INIT(loops_split, pair_split_max);
STACK_INIT(verts_pair, pair_split_max);
diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
index b8acc9d09b8..67590fe8ef9 100644
--- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c
+++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
@@ -67,8 +67,8 @@ static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r
{
BMLoop *l_iter, *l_first;
BMLoop **l_arr = BLI_array_alloca(l_arr, f->len);
- const unsigned int f_len = f->len;
- unsigned int i_a, i_b;
+ const uint f_len = f->len;
+ uint i_a, i_b;
bool found = false;
/* angle finding */
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index a73c86fd122..b474ad9fc7b 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -530,8 +530,8 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
float basis_nor_b[3];
/* align normal to direction */
- project_plane_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir);
- project_plane_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir);
+ project_plane_normalized_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir);
+ project_plane_normalized_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir);
/* don't normalize before combining so as normals approach the direction, they have less effect (T46784). */
@@ -569,7 +569,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
float angle_cos_test;
/* project basis dir onto the normal to find its closest angle */
- project_plane_v3_v3v3(basis_dir_proj, basis_dir, l->f->no);
+ project_plane_normalized_v3_v3v3(basis_dir_proj, basis_dir, l->f->no);
if (normalize_v3(basis_dir_proj) > eps) {
angle_cos_test = dot_v3v3(basis_dir_proj, basis_dir);
@@ -586,7 +586,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
* note: we could add the directions,
* but this more often gives 45d rotated matrix, so just use the best one. */
copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor);
- project_plane_v3_v3v3(basis_nor, basis_nor, basis_dir);
+ project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir);
cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 6e3a8a1473d..2df8e73c2b8 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -309,7 +309,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
BMFace *f_pair[2];
if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
- unsigned int j;
+ uint j;
for (j = 0; j < 2; j++) {
BMLoop *l_first, *l_iter;
l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]);
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 8048add84d4..e35c1f3b66c 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -83,7 +83,7 @@ static BMEdge *bmo_edge_copy(
{
BMEdge *e_dst;
BMVert *e_dst_v1, *e_dst_v2;
- unsigned int rlen;
+ uint rlen;
/* see if any of the neighboring faces are
* not being duplicated. in that case,
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index 233ed746ed4..dcf2570dff4 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -91,7 +91,7 @@ static void bm_face_copy_shared_all(
/**
* Flood fill attributes.
*/
-static unsigned int bmesh_face_attribute_fill(
+static uint bmesh_face_attribute_fill(
BMesh *bm,
const bool use_normals, const bool use_data)
{
@@ -102,7 +102,7 @@ static unsigned int bmesh_face_attribute_fill(
BMIter iter;
BMLoop *l;
- unsigned int face_tot = 0;
+ uint face_tot = 0;
BLI_LINKSTACK_INIT(loop_queue_prev);
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 04ae915b707..dc4ebf50754 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -187,15 +187,15 @@ static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_
* 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,
+ const uint xtot, const uint 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;
+ uint i = 0;
float xy_fl[2];
- unsigned int x, y;
+ uint x, y;
for (y = 0; y < ytot; y++) {
xy_fl[1] = y_step * (float)y;
for (x = 0; x < xtot; x++) {
@@ -219,13 +219,13 @@ static void barycentric_weights_v2_grid_cache(
* \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 unsigned int xtot, unsigned const int ytot,
+ BMesh *bm, BMVert **v_grid, const uint xtot, unsigned const int ytot,
const short mat_nr, const bool use_smooth,
const bool use_flip, const bool use_interp_simple)
{
const bool use_vert_interp = CustomData_has_interp(&bm->vdata);
const bool use_loop_interp = CustomData_has_interp(&bm->ldata);
- unsigned int x, y;
+ uint x, y;
/* for use_loop_interp */
BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]);
@@ -393,7 +393,7 @@ static void bm_grid_fill_array(
BMLoop *l_quad[4];
BMLoop *l_bound[4];
BMLoop *l_tmp;
- unsigned int x_side, y_side, i;
+ uint x_side, y_side, i;
char interp_from;
@@ -496,12 +496,12 @@ static void bm_grid_fill(
{
#define USE_FLIP_DETECT
- 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);
+ const uint xtot = (uint)BM_edgeloop_length_get(estore_a);
+ const uint ytot = (uint)BM_edgeloop_length_get(estore_rail_a);
//BMVert *v;
- unsigned int i;
+ uint i;
#ifdef DEBUG
- unsigned int x, y;
+ uint x, y;
#endif
LinkData *el;
bool use_flip = false;
diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c
index eadfbdb1aa8..869994a98b9 100644
--- a/source/blender/bmesh/operators/bmo_fill_holes.c
+++ b/source/blender/bmesh/operators/bmo_fill_holes.c
@@ -36,7 +36,7 @@
void bmo_holes_fill_exec(BMesh *bm, BMOperator *op)
{
BMOperator op_attr;
- const unsigned int sides = BMO_slot_int_get(op->slots_in, "sides");
+ const uint sides = BMO_slot_int_get(op->slots_in, "sides");
BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index e2ff09669d7..a64c6d74a93 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -275,7 +275,7 @@ static void bmo_face_inset_individual(
BMLoop *l_iter, *l_first;
BMLoop *l_other;
- unsigned int i;
+ uint i;
float e_length_prev;
l_first = BM_FACE_FIRST_LOOP(f);
@@ -663,7 +663,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
/* run the separate arg */
if (!BM_edge_is_boundary(es->e_old)) {
- bmesh_edge_separate(bm, es->e_old, es->l, false);
+ bmesh_kernel_edge_separate(bm, es->e_old, es->l, false);
}
/* calc edge-split info */
@@ -742,7 +742,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
/* disable touching twice, this _will_ happen if the flags not disabled */
BM_elem_flag_disable(v, BM_ELEM_TAG);
- bmesh_vert_separate(bm, v, &vout, &r_vout_len, false);
+ bmesh_kernel_vert_separate(bm, v, &vout, &r_vout_len, false);
v = NULL; /* don't use again */
/* in some cases the edge doesn't split off */
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 655fb346976..69198ff35ab 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -132,11 +132,11 @@ struct DelimitData_CD {
};
struct DelimitData {
- unsigned int do_seam : 1;
- unsigned int do_sharp : 1;
- unsigned int do_mat : 1;
- unsigned int do_angle_face : 1;
- unsigned int do_angle_shape : 1;
+ uint do_seam : 1;
+ uint do_sharp : 1;
+ uint do_mat : 1;
+ uint do_angle_face : 1;
+ uint do_angle_shape : 1;
float angle_face;
float angle_face__cos;
@@ -272,7 +272,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
/* data: edge-to-join, sort_value: error weight */
struct SortPointerByFloat *jedges;
unsigned i, totedge;
- unsigned int totedge_tag = 0;
+ uint totedge_tag = 0;
struct DelimitData delimit_data = {0};
diff --git a/source/blender/bmesh/operators/bmo_offset_edgeloops.c b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
index 7a6f779b34f..a9840a72fc9 100644
--- a/source/blender/bmesh/operators/bmo_offset_edgeloops.c
+++ b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
@@ -270,7 +270,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
v_other = BM_edge_other_vert(e, v);
if (BM_elem_index_get(v_other) == -1) {
if (BM_vert_is_edge_pair(v_other)) {
- /* defer bmesh_jekv to avoid looping over data we're removing */
+ /* defer bmesh_kernel_join_edge_kill_vert to avoid looping over data we're removing */
v_other->e = e;
STACK_PUSH(varr, v_other);
}
@@ -278,7 +278,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
}
while ((v = STACK_POP(varr))) {
- bmesh_jekv(bm, v->e, v, true, false, false);
+ bmesh_kernel_join_edge_kill_vert(bm, v->e, v, true, false, false);
}
}
}
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 723e0b168e0..cca0f7387cd 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -760,11 +760,13 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
BMOpSlot *slot_verts_out = BMO_slot_get(op->slots_out, "verts.out");
const float dia = BMO_slot_float_get(op->slots_in, "size");
- const unsigned int xtot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments"));
- const unsigned int ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
+ const uint xtot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments"));
+ const uint ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
const float xtot_inv2 = 2.0f / (xtot - 1);
const float ytot_inv2 = 2.0f / (ytot - 1);
- const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert **varr;
BMVert *vquad[4];
@@ -772,7 +774,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
float mat[4][4];
float vec[3], tvec[3];
- unsigned int x, y, i;
+ uint x, y, i;
BMO_slot_mat4_get(op->slots_in, "matrix", mat);
@@ -814,7 +816,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
#undef XY
if (calc_uvs) {
- BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK);
+ BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK, cd_loop_uv_offset);
}
}
@@ -826,7 +828,9 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
* \param y_segments The y-resolution of the grid
* \param oflag The flag to check faces with.
*/
-void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag)
+void BM_mesh_calc_uvs_grid(
+ BMesh *bm, const uint x_segments, const uint y_segments,
+ const short oflag, const int cd_loop_uv_offset)
{
BMFace *f;
BMLoop *l;
@@ -837,8 +841,6 @@ void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsig
float x = 0.0f;
float y = 0.0f;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
int loop_index;
BLI_assert(cd_loop_uv_offset != -1);
@@ -884,7 +886,9 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
const float dia = BMO_slot_float_get(op->slots_in, "diameter");
const int seg = BMO_slot_int_get(op->slots_in, "u_segments");
const int tot = BMO_slot_int_get(op->slots_in, "v_segments");
- const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMOperator bmop, prevop;
BMVert *eve, *preveve;
@@ -982,7 +986,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
}
}
- BM_mesh_calc_uvs_sphere(bm, FACE_MARK);
+ BM_mesh_calc_uvs_sphere(bm, FACE_MARK, cd_loop_uv_offset);
}
/* and now do imat */
@@ -1000,7 +1004,9 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
const float dia = BMO_slot_float_get(op->slots_in, "diameter");
const float dia_div = dia / 200.0f;
const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions");
- const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert *eva[12];
BMVert *v;
@@ -1026,7 +1032,6 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
}
int uvi = 0;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
for (a = 0; a < 20; a++) {
BMFace *f;
BMVert *v1, *v2, *v3;
@@ -1157,13 +1162,13 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
* \param bm The BMesh to operate on
* \param oflag The flag to check faces with.
*/
-void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag)
+void BM_mesh_calc_uvs_sphere(
+ BMesh *bm,
+ const short oflag, const int cd_loop_uv_offset)
{
BMFace *f;
BMIter iter;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
@@ -1206,7 +1211,9 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
int i;
BMO_slot_mat4_get(op->slots_in, "matrix", mat);
- const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
for (i = 0; i < monkeynv; i++) {
float v[3];
@@ -1234,7 +1241,6 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
}
int uvi = 0;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
for (i = 0; i < monkeynf; i++) {
BMFace *f_new_a = BM_face_create_quad_tri(bm,
tv[monkeyf[i][0] + i - monkeyo],
@@ -1283,7 +1289,9 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
const int segs = BMO_slot_int_get(op->slots_in, "segments");
const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
- const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL;
float vec[3], mat[4][4], phi, phid;
@@ -1343,7 +1351,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
BMO_face_flag_enable(bm, f, FACE_NEW);
if (calc_uvs) {
- BM_mesh_calc_uvs_circle(bm, mat, dia, FACE_NEW);
+ BM_mesh_calc_uvs_circle(bm, mat, dia, FACE_NEW, cd_loop_uv_offset);
}
}
@@ -1362,14 +1370,14 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
* \param radius The size of the circle.
* \param oflag The flag to check faces with.
*/
-void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], const float radius, const short oflag)
+void BM_mesh_calc_uvs_circle(
+ BMesh *bm, float mat[4][4], const float radius,
+ const short oflag, const int cd_loop_uv_offset)
{
BMFace *f;
BMLoop *l;
BMIter fiter, liter;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
const float uv_scale = 0.5f / radius;
const float uv_center = 0.5f;
@@ -1409,7 +1417,9 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
int segs = BMO_slot_int_get(op->slots_in, "segments");
const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
- const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
int a;
if (!segs)
@@ -1506,7 +1516,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
}
if (calc_uvs) {
- BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK);
+ BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK, cd_loop_uv_offset);
}
if (!cap_tris) {
@@ -1530,12 +1540,12 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
*/
void BM_mesh_calc_uvs_cone(
BMesh *bm, float mat[4][4],
- const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag)
+ const float radius_top, const float radius_bottom, const int segments, const bool cap_ends,
+ const short oflag, const int cd_loop_uv_offset)
{
BMFace *f;
BMLoop *l;
BMIter fiter, liter;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const float uv_width = 1.0f / (float)segments;
const float uv_height = cap_ends ? 0.5f : 1.0f;
@@ -1566,7 +1576,7 @@ void BM_mesh_calc_uvs_cone(
BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for ensuring the mesh has UVs */
- x = 0.0f;
+ x = 1.0f;
y = 1.0f - uv_height;
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
@@ -1580,7 +1590,7 @@ void BM_mesh_calc_uvs_cone(
switch (loop_index) {
case 0:
- x += uv_width;
+ /* Continue in the last position */
break;
case 1:
y += uv_height;
@@ -1598,8 +1608,6 @@ void BM_mesh_calc_uvs_cone(
luv->uv[0] = x;
luv->uv[1] = y;
}
-
- x += uv_width;
}
else {
/* top or bottom face - so unwrap it by transforming back to a circle and using the X/Y coords */
@@ -1629,8 +1637,10 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
BMVert *verts[8];
float mat[4][4];
float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
- const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs");
- int i, x, y, z;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
/* rotation order set to match 'BM_mesh_calc_uvs_cube' */
const char faces[6][4] = {
{0, 1, 3, 2},
@@ -1644,11 +1654,11 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
BMO_slot_mat4_get(op->slots_in, "matrix", mat);
if (!off) off = 0.5f;
- i = 0;
+ int i = 0;
- for (x = -1; x < 2; x += 2) {
- for (y = -1; y < 2; y += 2) {
- for (z = -1; z < 2; z += 2) {
+ for (int x = -1; x < 2; x += 2) {
+ for (int y = -1; y < 2; y += 2) {
+ for (int z = -1; z < 2; z += 2) {
float vec[3] = {(float)x * off, (float)y * off, (float)z * off};
mul_m4_v3(mat, vec);
verts[i] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 0ad8247e539..7d19d90807a 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -153,7 +153,7 @@ static BMFace *remdoubles_createface(BMesh *bm, BMFace *f, BMOpSlot *slot_target
finally:
{
- unsigned int i;
+ uint i;
for (i = 0; i < STACK_SIZE(verts); i++) {
BMO_vert_flag_disable(bm, verts[i], VERT_IN_FACE);
}
@@ -165,7 +165,7 @@ finally:
BLI_assert(f_new != f);
if (f_new) {
- unsigned int i = 0;
+ uint i = 0;
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
do {
@@ -440,20 +440,24 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- float min[3], max[3], center[3];
+ float center[3];
+ int count = 0;
BMVert *v_tar;
+ zero_v3(center);
+
if (!BMO_edge_flag_test(bm, e, EDGE_MARK))
continue;
BLI_assert(BLI_stack_is_empty(edge_stack));
- INIT_MINMAX(min, max);
for (e = BMW_begin(&walker, e->v1); e; e = BMW_step(&walker)) {
BLI_stack_push(edge_stack, &e);
- minmax_v3v3_v3(min, max, e->v1->co);
- minmax_v3v3_v3(min, max, e->v2->co);
+ add_v3_v3(center, e->v1->co);
+ add_v3_v3(center, e->v2->co);
+
+ count += 2;
/* prevent adding to slot_targetmap multiple times */
BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
@@ -461,15 +465,14 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
}
if (!BLI_stack_is_empty(edge_stack)) {
-
- mid_v3_v3v3(center, min, max);
+ mul_v3_fl(center, 1.0f / count);
/* snap edges to a point. for initial testing purposes anyway */
e = *(BMEdge **)BLI_stack_peek(edge_stack);
v_tar = e->v1;
while (!BLI_stack_is_empty(edge_stack)) {
- unsigned int j;
+ uint j;
BLI_stack_pop(edge_stack, &e);
for (j = 0; j < 2; j++) {
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index 1a83bafc074..2a7b85ac8fd 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -172,7 +172,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
float w1, w2, w3, w4;
int i, j;
bool has_4_vert;
- unsigned int idv1, idv2, idv3, idv4, idv[4];
+ uint idv1, idv2, idv3, idv4, idv[4];
BMEdge *e;
BMFace *f;
BMIter eiter;
@@ -289,7 +289,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
float w2, w3, w4;
int i, j;
bool has_4_vert;
- unsigned int idv1, idv2, idv3, idv4, idv[4];
+ uint idv1, idv2, idv3, idv4, idv[4];
BMEdge *e;
BMFace *f;
@@ -420,7 +420,7 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez
float leni, lene;
float vini, vend;
float *vi1, *vi2, ve1[3], ve2[3];
- unsigned int idv1, idv2;
+ uint idv1, idv2;
BMOIter siter;
BMVert *v;
BMEdge *e;
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index ce031e1c230..94b60a51f68 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -66,7 +66,7 @@
/* Specialized Utility Funcs */
#ifndef NDEBUG
-static unsigned int bm_verts_tag_count(BMesh *bm)
+static uint bm_verts_tag_count(BMesh *bm)
{
int count = 0;
BMIter iter;
@@ -390,9 +390,9 @@ static void bm_vert_calc_surface_tangent(BMesh *bm, BMVert *v, float r_no[3])
* Tag faces connected to an edge loop as FACE_SHARED
* if all vertices are VERT_SHARED.
*/
-static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const unsigned int e_arr_len)
+static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const uint e_arr_len)
{
- unsigned int i;
+ uint i;
for (i = 0; i < e_arr_len; i++) {
BMEdge *e = e_arr[i];
@@ -412,9 +412,9 @@ static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const unsigned i
/**
* Un-Tag faces connected to an edge loop, clearing FACE_SHARED
*/
-static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const unsigned int e_arr_len_iter)
+static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const uint e_arr_len_iter)
{
- unsigned int i;
+ uint i;
for (i = 0; i < e_arr_len_iter; i++) {
BMEdge *e = e_arr_iter[i];
@@ -454,16 +454,16 @@ static LoopPairStore *bm_edgering_pair_store_create(
LoopPairStore *lpair = MEM_mallocN(sizeof(*lpair), __func__);
if (interp_mode == SUBD_RING_INTERP_SURF) {
- const unsigned int len_a = BM_edgeloop_length_get(el_store_a);
- const unsigned int len_b = BM_edgeloop_length_get(el_store_b);
- const unsigned int e_arr_a_len = len_a - (BM_edgeloop_is_closed(el_store_a) ? 0 : 1);
- const unsigned int e_arr_b_len = len_b - (BM_edgeloop_is_closed(el_store_b) ? 0 : 1);
+ const uint len_a = BM_edgeloop_length_get(el_store_a);
+ const uint len_b = BM_edgeloop_length_get(el_store_b);
+ const uint e_arr_a_len = len_a - (BM_edgeloop_is_closed(el_store_a) ? 0 : 1);
+ const uint e_arr_b_len = len_b - (BM_edgeloop_is_closed(el_store_b) ? 0 : 1);
BMEdge **e_arr_a = BLI_array_alloca(e_arr_a, e_arr_a_len);
BMEdge **e_arr_b = BLI_array_alloca(e_arr_b, e_arr_b_len);
- unsigned int i;
+ uint i;
struct BMEdgeLoopStore *el_store_pair[2] = {el_store_a, el_store_b};
- unsigned int side_index;
+ uint side_index;
float (*nors_pair[2])[3];
GHash *nors_gh_pair[2];
@@ -768,8 +768,8 @@ static void bm_edgering_pair_interpolate(
bm_vert_calc_surface_tangent(bm, v_b, no_b);
#else
{
- const unsigned int index_a = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_a, v_a));
- const unsigned int index_b = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_b, v_b));
+ const uint index_a = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_a, v_a));
+ const uint index_b = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_b, v_b));
BLI_assert(BLI_ghash_haskey(lpair->nors_gh_a, v_a));
BLI_assert(BLI_ghash_haskey(lpair->nors_gh_b, v_b));
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 6bd3174d27a..4e8bace59e0 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -77,7 +77,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
GHash *sf_vert_map;
float normal[3];
const int scanfill_flag = BLI_SCANFILL_CALC_HOLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_LOOSE;
- unsigned int nors_tot;
+ uint nors_tot;
bool calc_winding = false;
sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges"));
@@ -89,7 +89,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
ScanFillVert *sf_verts[2];
BMVert **e_verts = &e->v1;
- unsigned int i;
+ uint i;
BMO_edge_flag_enable(bm, e, EDGE_MARK);
@@ -115,7 +115,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
* Since we don't know winding, just accumulate */
ScanFillVert *sf_vert;
struct SortNormal *nors;
- unsigned int i;
+ uint i;
bool is_degenerate = true;
nors = MEM_mallocN(sizeof(*nors) * nors_tot, __func__);
@@ -124,7 +124,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
BMVert *v = sf_vert->tmp.p;
BMIter eiter;
BMEdge *e_pair[2];
- unsigned int e_index = 0;
+ uint e_index = 0;
nors[i].value = -1.0f;
@@ -199,7 +199,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
int winding_votes = 0;
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
BMVert *v_tri[3] = {sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p};
- unsigned int i, i_prev;
+ uint i, i_prev;
for (i = 0, i_prev = 2; i < 3; i_prev = i++) {
e = BM_edge_exists(v_tri[i], v_tri[i_prev]);
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 3e3a6547b75..f08f21a2c88 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -62,7 +62,7 @@ typedef struct EdRotState {
#if 0
/* use BLI_ghashutil_inthash_v4 direct */
-static unsigned int erot_gsetutil_hash(const void *ptr)
+static uint erot_gsetutil_hash(const void *ptr)
{
const EdRotState *e_state = (const EdRotState *)ptr;
return BLI_ghashutil_inthash_v4(&e_state->v1);
@@ -368,7 +368,7 @@ void BM_mesh_beautify_fill(
TIMEIT_START(beautify_fill);
#endif
- eheap = BLI_heap_new_ex((unsigned int)edge_array_len);
+ eheap = BLI_heap_new_ex((uint)edge_array_len);
eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__);
/* build heap */
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 05169a2a976..6673c5d25cf 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -205,6 +205,38 @@ static int bev_debug_flags = 0;
#define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2)
#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
+/* this flag values will get set on geom we want to return in 'out' slots for edges and verts */
+#define EDGE_OUT 4
+#define VERT_OUT 8
+
+/* If we're called from the modifier, tool flags aren't available, but don't need output geometry */
+static void flag_out_edge(BMesh *bm, BMEdge *bme)
+{
+ if (bm->use_toolflags)
+ BMO_edge_flag_enable(bm, bme, EDGE_OUT);
+}
+
+static void flag_out_vert(BMesh *bm, BMVert *bmv)
+{
+ if (bm->use_toolflags)
+ BMO_vert_flag_enable(bm, bmv, VERT_OUT);
+}
+
+static void disable_flag_out_edge(BMesh *bm, BMEdge *bme)
+{
+ if (bm->use_toolflags)
+ BMO_edge_flag_disable(bm, bme, EDGE_OUT);
+}
+
+/* Are d1 and d2 parallel or nearly so? */
+static bool nearly_parallel(const float d1[3], const float d2[3])
+{
+ float ang;
+
+ ang = angle_v3v3(d1, d2);
+ return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - M_PI) < BEVEL_EPSILON_ANG);
+}
+
/* Make a new BoundVert of the given kind, insert it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
@@ -253,6 +285,7 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
NewVert *nv = mesh_vert(vm, i, j, k);
nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP);
BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
+ flag_out_vert(bm, nv->v);
}
static void copy_mesh_vert(
@@ -495,9 +528,12 @@ static BMFace *bev_create_ngon(
}
/* not essential for bevels own internal logic,
- * this is done so the operator can select newly created faces */
+ * this is done so the operator can select newly created geometry */
if (f) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_ITER_ELEM(bme, &iter, f, BM_EDGES_OF_FACE) {
+ flag_out_edge(bm, bme);
+ }
}
if (mat_nr >= 0)
@@ -916,8 +952,12 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc
return false;
}
cross_v3_v3v3(fno, dir1, dir2);
- if (dot_v3v3(fno, v->no) < 0.0f)
+ if (dot_v3v3(fno, v->no) < 0.0f) {
ang = 2.0f * (float)M_PI - ang; /* angle is reflex */
+ if (r_angle)
+ *r_angle = ang;
+ return false;
+ }
if (r_angle)
*r_angle = ang;
@@ -1055,7 +1095,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
{
EdgeHalf *e;
Profile *pro;
- float co1[3], co2[3], co3[3], d1[3], d2[3], l;
+ float co1[3], co2[3], co3[3], d1[3], d2[3];
bool do_linear_interp;
copy_v3_v3(co1, bndv->nv.co);
@@ -1093,8 +1133,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
normalize_v3(d1);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
- l = normalize_v3(pro->plane_no);
- if (l <= BEVEL_EPSILON_BIG) {
+ normalize_v3(pro->plane_no);
+ if (nearly_parallel(d1, d2)) {
/* co1 - midco -co2 are collinear.
* Should be case that beveled edge is coplanar with two boundary verts.
* We want to move the profile to that common plane, if possible.
@@ -1126,17 +1166,24 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
sub_v3_v3v3(d4, e->next->e->v1->co, e->next->e->v2->co);
normalize_v3(d3);
normalize_v3(d4);
- add_v3_v3v3(co3, co1, d3);
- add_v3_v3v3(co4, co2, d4);
- isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
- if (isect_kind != 0) {
- copy_v3_v3(pro->midco, meetco);
- }
- else {
+ if (nearly_parallel(d3, d4)) {
/* offset lines are collinear - want linear interpolation */
mid_v3_v3v3(pro->midco, co1, co2);
do_linear_interp = true;
}
+ else {
+ add_v3_v3v3(co3, co1, d3);
+ add_v3_v3v3(co4, co2, d4);
+ isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
+ if (isect_kind != 0) {
+ copy_v3_v3(pro->midco, meetco);
+ }
+ else {
+ /* offset lines don't intersect - want linear interpolation */
+ mid_v3_v3v3(pro->midco, co1, co2);
+ do_linear_interp = true;
+ }
+ }
}
}
copy_v3_v3(pro->cob, co2);
@@ -1145,8 +1192,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
sub_v3_v3v3(d2, pro->midco, co2);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
- l = normalize_v3(pro->plane_no);
- if (l <= BEVEL_EPSILON_BIG) {
+ normalize_v3(pro->plane_no);
+ if (nearly_parallel(d1, d2)) {
/* whole profile is collinear with edge: just interpolate */
do_linear_interp = true;
}
@@ -2295,7 +2342,7 @@ static int interp_range(const float *frac, int n, const float f, float *r_rest)
/* Interpolate given vmesh to make one with target nseg border vertices on the profiles */
static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm0, int nseg)
{
- int n, ns0, nseg2, odd, i, j, k, j0, k0, k0prev;
+ int n, ns0, nseg2, odd, i, j, k, j0, k0, k0prev, j0inc, k0inc;
float *prev_frac, *frac, *new_frac, *prev_new_frac;
float f, restj, restk, restkprev;
float quad[4][3], co[3], center[3];
@@ -2339,10 +2386,12 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm0, int nseg)
copy_v3_v3(co, mesh_vert_canon(vm0, i, j0, k0)->co);
}
else {
+ j0inc = (restj < BEVEL_EPSILON || j0 == ns0) ? 0 : 1;
+ k0inc = (restk < BEVEL_EPSILON || k0 == ns0) ? 0 : 1;
copy_v3_v3(quad[0], mesh_vert_canon(vm0, i, j0, k0)->co);
- copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + 1)->co);
- copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + 1, k0 + 1)->co);
- copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + 1, k0)->co);
+ copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + k0inc)->co);
+ copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + j0inc, k0 + k0inc)->co);
+ copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + j0inc, k0)->co);
interp_bilinear_quad_v3(quad, restk, restj, co);
}
copy_v3_v3(mesh_vert(vm1, i, j, k)->co, co);
@@ -3191,6 +3240,7 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
BMFace *f_new;
BLI_assert(v_fan == l_fan->v);
f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false);
+ flag_out_edge(bm, l_new->e);
if (f_new->len > f->len) {
f = f_new;
@@ -3237,6 +3287,7 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv)
else {
BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
f = l_new->f;
+ flag_out_edge(bm, l_new->e);
/* walk around the new face to get the next verts to split */
l_a = l_new->prev;
@@ -3256,7 +3307,7 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
{
VMesh *vm = bv->vmesh;
BMVert *v1, *v2;
- BMEdge *e_eg;
+ BMEdge *e_eg, *bme;
Profile *pro;
float co[3];
BoundVert *bndv;
@@ -3298,7 +3349,9 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
v1 = mesh_vert(vm, 0, 0, k)->v;
v2 = mesh_vert(vm, 0, 0, k + 1)->v;
BLI_assert(v1 != NULL && v2 != NULL);
- BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+ bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+ if (bme)
+ flag_out_edge(bm, bme);
}
}
}
@@ -3879,7 +3932,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
/* Face f has at least one beveled vertex. Rebuild f */
static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
{
- BMIter liter;
+ BMIter liter, eiter, fiter;
BMLoop *l, *lprev;
BevVert *bv;
BoundVert *v, *vstart, *vend;
@@ -3887,10 +3940,10 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
VMesh *vm;
int i, k, n;
bool do_rebuild = false;
- bool go_ccw, corner3special;
+ bool go_ccw, corner3special, keep;
BMVert *bmv;
BMEdge *bme, *bme_new, *bme_prev;
- BMFace *f_new;
+ BMFace *f_new, *f_other;
BMVert **vv = NULL;
BMVert **vv_fix = NULL;
BMEdge **ee = NULL;
@@ -4028,9 +4081,21 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
}
}
- /* don't select newly created boundary faces... */
+ /* don't select newly or return created boundary faces... */
if (f_new) {
BM_elem_flag_disable(f_new, BM_ELEM_TAG);
+ /* Also don't want new edges that aren't part of a new bevel face */
+ BM_ITER_ELEM(bme, &eiter, f_new, BM_EDGES_OF_FACE) {
+ keep = false;
+ BM_ITER_ELEM(f_other, &fiter, bme, BM_FACES_OF_EDGE) {
+ if (BM_elem_flag_test(f_other, BM_ELEM_TAG)) {
+ keep = true;
+ break;
+ }
+ }
+ if (!keep)
+ disable_flag_out_edge(bm, bme);
+ }
}
}
@@ -4112,8 +4177,9 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
}
}
} while ((bndv = bndv->next) != bv->vmesh->boundstart);
- if (vclosest)
+ if (vclosest) {
BM_edge_create(bm, vclosest, votherclosest, e, BM_CREATE_NO_DOUBLE);
+ }
}
}
@@ -4517,9 +4583,9 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
/**
* - Currently only bevels BM_ELEM_TAG'd verts and edges.
*
- * - Newly created faces are BM_ELEM_TAG'd too,
- * the caller needs to ensure this is cleared before calling
- * if its going to use this face tag.
+ * - Newly created faces, edges, and verts are BM_ELEM_TAG'd too,
+ * the caller needs to ensure these are cleared before calling
+ * if its going to use this tag.
*
* - If limit_offset is set, adjusts offset down if necessary
* to avoid geometry collisions.
@@ -4611,6 +4677,20 @@ void BM_mesh_bevel(
}
}
+ /* When called from operator (as opposed to modifier), bm->use_toolflags
+ * will be set, and we to transfer the oflags to BM_ELEM_TAGs */
+ if (bm->use_toolflags) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, VERT_OUT))
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, EDGE_OUT)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
+ }
+
/* primary free */
BLI_ghash_free(bp.vert_hash, NULL, NULL);
BLI_memarena_free(bp.mem_arena);
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index 51b92a3c45e..676a8de94c8 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -74,7 +74,7 @@ static short plane_point_test_v3(const float plane[4], const float co[3], const
#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])))
+ (*((uint *)(&(v)->no[2])))
/**
* Hide flag access
@@ -110,10 +110,10 @@ static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v)
}
-static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center)
+static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new)
{
/* unlikely more than 2 verts are needed */
- const unsigned int f_len_orig = (unsigned int)f->len;
+ const uint f_len_orig = (uint)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;
@@ -154,10 +154,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
/* common case, just cut the face once */
BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true);
if (l_new) {
- if (oflag_center) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center);
- BMO_face_flag_enable(bm, l_new->f, oflag_center);
- BMO_face_flag_enable(bm, f, oflag_center);
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
}
}
}
@@ -170,7 +171,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
STACK_DECLARE(face_split_arr);
float sort_dir[3];
- unsigned int i;
+ uint i;
/* ---- */
@@ -245,7 +246,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
if (is_inside) {
BMLoop *l_a, *l_b;
bool found = false;
- unsigned int j;
+ uint j;
for (j = 0; j < STACK_SIZE(face_split_arr); j++) {
/* would be nice to avoid loop lookup here,
@@ -269,10 +270,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true);
if (l_new) {
- if (oflag_center) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center);
- BMO_face_flag_enable(bm, l_new->f, oflag_center);
- BMO_face_flag_enable(bm, face_split_arr[j], oflag_center);
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
}
}
@@ -307,10 +309,10 @@ finally:
void BM_mesh_bisect_plane(
BMesh *bm, const float plane[4],
const bool use_snap_center, const bool use_tag,
- const short oflag_center, const float eps)
+ const short oflag_center, const short oflag_new, const float eps)
{
- unsigned int einput_len;
- unsigned int i;
+ uint einput_len;
+ uint i;
BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__);
BLI_LINKSTACK_DECLARE(face_stack, BMFace *);
@@ -343,7 +345,7 @@ void BM_mesh_bisect_plane(
}
else {
BMEdge *e;
- einput_len = (unsigned int)bm->totedge;
+ einput_len = (uint)bm->totedge;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
edge_is_cut_enable(e);
edges_arr[i] = e;
@@ -390,7 +392,7 @@ void BM_mesh_bisect_plane(
const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)};
if (side[0] && side[1] && (side[0] != side[1])) {
- const float e_fac = fabsf(dist[0]) / fabsf(dist[0] - dist[1]);
+ const float e_fac = dist[0] / (dist[0] - dist[1]);
BMVert *v_new;
if (e->l) {
@@ -404,10 +406,17 @@ void BM_mesh_bisect_plane(
} while ((l_iter = l_iter->radial_next) != l_first);
}
- v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac);
+ {
+ BMEdge *e_new;
+ v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac);
+ if (oflag_new) {
+ BMO_edge_flag_enable(bm, e_new, oflag_new);
+ }
+ }
+
vert_is_center_enable(v_new);
- if (oflag_center) {
- BMO_vert_flag_enable(bm, v_new, oflag_center);
+ if (oflag_new | oflag_center) {
+ BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center);
}
BM_VERT_DIR(v_new) = 0;
@@ -416,7 +425,7 @@ void BM_mesh_bisect_plane(
else if (side[0] == 0 || side[1] == 0) {
/* check if either edge verts are aligned,
* if so - tag and push all faces that use it into the stack */
- unsigned int j;
+ uint j;
BM_ITER_ELEM_INDEX (v, &iter, e, BM_VERTS_OF_EDGE, j) {
if (side[j] == 0) {
if (vert_is_center_test(v) == 0) {
@@ -448,7 +457,7 @@ void BM_mesh_bisect_plane(
MEM_freeN(edges_arr);
while ((f = BLI_LINKSTACK_POP(face_stack))) {
- bm_face_bisect_verts(bm, f, plane, oflag_center);
+ bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new);
}
/* now we have all faces to split in the stack */
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h
index 7f3a97c4c79..fb99a1c8214 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.h
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h
@@ -30,6 +30,6 @@
void BM_mesh_bisect_plane(
BMesh *bm, const float plane[4],
const bool use_snap_center, const bool use_tag,
- const short oflag_center, const float eps);
+ const short oflag_center, const short oflag_new, const float eps);
#endif /* __BMESH_BISECT_PLANE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 372d341f223..c417131d588 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -180,7 +180,7 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_
{
BMIter liter;
BMLoop *l;
- unsigned int i;
+ uint i;
for (i = 0; i < 2; i++) {
/* loop over both verts */
@@ -367,7 +367,7 @@ static void bm_decim_build_edge_cost(
{
BMIter iter;
BMEdge *e;
- unsigned int i;
+ uint i;
BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
eheap_table[i] = NULL; /* keep sanity check happy */
@@ -418,12 +418,12 @@ static bool bm_edge_symmetry_check_cb(void *user_data, int index, const float UN
return false;
}
-static int *bm_edge_symmetry_map(BMesh *bm, unsigned int symmetry_axis, float limit)
+static int *bm_edge_symmetry_map(BMesh *bm, uint symmetry_axis, float limit)
{
struct KD_Symmetry_Data sym_data;
BMIter iter;
BMEdge *e, **etable;
- unsigned int i;
+ uint i;
int *edge_symmetry_map;
const float limit_sq = SQUARE(limit);
KDTree *tree;
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index 92300ae66a2..f0ac6c673c9 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -43,10 +43,10 @@ static bool bm_vert_dissolve_fan_test(BMVert *v)
BMVert *varr[4];
- unsigned int tot_edge = 0;
- unsigned int tot_edge_boundary = 0;
- unsigned int tot_edge_manifold = 0;
- unsigned int tot_edge_wire = 0;
+ uint tot_edge = 0;
+ uint tot_edge_boundary = 0;
+ uint tot_edge_manifold = 0;
+ uint tot_edge_wire = 0;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
if (BM_edge_is_boundary(e)) {
@@ -97,11 +97,11 @@ static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
BMIter iter;
BMEdge *e;
- unsigned int tot_loop = 0;
- unsigned int tot_edge = 0;
- unsigned int tot_edge_boundary = 0;
- unsigned int tot_edge_manifold = 0;
- unsigned int tot_edge_wire = 0;
+ uint tot_loop = 0;
+ uint tot_edge = 0;
+ uint tot_edge_boundary = 0;
+ uint tot_edge_manifold = 0;
+ uint tot_edge_wire = 0;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
if (BM_edge_is_boundary(e)) {
@@ -143,7 +143,7 @@ static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
if (tot_loop) {
BMLoop *f_loop[4];
- unsigned int i;
+ uint i;
/* ensure there are exactly tot_loop loops */
BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL);
@@ -192,8 +192,8 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
BMIter iter;
- const unsigned int offset = 0;
- const unsigned int nth = 2;
+ const uint offset = 0;
+ const uint nth = 2;
int iter_step;
@@ -229,8 +229,8 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
#ifdef USE_WALKER
BMWalker walker;
#else
- unsigned int depth = 1;
- unsigned int i;
+ uint depth = 1;
+ uint i;
#endif
BMVert *v_first = NULL;
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index 2a1946df7ae..193a032b46e 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -100,13 +100,13 @@ static BMEdge *bm_edgenet_edge_get_next(
*
* This function returns half a loop, the caller needs to run twice to get both sides.
*/
-static unsigned int bm_edgenet_path_from_pass(
+static uint 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;
+ uint v_ls_tot = 0;
do {
BLI_linklist_prepend_pool(v_ls, v, path_pool);
@@ -127,10 +127,10 @@ static bool bm_edgenet_path_check_overlap(
VertNetInfo *vnet_info)
{
/* vert order doesn't matter */
- unsigned int v_ls_tot = 0;
+ uint v_ls_tot = 0;
LinkNode *v_ls = NULL;
BMVert *v_pair[2] = {v1, v2};
- unsigned int i;
+ uint i;
for (i = 0; i < 2; i++) {
BMVert *v = v_pair[i];
@@ -162,7 +162,7 @@ static bool bm_edgenet_path_check_overlap(
* Create a face from the path.
*/
static BMFace *bm_edgenet_face_from_path(
- BMesh *bm, LinkNode *path, const unsigned int path_len)
+ BMesh *bm, LinkNode *path, const uint path_len)
{
BMFace *f;
LinkNode *v_lnk;
@@ -205,8 +205,8 @@ static BMEdge *bm_edgenet_path_step(
BMEdge *e;
BMIter iter;
- unsigned int tot;
- unsigned int v_ls_tot;
+ uint tot;
+ uint v_ls_tot;
begin:
@@ -277,8 +277,8 @@ begin:
* \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,
+ BMEdge *e, const int pass_nr, const uint path_cost_max,
+ uint *r_path_len, uint *r_path_cost,
VertNetInfo *vnet_info, BLI_mempool *path_pool)
{
VertNetInfo *vn_1, *vn_2;
@@ -288,7 +288,7 @@ static LinkNode *bm_edgenet_path_calc(
LinkNode *v_ls_prev = NULL;
LinkNode *v_ls_next = NULL;
- unsigned int path_cost_accum = 0;
+ uint path_cost_accum = 0;
BLI_assert(bm_edge_step_ok(e));
@@ -331,7 +331,7 @@ static LinkNode *bm_edgenet_path_calc(
if (e_found) {
LinkNode *path = NULL;
- unsigned int path_len;
+ uint path_len;
BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
@@ -376,12 +376,12 @@ static LinkNode *bm_edgenet_path_calc(
* _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,
+ BMEdge *e, int *pass_nr, uint path_cost_max,
+ uint *r_path_len, uint *r_path_cost,
VertNetInfo *vnet_info, BLI_mempool *path_pool)
{
LinkNode *path;
- unsigned int path_cost;
+ uint path_cost;
path = bm_edgenet_path_calc(e, *pass_nr, path_cost_max,
r_path_len, &path_cost,
@@ -399,8 +399,8 @@ static LinkNode *bm_edgenet_path_calc_best(
/* 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;
+ const uint path_len = *r_path_len;
+ uint i, i_prev;
BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
LinkNode *v_lnk;
@@ -413,8 +413,8 @@ static LinkNode *bm_edgenet_path_calc_best(
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;
+ uint path_len_test;
+ uint path_cost_test;
path_test = bm_edgenet_path_calc(e_other, *pass_nr, path_cost,
&path_len_test, &path_cost_test,
@@ -471,8 +471,8 @@ void BM_mesh_edgenet(
while (true) {
LinkNode *path = NULL;
- unsigned int path_len;
- unsigned int path_cost;
+ uint path_len;
+ uint path_cost;
e = bm_edgenet_edge_get_next(bm, &edge_queue, edge_queue_pool);
if (e == NULL) {
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
index a59a5c43c82..3a844a0b8d9 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.c
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -96,7 +96,7 @@ void BM_mesh_edgesplit(
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- unsigned int i;
+ uint i;
for (i = 0; i < 2; i++) {
BMVert *v = ((&e->v1)[i]);
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 2cb82d0fc02..b9408492cc1 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -152,7 +152,7 @@ struct ISectState {
*/
struct LinkBase {
LinkNode *list;
- unsigned int list_len;
+ uint list_len;
};
static bool ghash_insert_link(
@@ -193,7 +193,7 @@ struct vert_sort_t {
static void edge_verts_sort(const float co[3], struct LinkBase *v_ls_base)
{
/* not optimal but list will be typically < 5 */
- unsigned int i;
+ uint i;
struct vert_sort_t *vert_sort = BLI_array_alloca(vert_sort, v_ls_base->list_len);
LinkNode *node;
@@ -246,8 +246,8 @@ static void face_edges_split(
bool use_island_connect,
MemArena *mem_arena_edgenet)
{
- unsigned int i;
- unsigned int edge_arr_len = e_ls_base->list_len;
+ uint i;
+ uint edge_arr_len = e_ls_base->list_len;
BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
LinkNode *node;
BLI_assert(f->head.htype == BM_FACE);
@@ -263,7 +263,7 @@ static void face_edges_split(
#ifdef USE_NET_ISLAND_CONNECT
if (use_island_connect) {
- unsigned int edge_arr_holes_len;
+ uint edge_arr_holes_len;
BMEdge **edge_arr_holes;
if (BM_face_split_edgenet_connect_islands(
bm, f,
@@ -305,14 +305,14 @@ static enum ISectType intersect_line_tri(
const struct ISectEpsilon *e)
{
float p_dir[3];
- unsigned int i_t0;
+ uint i_t0;
float fac;
sub_v3_v3v3(p_dir, p0, p1);
normalize_v3(p_dir);
for (i_t0 = 0; i_t0 < 3; i_t0++) {
- const unsigned int i_t1 = (i_t0 + 1) % 3;
+ const uint i_t1 = (i_t0 + 1) % 3;
float te_dir[3];
sub_v3_v3v3(te_dir, t_cos[i_t0], t_cos[i_t1]);
@@ -375,7 +375,7 @@ static BMVert *bm_isect_edge_tri(
{
BMesh *bm = s->bm;
int k_arr[IX_TOT][4];
- unsigned int i;
+ uint i;
const int ti[3] = {UNPACK3_EX(BM_elem_index_get, t, )};
float ix[3];
@@ -470,7 +470,7 @@ static BMVert *bm_isect_edge_tri(
}
if ((*r_side >= IX_EDGE_TRI_EDGE0) && (*r_side <= IX_EDGE_TRI_EDGE2)) {
- i = (unsigned int)(*r_side - IX_EDGE_TRI_EDGE0);
+ i = (uint)(*r_side - IX_EDGE_TRI_EDGE0);
e = BM_edge_exists(t[i], t[(i + 1) % 3]);
if (e) {
edge_verts_add(s, e, iv, false);
@@ -537,7 +537,7 @@ static void bm_isect_tri_tri(
const float *f_b_cos[3] = {UNPACK3_EX(, fv_b, ->co)};
float f_a_nor[3];
float f_b_nor[3];
- unsigned int i;
+ uint i;
/* should be enough but may need to bump */
@@ -578,9 +578,9 @@ static void bm_isect_tri_tri(
/* first check in any verts are touching
* (any case where we wont create new verts)
*/
- unsigned int i_a;
+ uint i_a;
for (i_a = 0; i_a < 3; i_a++) {
- unsigned int i_b;
+ uint i_b;
for (i_b = 0; i_b < 3; i_b++) {
if (len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
#ifdef USE_DUMP
@@ -603,12 +603,12 @@ static void bm_isect_tri_tri(
/* vert-edge
* --------- */
{
- unsigned int i_a;
+ uint i_a;
for (i_a = 0; i_a < 3; i_a++) {
if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT_A) == 0) {
- unsigned int i_b_e0;
+ uint i_b_e0;
for (i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
- unsigned int i_b_e1 = (i_b_e0 + 1) % 3;
+ uint i_b_e1 = (i_b_e0 + 1) % 3;
if (BM_ELEM_API_FLAG_TEST(fv_b[i_b_e0], VERT_VISIT_B) ||
BM_ELEM_API_FLAG_TEST(fv_b[i_b_e1], VERT_VISIT_B))
@@ -644,12 +644,12 @@ static void bm_isect_tri_tri(
}
{
- unsigned int i_b;
+ uint i_b;
for (i_b = 0; i_b < 3; i_b++) {
if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT_B) == 0) {
- unsigned int i_a_e0;
+ uint i_a_e0;
for (i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
- unsigned int i_a_e1 = (i_a_e0 + 1) % 3;
+ uint i_a_e1 = (i_a_e0 + 1) % 3;
if (BM_ELEM_API_FLAG_TEST(fv_a[i_a_e0], VERT_VISIT_A) ||
BM_ELEM_API_FLAG_TEST(fv_a[i_a_e1], VERT_VISIT_A))
@@ -689,7 +689,7 @@ static void bm_isect_tri_tri(
{
float t_scale[3][3];
- unsigned int i_a;
+ uint i_a;
copy_v3_v3(t_scale[0], fv_b[0]->co);
copy_v3_v3(t_scale[1], fv_b[1]->co);
@@ -717,7 +717,7 @@ static void bm_isect_tri_tri(
{
float t_scale[3][3];
- unsigned int i_b;
+ uint i_b;
copy_v3_v3(t_scale[0], fv_a[0]->co);
copy_v3_v3(t_scale[1], fv_a[1]->co);
@@ -757,8 +757,8 @@ static void bm_isect_tri_tri(
/* edge-tri & edge-edge
* -------------------- */
{
- for (unsigned int i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
- unsigned int i_a_e1 = (i_a_e0 + 1) % 3;
+ for (uint i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
+ uint i_a_e1 = (i_a_e0 + 1) % 3;
enum ISectType side;
BMVert *iv;
@@ -778,8 +778,8 @@ static void bm_isect_tri_tri(
}
}
- for (unsigned int i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
- unsigned int i_b_e1 = (i_b_e0 + 1) % 3;
+ for (uint i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
+ uint i_b_e1 = (i_b_e0 + 1) % 3;
enum ISectType side;
BMVert *iv;
@@ -956,7 +956,7 @@ static int isect_bvhtree_point_v3(
const float *depth_arr = z_buffer.data;
float depth_last = depth_arr[0];
- for (unsigned int i = 1; i < z_buffer.count; i++) {
+ for (uint i = 1; i < z_buffer.count; i++) {
if (depth_arr[i] - depth_last > eps) {
depth_last = depth_arr[i];
num_isect++;
@@ -1000,7 +1000,7 @@ bool BM_mesh_intersect(
#ifdef USE_BVH
BVHTree *tree_a, *tree_b;
- unsigned int tree_overlap_tot;
+ uint tree_overlap_tot;
BVHTreeOverlap *overlap;
#else
int i_a, i_b;
@@ -1117,7 +1117,7 @@ bool BM_mesh_intersect(
overlap = BLI_bvhtree_overlap(tree_b, tree_a, &tree_overlap_tot, NULL, NULL);
if (overlap) {
- unsigned int i;
+ uint i;
for (i = 0; i < tree_overlap_tot; i++) {
#ifdef USE_DUMP
@@ -1390,7 +1390,7 @@ bool BM_mesh_intersect(
GHASH_ITER (gh_iter, s.face_edges) {
struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
LinkNode **node_prev_p;
- unsigned int i;
+ uint i;
node_prev_p = &e_ls_base->list;
for (i = 0, node = e_ls_base->list; node; i++, node = node->next) {
@@ -1455,7 +1455,7 @@ bool BM_mesh_intersect(
}
{
- unsigned int i;
+ uint i;
for (i = 0; i < STACK_SIZE(splice_ls); i++) {
if (!BLI_gset_haskey(verts_invalid, splice_ls[i][0]) &&
!BLI_gset_haskey(verts_invalid, splice_ls[i][1]))
@@ -1610,7 +1610,7 @@ bool BM_mesh_intersect(
#ifdef USE_BOOLEAN_RAYCAST_DRAW
{
- unsigned int colors[4] = {0x00000000, 0xffffffff, 0xff000000, 0x0000ff};
+ uint colors[4] = {0x00000000, 0xffffffff, 0xff000000, 0x0000ff};
float co_other[3] = {UNPACK3(co)};
co_other[0] += 1000.0f;
bl_debug_color_set(colors[(hits & 1) == 1]);
diff --git a/source/blender/bmesh/tools/bmesh_path.h b/source/blender/bmesh/tools/bmesh_path.h
index b6de5e0e4e0..fbdd2296121 100644
--- a/source/blender/bmesh/tools/bmesh_path.h
+++ b/source/blender/bmesh/tools/bmesh_path.h
@@ -28,8 +28,8 @@
*/
struct BMCalcPathParams {
- unsigned int use_topology_distance : 1;
- unsigned int use_step_face : 1;
+ uint use_topology_distance : 1;
+ uint use_step_face : 1;
};
struct LinkNode *BM_mesh_calc_path_vert(
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index a6860a6614a..2abf8f2c46e 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -114,7 +114,7 @@ typedef struct UUIDWalk {
GHash *faces_from_uuid; /* UUID -> UUIDFaceStepItem */
UUID_Int *rehash_store;
- unsigned int rehash_store_len;
+ uint rehash_store_len;
} cache;
} UUIDWalk;
@@ -136,7 +136,7 @@ typedef struct UUIDFaceStepItem {
uintptr_t uuid;
LinkNode *list;
- unsigned int list_len;
+ uint list_len;
} UUIDFaceStepItem;
BLI_INLINE bool bm_uuidwalk_face_test(
@@ -178,10 +178,10 @@ BLI_INLINE bool bm_uuidwalk_face_lookup(
}
}
-static unsigned int ghashutil_bmelem_indexhash(const void *key)
+static uint ghashutil_bmelem_indexhash(const void *key)
{
const BMElem *ele = key;
- return (unsigned int)BM_elem_index_get(ele);
+ return (uint)BM_elem_index_get(ele);
}
static bool ghashutil_bmelem_indexcmp(const void *a, const void *b)
@@ -192,14 +192,14 @@ static bool ghashutil_bmelem_indexcmp(const void *a, const void *b)
static GHash *ghash_bmelem_new_ex(
const char *info,
- const unsigned int nentries_reserve)
+ const uint nentries_reserve)
{
return BLI_ghash_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
}
static GSet *gset_bmelem_new_ex(
const char *info,
- const unsigned int nentries_reserve)
+ const uint nentries_reserve)
{
return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
}
@@ -218,8 +218,8 @@ static GSet *gset_bmelem_new(const char *info)
static void bm_uuidwalk_init(
UUIDWalk *uuidwalk,
- const unsigned int faces_src_region_len,
- const unsigned int verts_src_region_len)
+ const uint faces_src_region_len,
+ const uint verts_src_region_len)
{
BLI_listbase_clear(&uuidwalk->faces_step);
@@ -307,7 +307,7 @@ static UUID_Int bm_uuidwalk_calc_vert_uuid(
/* vert -> other */
{
- unsigned int tot = 0;
+ uint tot = 0;
BMIter eiter;
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
@@ -323,7 +323,7 @@ static UUID_Int bm_uuidwalk_calc_vert_uuid(
/* faces */
{
- unsigned int tot = 0;
+ uint tot = 0;
BMIter iter;
BMFace *f;
@@ -357,7 +357,7 @@ static UUID_Int bm_uuidwalk_calc_face_uuid(
UUID_Int uuid;
- uuid = uuidwalk->pass * (unsigned int)f->len * PRIME_FACE_LARGE;
+ uuid = uuidwalk->pass * (uint)f->len * PRIME_FACE_LARGE;
/* face-verts */
{
@@ -399,7 +399,7 @@ static UUID_Int bm_uuidwalk_calc_face_uuid(
}
static void bm_uuidwalk_rehash_reserve(
- UUIDWalk *uuidwalk, unsigned int rehash_store_len_new)
+ UUIDWalk *uuidwalk, uint rehash_store_len_new)
{
if (UNLIKELY(rehash_store_len_new > uuidwalk->cache.rehash_store_len)) {
/* avoid re-allocs */
@@ -419,9 +419,9 @@ static void bm_uuidwalk_rehash(
{
GHashIterator gh_iter;
UUID_Int *uuid_store;
- unsigned int i;
+ uint i;
- unsigned int rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid),
+ uint rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid),
BLI_ghash_size(uuidwalk->faces_uuid));
bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new);
@@ -454,12 +454,12 @@ static void bm_uuidwalk_rehash(
static void bm_uuidwalk_rehash_facelinks(
UUIDWalk *uuidwalk,
- LinkNode *faces, const unsigned int faces_len,
+ LinkNode *faces, const uint faces_len,
const bool is_init)
{
UUID_Int *uuid_store;
LinkNode *f_link;
- unsigned int i;
+ uint i;
bm_uuidwalk_rehash_reserve(uuidwalk, faces_len);
uuid_store = uuidwalk->cache.rehash_store;
@@ -502,7 +502,7 @@ static bool bm_vert_is_uuid_connect(
}
static void bm_uuidwalk_pass_add(
- UUIDWalk *uuidwalk, LinkNode *faces_pass, const unsigned int faces_pass_len)
+ UUIDWalk *uuidwalk, LinkNode *faces_pass, const uint faces_pass_len)
{
GHashIterator gh_iter;
GHash *verts_uuid_pass;
@@ -511,7 +511,7 @@ static void bm_uuidwalk_pass_add(
UUIDFaceStep *fstep;
- BLI_assert(faces_pass_len == (unsigned int)BLI_linklist_count(faces_pass));
+ BLI_assert(faces_pass_len == (uint)BLI_linklist_count(faces_pass));
/* rehash faces now all their verts have been added */
bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, true);
@@ -588,13 +588,13 @@ static int bm_face_len_cmp(const void *v1, const void *v2)
else return 0;
}
-static unsigned int bm_uuidwalk_init_from_edge(
+static uint bm_uuidwalk_init_from_edge(
UUIDWalk *uuidwalk, BMEdge *e)
{
BMLoop *l_iter = e->l;
- unsigned int f_arr_len = (unsigned int)BM_edge_face_count(e);
+ uint f_arr_len = (uint)BM_edge_face_count(e);
BMFace **f_arr = BLI_array_alloca(f_arr, f_arr_len);
- unsigned int fstep_num = 0, i = 0;
+ uint fstep_num = 0, i = 0;
do {
BMFace *f = l_iter->f;
@@ -619,7 +619,7 @@ static unsigned int bm_uuidwalk_init_from_edge(
* elsewhere using LinkNode's makes more sense */
for (i = 0; i < f_arr_len; ) {
LinkNode *faces_pass = NULL;
- const unsigned int i_init = i;
+ const uint i_init = i;
const int f_len = f_arr[i]->len;
do {
@@ -750,9 +750,9 @@ static BMFace **bm_mesh_region_match_pair(
UUIDWalk *w_src, UUIDWalk *w_dst,
#endif
BMEdge *e_src, BMEdge *e_dst,
- const unsigned int faces_src_region_len,
- const unsigned int verts_src_region_len,
- unsigned int *r_faces_result_len)
+ const uint faces_src_region_len,
+ const uint verts_src_region_len,
+ uint *r_faces_result_len)
{
#ifndef USE_WALKER_REUSE
UUIDWalk w_src_, w_dst_;
@@ -877,8 +877,8 @@ static BMFace **bm_mesh_region_match_pair(
if (found) {
GHashIterator gh_iter;
- const unsigned int faces_result_len = BLI_ghash_size(w_dst->faces_uuid);
- unsigned int i;
+ const uint faces_result_len = BLI_ghash_size(w_dst->faces_uuid);
+ uint i;
faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__);
GHASH_ITER_INDEX (gh_iter, w_dst->faces_uuid, i) {
@@ -909,12 +909,12 @@ finally:
* Tag as visited, avoid re-use.
*/
static void bm_face_array_visit(
- BMFace **faces, const unsigned int faces_len,
- unsigned int *r_verts_len,
+ BMFace **faces, const uint faces_len,
+ uint *r_verts_len,
bool visit_faces)
{
- unsigned int verts_len = 0;
- unsigned int i;
+ uint verts_len = 0;
+ uint i;
for (i = 0; i < faces_len; i++) {
BMFace *f = faces[i];
BMLoop *l_iter, *l_first;
@@ -1081,9 +1081,9 @@ static SUID_Int bm_face_region_vert_pass_id(GHash *gh, BMVert *v)
* This is only called once on the source region (no need to be highly optimized).
*/
static BMEdge *bm_face_region_pivot_edge_find(
- BMFace **faces_region, unsigned int faces_region_len,
- unsigned int verts_region_len,
- unsigned int *r_depth)
+ BMFace **faces_region, uint faces_region_len,
+ uint verts_region_len,
+ uint *r_depth)
{
/* note, keep deterministic where possible (geometry order independent)
* this function assumed all visit faces & edges are tagged */
@@ -1092,7 +1092,7 @@ static BMEdge *bm_face_region_pivot_edge_find(
BLI_LINKSTACK_DECLARE(vert_queue_next, BMVert *);
GHash *gh = BLI_ghash_ptr_new(__func__);
- unsigned int i;
+ uint i;
BMEdge *e_pivot = NULL;
/* pick any non-boundary edge (not ideal) */
@@ -1101,7 +1101,7 @@ static BMEdge *bm_face_region_pivot_edge_find(
SUID_Int pass = 0;
/* total verts in 'gs' we have visited - aka - not v_init_none */
- unsigned int vert_queue_used = 0;
+ uint vert_queue_used = 0;
BLI_LINKSTACK_INIT(vert_queue_prev);
BLI_LINKSTACK_INIT(vert_queue_next);
@@ -1115,7 +1115,7 @@ static BMEdge *bm_face_region_pivot_edge_find(
do {
BMEdge *e = l_iter->e;
if (bm_edge_is_region_boundary(e)) {
- unsigned int j;
+ uint j;
for (j = 0; j < 2; j++) {
void **val_p;
if (!BLI_ghash_ensure_p(gh, (&e->v1)[j], &val_p)) {
@@ -1251,7 +1251,7 @@ static BMEdge *bm_face_region_pivot_edge_find(
pass = 0;
}
- *r_depth = (unsigned int)pass;
+ *r_depth = (uint)pass;
return e_pivot;
}
@@ -1286,7 +1286,7 @@ static UUIDFashMatch bm_vert_fasthash_single(BMVert *v)
e_num += 1;
do {
f_num += 1;
- l_num += (unsigned int)l_iter->f->len;
+ l_num += (uint)l_iter->f->len;
} while ((l_iter = l_iter->radial_next) != e->l);
}
}
@@ -1301,16 +1301,16 @@ static UUIDFashMatch bm_vert_fasthash_single(BMVert *v)
}
static UUIDFashMatch *bm_vert_fasthash_create(
- BMesh *bm, const unsigned int depth)
+ BMesh *bm, const uint depth)
{
UUIDFashMatch *id_prev;
UUIDFashMatch *id_curr;
- unsigned int pass, i;
+ uint pass, i;
BMVert *v;
BMIter iter;
- id_prev = MEM_mallocN(sizeof(*id_prev) * (unsigned int)bm->totvert, __func__);
- id_curr = MEM_mallocN(sizeof(*id_curr) * (unsigned int)bm->totvert, __func__);
+ id_prev = MEM_mallocN(sizeof(*id_prev) * (uint)bm->totvert, __func__);
+ id_curr = MEM_mallocN(sizeof(*id_curr) * (uint)bm->totvert, __func__);
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
id_prev[i] = bm_vert_fasthash_single(v);
@@ -1319,7 +1319,7 @@ static UUIDFashMatch *bm_vert_fasthash_create(
for (pass = 0; pass < depth; pass++) {
BMEdge *e;
- memcpy(id_curr, id_prev, sizeof(*id_prev) * (unsigned int)bm->totvert);
+ memcpy(id_curr, id_prev, sizeof(*id_prev) * (uint)bm->totvert);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_edge_is_wire(e) == false) {
@@ -1379,16 +1379,16 @@ static void bm_vert_fasthash_destroy(
*/
int BM_mesh_region_match(
BMesh *bm,
- BMFace **faces_region, unsigned int faces_region_len,
+ BMFace **faces_region, uint faces_region_len,
ListBase *r_face_regions)
{
BMEdge *e_src;
BMEdge *e_dst;
BMIter iter;
- unsigned int verts_region_len = 0;
- unsigned int faces_result_len = 0;
+ uint verts_region_len = 0;
+ uint faces_result_len = 0;
/* number of steps from e_src to a boundary vert */
- unsigned int depth;
+ uint depth;
#ifdef USE_WALKER_REUSE
@@ -1457,7 +1457,7 @@ int BM_mesh_region_match(
BM_ITER_MESH (e_dst, &iter, bm, BM_EDGES_OF_MESH) {
BMFace **faces_result;
- unsigned int faces_result_len_out;
+ uint faces_result_len_out;
if (BM_elem_flag_test(e_dst, BM_ELEM_TAG) || BM_edge_is_wire(e_dst)) {
continue;
diff --git a/source/blender/bmesh/tools/bmesh_region_match.h b/source/blender/bmesh/tools/bmesh_region_match.h
index edf8369b070..8ef138629b8 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.h
+++ b/source/blender/bmesh/tools/bmesh_region_match.h
@@ -27,7 +27,7 @@
int BM_mesh_region_match(
BMesh *bm,
- BMFace **faces_region, unsigned int faces_region_len,
+ BMFace **faces_region, uint faces_region_len,
ListBase *r_face_regions);
#endif /* __BMESH_REGION_MATCH_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c
index 04e03664956..287b4125330 100644
--- a/source/blender/bmesh/tools/bmesh_separate.c
+++ b/source/blender/bmesh/tools/bmesh_separate.c
@@ -58,8 +58,8 @@ void BM_mesh_separate_faces(
BMFace *f;
BMIter iter;
- unsigned int faces_a_len = 0;
- unsigned int faces_b_len = 0;
+ uint faces_a_len = 0;
+ uint faces_b_len = 0;
{
int i_a = 0;
int i_b = bm->totface;
@@ -77,7 +77,7 @@ void BM_mesh_separate_faces(
BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
/* Disable vert tag on faces_b */
- for (unsigned int i = 0; i < faces_b_len; i++) {
+ for (uint i = 0; i < faces_b_len; i++) {
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
do {
@@ -89,7 +89,7 @@ void BM_mesh_separate_faces(
BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
/* Check shared verts ('faces_a' tag and disable) */
- for (unsigned int i = 0; i < faces_a_len; i++) {
+ for (uint i = 0; i < faces_a_len; i++) {
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
do {
@@ -120,7 +120,7 @@ void BM_mesh_separate_faces(
}
/* Perform the split */
- bmesh_urmv_loop_multi(bm, loop_split.data, loop_split.count);
+ BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count);
BLI_buffer_empty(&loop_split);
}
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 3801c9300df..bd47ee0214d 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -1934,7 +1934,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
mul_m4_m4m4(mat, ipar, temp);
}
- TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size);
+ bc_decompose(mat, job->loc, NULL, job->quat, job->size);
if (par_job) {
job->parent = par_job;
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 9c26ba83b44..d2495a8cb9f 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -116,7 +116,10 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
ins.add();
return true;
@@ -156,11 +159,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
}
#endif
-std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm)
-{
- return get_joint_id(bone, ob_arm);
-}
-
// parent_mat is armature-space
void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
SceneExporter *se,
@@ -261,47 +259,59 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
//bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
float mat[4][4];
+ float bone_rest_mat[4][4]; /* derived from bone->arm_mat */
+ float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */
- if (bone->parent) {
- // get bone-space matrix from parent pose
- /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
- float invpar[4][4];
- invert_m4_m4(invpar, parchan->pose_mat);
- mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/
-
- float invpar[4][4];
- invert_m4_m4(invpar, bone->parent->arm_mat);
- mul_m4_m4m4(mat, invpar, bone->arm_mat);
+ bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat);
- }
- else {
+ if (!has_restmat) {
+
+ /* Have no restpose matrix stored, try old style <= Blender 2.78 */
- //copy_m4_m4(mat, pchan->pose_mat);
- //pose mat is object space
- //New change: export bone->arm_mat
- copy_m4_m4(mat, bone->arm_mat);
- }
+ bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true);
- // OPEN_SIM_COMPATIBILITY
- if (export_settings->open_sim) {
- // Remove rotations vs armature from transform
- // parent_rest_rot * mat * irest_rot
- float temp[4][4];
- copy_m4_m4(temp, bone->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- invert_m4(temp);
+ if (bone->parent) {
+ // get bone-space matrix from parent pose
+ /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
+ float invpar[4][4];
+ invert_m4_m4(invpar, parchan->pose_mat);
+ mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/
+ float invpar[4][4];
+ bc_create_restpose_mat(this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true);
- mul_m4_m4m4(mat, mat, temp);
+ invert_m4_m4(invpar, parent_rest_mat);
+ mul_m4_m4m4(mat, invpar, bone_rest_mat);
- if (bone->parent) {
- copy_m4_m4(temp, bone->parent->arm_mat);
+ }
+ else {
+ copy_m4_m4(mat, bone_rest_mat);
+ }
+
+ // OPEN_SIM_COMPATIBILITY
+ if (export_settings->open_sim) {
+ // Remove rotations vs armature from transform
+ // parent_rest_rot * mat * irest_rot
+ float temp[4][4];
+ copy_m4_m4(temp, bone_rest_mat);
temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ invert_m4(temp);
+
+ mul_m4_m4m4(mat, mat, temp);
- mul_m4_m4m4(mat, temp, mat);
+ if (bone->parent) {
+ copy_m4_m4(temp, parent_rest_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+
+ mul_m4_m4m4(mat, temp, mat);
+ }
}
}
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(mat, 6);
+
TransformWriter::add_node_transform(node, mat, NULL);
+
}
std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index 883a6aca847..d271b505aa9 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -83,8 +83,6 @@ private:
void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
#endif
- std::string get_joint_sid(Bone *bone, Object *ob_arm);
-
// Scene, SceneExporter and the list of child_objects
// are required for writing bone parented objects
void add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se,
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 17334ca326c..0ea8324ed7c 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -32,6 +32,7 @@
#include "COLLADAFWUniqueId.h"
+extern "C" {
#include "BKE_action.h"
#include "BKE_depsgraph.h"
#include "BKE_object.h"
@@ -39,7 +40,9 @@
#include "BLI_string.h"
#include "BLI_listbase.h"
#include "ED_armature.h"
+}
+#include "collada_utils.h"
#include "ArmatureImporter.h"
// use node name, or fall back to original id if not present (name is optional)
@@ -91,6 +94,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
{
float mat[4][4];
float joint_inv_bind_mat[4][4];
+ float joint_bind_mat[4][4];
int chain_length = 0;
//Checking if bone is already made.
@@ -106,7 +110,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
*/
std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it;
- bool bone_is_not_skinned = true;
+ bool bone_is_skinned = false;
for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) {
SkinInfo *b = &skin_it->second;
@@ -114,7 +118,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
// get original world-space matrix
invert_m4_m4(mat, joint_inv_bind_mat);
-
+ copy_m4_m4(joint_bind_mat, mat);
// And make local to armature
Object *ob_arm = skin->BKE_armature_from_object();
if (ob_arm) {
@@ -123,24 +127,14 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
mul_m4_m4m4(mat, invmat, mat);
}
- bone_is_not_skinned = false;
+ bone_is_skinned = true;
break;
}
}
// create a bone even if there's no joint data for it (i.e. it has no influence)
- if (bone_is_not_skinned) {
- float obmat[4][4];
- // bone-space
- get_node_mat(obmat, node, NULL, NULL);
-
- // get world-space
- if (parent) {
- mul_m4_m4m4(mat, parent_mat, obmat);
- }
- else {
- copy_m4_m4(mat, obmat);
- }
+ if (!bone_is_skinned) {
+ get_node_mat(mat, node, NULL, NULL, parent_mat);
}
if (parent) bone->parent = parent;
@@ -156,10 +150,11 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
int use_connect = be.get_use_connect();
switch (use_connect) {
- case 1: bone->flag |= BONE_CONNECTED;
- break;
- case 0: bone->flag &= ~BONE_CONNECTED;
- case -1: break; // not defined
+ case 1: bone->flag |= BONE_CONNECTED;
+ break;
+ case -1:/* Connect type not specified */
+ case 0: bone->flag &= ~BONE_CONNECTED;
+ break;
}
if (be.has_roll()) {
@@ -172,6 +167,15 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
bone->roll = angle;
}
copy_v3_v3(bone->head, mat[3]);
+
+ if (bone_is_skinned)
+ {
+ float rest_mat[4][4];
+ get_node_mat(rest_mat, node, NULL, NULL, NULL);
+ bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat);
+ bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat);
+ }
+
add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero
/* find smallest bone length in armature (used later for leaf bone length) */
@@ -273,7 +277,6 @@ void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone)
}
-
void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip)
{
BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature);
@@ -289,12 +292,13 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
for (; child; child = child->next) {
BoneExtended *be = extended_bones[child->name];
if (be != NULL) {
- if (be->get_chain_length() <= clip) {
- if (be->get_chain_length() > maxlen) {
+ int chain_len = be->get_chain_length();
+ if (chain_len <= clip) {
+ if (chain_len > maxlen) {
dominant_child = be;
- maxlen = be->get_chain_length();
+ maxlen = chain_len;
}
- else if (be->get_chain_length() == maxlen) {
+ else if (chain_len == maxlen) {
dominant_child = NULL;
}
}
@@ -308,7 +312,6 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
EditBone *pebone = bc_get_edit_bone(armature, parentbone->name);
EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name());
if (pebone && !(cebone->flag & BONE_CONNECTED)) {
-
float vec[3];
sub_v3_v3v3(vec, cebone->head, pebone->head);
@@ -321,14 +324,16 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH)
{
- pebone->tail[0] = cebone->head[0];
- pebone->tail[1] = cebone->head[1];
- pebone->tail[2] = cebone->head[2];
-
+ copy_v3_v3(pebone->tail, cebone->head);
+ pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/
if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) {
+
+ BoneExtended *cbe = extended_bones[cebone->name];
+ cbe->set_use_connect(true);
+
cebone->flag |= BONE_CONNECTED;
- printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name);
pbe->set_leaf_bone(false);
+ printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name);
}
}
}
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index 06e151c363b..5cd5e6d271a 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -98,7 +98,10 @@ bool ControllerExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
ins.add();
return true;
@@ -157,11 +160,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
}
#endif
-std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm)
-{
- return get_joint_id(bone, ob_arm);
-}
-
std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob)
{
return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
@@ -468,81 +466,6 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb
return source_id;
}
-static float get_property(Bone *bone, const char *key, float def)
-{
- float result = def;
- if (bone->prop) {
- IDProperty *property = IDP_GetPropertyFromGroup(bone->prop, key);
- if (property) {
- switch (property->type) {
- case IDP_INT:
- result = (float)(IDP_Int(property));
- break;
- case IDP_FLOAT:
- result = (float)(IDP_Float(property));
- break;
- case IDP_DOUBLE:
- result = (float)(IDP_Double(property));
- break;
- default:
- result = def;
- }
- }
- }
- return result;
-}
-
-/**
- * This function creates an arbitrary rest pose matrix from
- * data provided as custom properties. This is a workaround
- * for support of maya's restpose matrix which can be arbitrary
- * in opposition to Blender where the Rest pose Matrix is always
- * the Identity matrix.
- *
- * The custom properties are:
- *
- * restpose_scale_x
- * restpose_scale_y
- * restpose_scale_z
- *
- * restpose_rot_x
- * restpose_rot_y
- * restpose_rot_z
- *
- * restpose_loc_x
- * restpose_loc_y
- * restpose_loc_z
- *
- * The matrix is only setup if the scale AND the rot properties are defined.
- * The presence of the loc properties is optional.
- *
- * This feature has been implemented to support Second Life "Fitted Mesh"
- * TODO: Check if an arbitrary rest pose matrix makes sense within Blender.
- * Eventually leverage the custom property data into an "official"
- * Edit_bone Property
- */
-static void create_restpose_mat(Bone *bone, float mat[4][4])
-{
- float loc[3] = {
- get_property(bone, "restpose_loc_x", 0.0),
- get_property(bone, "restpose_loc_y", 0.0),
- get_property(bone, "restpose_loc_z", 0.0)
- };
-
- float rot[3] = {
- DEG2RADF(get_property(bone, "restpose_rot_x", 0.0)),
- DEG2RADF(get_property(bone, "restpose_rot_y", 0.0)),
- DEG2RADF(get_property(bone, "restpose_rot_z", 0.0))
- };
-
- float scale[3] = {
- get_property(bone, "restpose_scale_x", 1.0),
- get_property(bone, "restpose_scale_y", 1.0),
- get_property(bone, "restpose_scale_z", 1.0)
- };
-
- loc_eulO_size_to_mat4(mat, loc, rot, scale, 6);
-}
std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
{
@@ -585,30 +508,36 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
float world[4][4];
float inv_bind_mat[4][4];
+ float bind_mat[4][4]; /* derived from bone->arm_mat */
+
+ bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat);
- // SL/OPEN_SIM COMPATIBILITY
- if (export_settings->open_sim) {
- // Only translations, no rotation vs armature
- float temp[4][4];
- unit_m4(temp);
- copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
- mul_m4_m4m4(world, ob_arm->obmat, temp);
-
- // Add Maya restpose matrix (if defined as properties)
- float restpose_mat[4][4];
- create_restpose_mat(pchan->bone, restpose_mat);
- mul_m4_m4m4(world, world, restpose_mat);
+ if (!has_bindmat) {
- }
- else {
- // make world-space matrix, arm_mat is armature-space
- mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
+ /* Have no bind matrix stored, try old style <= Blender 2.78 */
+
+ bc_create_restpose_mat(this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true);
+
+ // SL/OPEN_SIM COMPATIBILITY
+ if (export_settings->open_sim) {
+
+ float loc[3];
+ float rot[3] = { 0, 0, 0 };
+ float scale[3];
+ bc_decompose(bind_mat, loc, NULL, NULL, scale);
+
+ // Only translations, no rotation vs armature
+ loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6);
+ }
}
+ // make world-space matrix (bind_mat is armature-space)
+ mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
invert_m4_m4(mat, world);
converter.mat4_to_dae(inv_bind_mat, mat);
-
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(inv_bind_mat, 6);
source.appendValues(inv_bind_mat);
}
}
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
index 0be51187f6f..80b858ca6dd 100644
--- a/source/blender/collada/ControllerExporter.h
+++ b/source/blender/collada/ControllerExporter.h
@@ -84,8 +84,6 @@ private:
void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
#endif
- std::string get_joint_sid(Bone *bone, Object *ob_arm);
-
std::string get_controller_id(Object *ob_arm, Object *ob);
std::string get_controller_id(Key *key, Object *ob);
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index bd32e989ae3..634071bc90f 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -138,7 +138,8 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
{
int layer_index = CustomData_get_layer_index(data, type);
- if (layer_index < 0) return NULL;
+ if (layer_index < 0)
+ return NULL;
return data->layers[layer_index + n].name;
}
@@ -147,9 +148,10 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index < 0) return NULL;
+ if (layer_index < 1)
+ return NULL;
- return data->layers[layer_index].name;
+ return bc_CustomData_get_layer_name(data, type, layer_index-1);
}
DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 226f319cefd..435eaa0208a 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -388,9 +388,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera
Camera *cam = uid_camera_map[cam_uid];
Camera *old_cam = (Camera *)ob->data;
ob->data = cam;
- id_us_min(&old_cam->id);
- if (old_cam->id.us == 0)
- BKE_libblock_free(G.main, old_cam);
+ BKE_libblock_free_us(G.main, old_cam);
return ob;
}
@@ -406,9 +404,7 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce
Lamp *la = uid_lamp_map[lamp_uid];
Lamp *old_lamp = (Lamp *)ob->data;
ob->data = la;
- id_us_min(&old_lamp->id);
- if (old_lamp->id.us == 0)
- BKE_libblock_free(G.main, old_lamp);
+ BKE_libblock_free_us(G.main, old_lamp);
return ob;
}
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 76b51148509..2bf0859b0f0 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -27,7 +27,6 @@
#include <map>
-#include <set>
#include "COLLADASWEffectProfile.h"
#include "COLLADAFWColorOrTexture.h"
@@ -49,21 +48,10 @@ extern "C" {
#include "BKE_material.h"
}
-// OB_MESH is assumed
-static std::string getActiveUVLayerName(Object *ob)
-{
- Mesh *me = (Mesh *)ob->data;
-
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- if (num_layers)
- return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
-
- return "";
-}
-
EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
}
+
bool EffectsExporter::hasEffects(Scene *sce)
{
Base *base = (Base *)sce->base.first;
@@ -86,13 +74,49 @@ bool EffectsExporter::hasEffects(Scene *sce)
void EffectsExporter::exportEffects(Scene *sce)
{
- if (hasEffects(sce)) {
- this->scene = sce;
- openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
-
- closeLibrary();
+ this->scene = sce;
+
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
+ if (hasEffects(sce)) {
+ MaterialFunctor mf;
+ openLibrary();
+ mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
+ closeLibrary();
+ }
+ }
+ else {
+ std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only);
+ std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
+ if (uv_images.size() > 0) {
+ openLibrary();
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string key(id_name(ima));
+ key = translate_id(key);
+ COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
+ key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
+ key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
+ sampler.setImageId(key);
+
+ openEffect(key + "-effect");
+ COLLADASW::EffectProfile ep(mSW);
+ ep.setProfileType(COLLADASW::EffectProfile::COMMON);
+ ep.setShaderType(COLLADASW::EffectProfile::PHONG);
+ ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse");
+ COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f);
+ ep.setSpecular(cot, false, "specular");
+ ep.openProfile();
+ ep.addProfileElements();
+ ep.addExtraTechniques(mSW);
+ ep.closeProfile();
+ closeEffect();
+ }
+ closeLibrary();
+ }
}
}
@@ -176,8 +200,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
{
// create a list of indices to textures of type TEX_IMAGE
std::vector<int> tex_indices;
- if (this->export_settings->include_material_textures)
- createTextureIndices(ma, tex_indices);
+ createTextureIndices(ma, tex_indices);
openEffect(translate_id(id_name(ma)) + "-effect");
@@ -311,61 +334,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
}
}
- int active_uv_layer = -1;
- std::set<Image *> uv_textures;
- if (ob->type == OB_MESH && ob->totcol && this->export_settings->include_uv_textures) {
- bool active_uv_only = this->export_settings->active_uv_only;
- Mesh *me = (Mesh *) ob->data;
- active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- BKE_mesh_tessface_ensure(me);
- for (int i = 0; i < me->pdata.totlayer; i++) {
- if (!active_uv_only || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Material *mat = give_current_material(ob, mpoly->mat_nr + 1);
- if (mat != ma)
- continue;
-
- Image *ima = txface->tpage;
- if (ima == NULL)
- continue;
-
-
- bool not_in_list = uv_textures.find(ima)==uv_textures.end();
- if (not_in_list) {
- std::string name = id_name(ima);
- std::string key(name);
- key = translate_id(key);
-
- // create only one <sampler>/<surface> pair for each unique image
- if (im_samp_map.find(key) == im_samp_map.end()) {
- //<newparam> <sampler> <source>
- COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
- key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
- key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
- sampler.setImageId(key);
- samplers[a] = sampler;
- samp_surf[b] = &samplers[a];
- im_samp_map[key] = b;
- b++;
- a++;
- uv_textures.insert(ima);
- }
- }
- }
- }
- }
- }
- }
-
// used as fallback when MTex->uvname is "" (this is pretty common)
// it is indeed the correct value to use in that case
- std::string active_uv(getActiveUVLayerName(ob));
+ std::string active_uv(bc_get_active_uvlayer_name(ob));
// write textures
// XXX very slow
@@ -385,19 +356,6 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
writeTextures(ep, key, sampler, t, ima, uvname);
}
- std::set<Image *>::iterator uv_t_iter;
- int idx;
- for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) {
- if (active_uv_layer>-1 && idx==active_uv_layer) {
- Image *ima = *uv_t_iter;
- std::string key(id_name(ima));
- key = translate_id(key);
- int i = im_samp_map[key];
- COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i];
- ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse");
- }
- }
-
// performs the actual writing
ep.addProfileElements();
bool twoSided = false;
diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h
index d20cbfdfe0b..7d45a085777 100644
--- a/source/blender/collada/EffectExporter.h
+++ b/source/blender/collada/EffectExporter.h
@@ -48,7 +48,6 @@ class EffectsExporter: COLLADASW::LibraryEffects
public:
EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
void exportEffects(Scene *sce);
-
void operator()(Material *ma, Object *ob);
COLLADASW::ColorOrTexture createTexture(Image *ima,
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index 98aa85f8a9b..32aa5636e08 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -49,7 +49,7 @@ ErrorHandler::~ErrorHandler()
//--------------------------------------------------------------------
bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
{
- bool isError = true;
+ bool isError = false;
if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) {
COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error;
@@ -81,10 +81,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
* Accept non critical errors as warnings (i.e. texture not found)
* This makes the importer more graceful, so it now imports what makes sense.
*/
- if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) {
- isError = false;
- }
-
+ isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL);
std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl;
}
else {
@@ -93,5 +90,5 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
mError |= isError;
- return false; // let OpenCollada decide when to abort
+ return isError; // let OpenCollada decide when to abort
}
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 9451cac9dae..6d90edd2f67 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -28,7 +28,6 @@
#define __EXPORTSETTINGS_H__
#include "collada.h"
-#include "collada.h"
struct ExportSettings {
public:
@@ -42,8 +41,7 @@ public:
bool deform_bones_only;
bool active_uv_only;
- bool include_uv_textures;
- bool include_material_textures;
+ BC_export_texture_type export_texture_type;
bool use_texture_copies;
bool triangulate;
@@ -51,7 +49,10 @@ public:
bool use_blender_profile;
bool sort_by_name;
BC_export_transformation_type export_transformation_type;
+
bool open_sim;
+ bool limit_precision;
+ bool keep_bind_info;
char *filepath;
LinkNode *export_set;
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 7c7c57f3305..b8b1ff7fd95 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -52,6 +52,7 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
+
// TODO: optimize UV sets by making indexed list with duplicates removed
GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
{
@@ -134,13 +135,22 @@ void GeometryExporter::operator()(Object *ob)
// Only create Polylists if number of faces > 0
if (me->totface > 0) {
// XXX slow
- if (ob->totcol) {
- for (int a = 0; a < ob->totcol; a++) {
- createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+ std::set<Image *> uv_images = bc_getUVImages(ob, !this->export_settings->active_uv_only);
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT || uv_images.size() == 0) {
+ if (ob->totcol) {
+ for (int a = 0; a < ob->totcol; a++) {
+ createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+ }
+ else {
+ int i = 0;
+ createPolylist(i, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+ bool all_uv_layers = !this->export_settings->active_uv_only;
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
}
@@ -220,13 +230,15 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
//createLooseEdgeList(ob, me, geom_id, norind);
// XXX slow
- if (ob->totcol) {
+ if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
for (int a = 0; a < ob->totcol; a++) {
createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+ bool all_uv_layers = !this->export_settings->active_uv_only;
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
closeMesh();
@@ -295,7 +307,44 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char
return result;
}
-// powerful because it handles both cases when there is material and when there's not
+static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase *facelist, std::vector<unsigned long> &vcount_list)
+{
+ // performs the actual writing
+ if (is_triangulated) {
+ ((COLLADASW::Triangles *)facelist)->prepareToAppendValues();
+ }
+ else {
+ // sets <vcount>
+ facelist->setVCountList(vcount_list);
+ ((COLLADASW::Polylist *)facelist)-> prepareToAppendValues();
+ }
+}
+
+static void finishList(bool is_triangulated, COLLADASW::PrimitivesBase *facelist)
+{
+ if (is_triangulated) {
+ ((COLLADASW::Triangles *)facelist)->finish();
+ }
+ else {
+ ((COLLADASW::Polylist *)facelist)->finish();
+ }
+}
+
+COLLADASW::PrimitivesBase *getFacelist(bool is_triangulated, COLLADASW::StreamWriter *mSW)
+{
+ COLLADASW::PrimitivesBase *facelist;
+
+ if (is_triangulated)
+ {
+ facelist = new COLLADASW::Triangles(mSW);
+ }
+ else {
+ facelist = new COLLADASW::Polylist(mSW);
+ }
+ return facelist;
+}
+
+// Export meshes with Materials
void GeometryExporter::createPolylist(short material_index,
bool has_uvs,
bool has_color,
@@ -313,7 +362,7 @@ void GeometryExporter::createPolylist(short material_index,
int i;
int faces_in_polylist = 0;
std::vector<unsigned long> vcount_list;
-
+ bool is_triangulated = true;
// count faces with this material
for (i = 0; i < totpolys; i++) {
MPoly *p = &mpolys[i];
@@ -321,6 +370,9 @@ void GeometryExporter::createPolylist(short material_index,
if (p->mat_nr == material_index) {
faces_in_polylist++;
vcount_list.push_back(p->totloop);
+ if (p->totloop != 3) {
+ is_triangulated = false;
+ }
}
}
@@ -331,20 +383,21 @@ void GeometryExporter::createPolylist(short material_index,
}
Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
- COLLADASW::Polylist polylist(mSW);
+ COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
+
// sets count attribute in <polylist>
- polylist.setCount(faces_in_polylist);
+ facelist->setCount(faces_in_polylist);
// sets material name
if (ma) {
std::string material_id = get_material_id(ma);
std::ostringstream ostr;
ostr << translate_id(material_id);
- polylist.setMaterial(ostr.str());
+ facelist->setMaterial(ostr.str());
}
- COLLADASW::InputList &til = polylist.getInputList();
+ COLLADASW::InputList &til = facelist->getInputList();
// creates <input> in <polylist> for vertices
COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
@@ -360,13 +413,21 @@ void GeometryExporter::createPolylist(short material_index,
int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
for (i = 0; i < num_layers; i++) {
if (!this->export_settings->active_uv_only || i == active_uv_index) {
-
- // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
+
+ std::string uv_name(bc_get_uvlayer_name(me, i));
+ std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ i, this->export_settings->active_uv_only);
+
+ /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
+ For now this is always 2 (This may change sometime/maybe)
+ */
COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
- 2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
- );
+ makeUrl(layer_id),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
til.push_back(input3);
}
}
@@ -387,12 +448,10 @@ void GeometryExporter::createPolylist(short material_index,
}
}
- // sets <vcount>
- polylist.setVCountList(vcount_list);
// performs the actual writing
- polylist.prepareToAppendValues();
-
+ prepareToAppendValues(is_triangulated, facelist, vcount_list);
+
// <p>
int texindex = 0;
for (i = 0; i < totpolys; i++) {
@@ -404,22 +463,202 @@ void GeometryExporter::createPolylist(short material_index,
BCPolygonNormalsIndices normal_indices = norind[i];
for (int j = 0; j < loop_count; j++) {
- polylist.appendValues(l[j].v);
- polylist.appendValues(normal_indices[j]);
+ facelist->appendValues(l[j].v);
+ facelist->appendValues(normal_indices[j]);
if (has_uvs)
- polylist.appendValues(texindex + j);
+ facelist->appendValues(texindex + j);
if (has_color)
- polylist.appendValues(texindex + j);
+ facelist->appendValues(texindex + j);
}
}
texindex += loop_count;
}
-
- polylist.finish();
+
+ finishList(is_triangulated, facelist);
+ delete facelist;
+}
+
+void GeometryExporter::createPolylists(std::set<Image *> uv_images,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind)
+{
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string imageid(id_name(ima));
+ createPolylist(imageid, has_uvs,
+ has_color,
+ ob,
+ me,
+ geom_id,
+ norind);
+ }
+
+ /* We msut add an additional collector for the case when
+ * some parts of the object are not textured at all.
+ * The next call creates a polylist for all untextured polygons
+ */
+
+ createPolylist("", has_uvs,
+ has_color,
+ ob,
+ me,
+ geom_id,
+ norind);
+
}
+/* ===========================================================================
+ * Export Meshes with UV Textures (export as materials, see also in
+ * effectExporter and MaterialExporter)
+ *
+ * If imageid is the empty string, then collect only untextured polygons
+ * =========================================================================== */
+void GeometryExporter::createPolylist(std::string imageid,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind)
+{
+
+ MPoly *mpolys = me->mpoly;
+ MLoop *mloops = me->mloop;
+ MTexPoly *mtpolys = me->mtpoly;
+
+ int totpolys = me->totpoly;
+
+ // <vcount>
+ int i;
+ int faces_in_polylist = 0;
+ std::vector<unsigned long> vcount_list;
+ bool is_triangulated = true;
+ // count faces with this material
+ for (i = 0; i < totpolys; i++) {
+ MTexPoly *tp = &mtpolys[i];
+ MPoly *p = &mpolys[i];
+
+ std::string tpageid = (tp->tpage) ? id_name(tp->tpage):"";
+ if (tpageid == imageid) {
+ faces_in_polylist++;
+ vcount_list.push_back(p->totloop);
+ if (p->totloop != 3) {
+ is_triangulated = false;
+ }
+ }
+ }
+
+ // no faces using this imageid
+ if (faces_in_polylist == 0) {
+ if (imageid != "")
+ fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid.c_str());
+ return;
+ }
+
+ COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
+
+ // sets count attribute in <polylist>
+ facelist->setCount(faces_in_polylist);
+
+ if (imageid != "") {
+ // sets material name
+ std::string material_id = get_material_id_from_id(imageid);
+ std::ostringstream ostr;
+ ostr << translate_id(material_id);
+ facelist->setMaterial(ostr.str());
+ }
+ COLLADASW::InputList &til = facelist->getInputList();
+
+ // creates <input> in <polylist> for vertices
+ COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
+
+ // creates <input> in <polylist> for normals
+ COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
+
+ til.push_back(input1);
+ til.push_back(input2);
+
+ // if mesh has uv coords writes <input> for TEXCOORD
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ for (i = 0; i < num_layers; i++) {
+ if (!this->export_settings->active_uv_only || i == active_uv_index) {
+
+ std::string uv_name(bc_get_uvlayer_name(me, i));
+ std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ i, this->export_settings->active_uv_only);
+
+ /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
+ For now this is always 2 (This may change sometime/maybe)
+ */
+ COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
+ makeUrl(layer_id),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
+ til.push_back(input3);
+ }
+ }
+
+ int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+ if (totlayer_mcol > 0) {
+ int map_index = 0;
+
+ for (int a = 0; a < totlayer_mcol; a++) {
+ char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
+ COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
+ makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
+ (has_uvs) ? 3 : 2, // all color layers have same index order
+ map_index // set number equals color map index
+ );
+ til.push_back(input4);
+ map_index++;
+ }
+ }
+
+ // performs the actual writing
+ prepareToAppendValues(is_triangulated, facelist, vcount_list);
+
+ // <p>
+ int texindex = 0;
+ for (i = 0; i < totpolys; i++) {
+ MTexPoly *tp = &mtpolys[i];
+ MPoly *p = &mpolys[i];
+ int loop_count = p->totloop;
+ std::string tpageid = (tp->tpage) ? id_name(tp->tpage) : "";
+ if (tpageid == imageid) {
+ MLoop *l = &mloops[p->loopstart];
+ BCPolygonNormalsIndices normal_indices = norind[i];
+
+ for (int j = 0; j < loop_count; j++) {
+ facelist->appendValues(l[j].v);
+ facelist->appendValues(normal_indices[j]);
+ if (has_uvs)
+ facelist->appendValues(texindex + j);
+
+ if (has_color)
+ facelist->appendValues(texindex + j);
+ }
+ }
+
+ texindex += loop_count;
+ }
+
+ finishList(is_triangulated, facelist);
+ delete facelist;
+}
// creates <source> for positions
void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
@@ -537,7 +776,13 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
- std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
+ std::string active_uv_name(bc_get_active_uvlayer_name(me));
+ std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ a,
+ this->export_settings->active_uv_only );
+
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 69d1067e6f4..890304f4568 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -85,15 +85,33 @@ public:
Mesh *me,
std::string& geom_id);
- // powerful because it handles both cases when there is material and when there's not
+ // Create polylists for meshes with Materials
void createPolylist(short material_index,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
+ // Create polylists for meshes with UV Textures
+ void createPolylists(std::set<Image *> uv_images,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
+ // Create polylists for meshes with UV Textures
+ void createPolylist(std::string imageid,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
// creates <source> for positions
void createVertsSource(std::string geom_id, Mesh *me);
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index aac41e2e93c..93be7de6236 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings
void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
{
- std::string name(id_name(image));
- std::string translated_name(translate_id(name));
- bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
+ std::string id(id_name(image));
+ std::string translated_id(translate_id(id));
+ bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
if (not_yet_exported) {
@@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// make absolute destination path
- BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
+ BLI_strncpy(export_file, id.c_str(), sizeof(export_file));
BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
@@ -143,10 +143,11 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
}
}
- COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+ /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+ COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id);
img.add(mSW);
fprintf(stdout, "Collada export: Added image: %s\n", export_file);
- mImages.push_back(translated_name);
+ mImages.push_back(translated_id);
BKE_image_release_ibuf(image, imbuf, NULL);
}
@@ -161,7 +162,7 @@ void ImagesExporter::export_UV_Images()
for (node = this->export_settings->export_set; node; node = node->next) {
Object *ob = (Object *)node->link;
- if (ob->type == OB_MESH && ob->totcol) {
+ if (ob->type == OB_MESH) {
Mesh *me = (Mesh *) ob->data;
BKE_mesh_tessface_ensure(me);
int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
@@ -189,7 +190,13 @@ void ImagesExporter::export_UV_Images()
}
}
-
+/* ============================================================
+ * Check if there are any images to be exported
+ * Returns true as soon as an object is detected that
+ * either has an UV Texture assigned, or has a material
+ * assigned that uses an Image Texture.
+ * ============================================================
+ */
bool ImagesExporter::hasImages(Scene *sce)
{
LinkNode *node;
@@ -232,11 +239,10 @@ void ImagesExporter::exportImages(Scene *sce)
openLibrary();
MaterialFunctor mf;
- if (this->export_settings->include_material_textures) {
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set);
}
-
- if (this->export_settings->include_uv_textures) {
+ else {
export_UV_Images();
}
diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h
index 2c52d73e756..4a2d4e8046a 100644
--- a/source/blender/collada/ImportSettings.h
+++ b/source/blender/collada/ImportSettings.h
@@ -37,6 +37,7 @@ public:
bool fix_orientation;
int min_chain_length;
char *filepath;
+ bool keep_bind_info;
};
#endif
diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp
index 71371d280df..de1a4075462 100644
--- a/source/blender/collada/InstanceWriter.cpp
+++ b/source/blender/collada/InstanceWriter.cpp
@@ -32,43 +32,76 @@
#include "COLLADASWInstanceMaterial.h"
extern "C" {
- #include "BKE_customdata.h"
- #include "BKE_material.h"
- #include "DNA_mesh_types.h"
+#include "BKE_customdata.h"
+#include "BKE_material.h"
+#include "DNA_mesh_types.h"
}
#include "InstanceWriter.h"
#include "collada_internal.h"
#include "collada_utils.h"
-void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only)
+void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
{
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
-
- COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
+ bool all_uv_layers = !active_uv_only;
+ COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
- if (ma) {
- std::string matid(get_material_id(ma));
- matid = translate_id(matid);
+ if (export_texture_type == BC_TEXTURE_TYPE_UV)
+ {
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+ Image *ima = *uv_images_iter;
+ std::string matid(id_name(ima));
+ matid = get_material_id_from_id(matid);
std::ostringstream ostr;
ostr << matid;
COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
-
+
// create <bind_vertex_input> for each uv map
Mesh *me = (Mesh *)ob->data;
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
+
int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
for (int b = 0; b < totlayer; b++) {
if (!active_uv_only || b == active_uv_index) {
char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
}
}
-
+
iml.push_back(im);
}
}
+
+ else {
+ for (int a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
+ if (ma) {
+ std::string matid(get_material_id(ma));
+ matid = translate_id(matid);
+ std::ostringstream ostr;
+ ostr << matid;
+ COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
+
+ // create <bind_vertex_input> for each uv map
+ Mesh *me = (Mesh *)ob->data;
+ int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+
+ int map_index = 0;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ for (int b = 0; b < totlayer; b++) {
+ if (!active_uv_only || b == active_uv_index) {
+ char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
+ im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
+ }
+ }
+
+ iml.push_back(im);
+ }
+ }
+ }
}
diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h
index 49ddf091b1c..a46027325a2 100644
--- a/source/blender/collada/InstanceWriter.h
+++ b/source/blender/collada/InstanceWriter.h
@@ -31,11 +31,12 @@
#include "COLLADASWBindMaterial.h"
#include "DNA_object_types.h"
+#include "collada.h"
class InstanceWriter
{
protected:
- void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only);
+ void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type);
};
#endif
diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp
index 4aece997f72..6e6cc24be20 100644
--- a/source/blender/collada/MaterialExporter.cpp
+++ b/source/blender/collada/MaterialExporter.cpp
@@ -38,14 +38,39 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSe
void MaterialsExporter::exportMaterials(Scene *sce)
{
- if (hasMaterials(sce)) {
- openLibrary();
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT)
+ {
+ if (hasMaterials(sce)) {
+ openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
+ MaterialFunctor mf;
+ mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
- closeLibrary();
+ closeLibrary();
+ }
}
+
+ else {
+ std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
+ if (uv_images.size() > 0) {
+ openLibrary();
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string matid(id_name(ima));
+
+ openMaterial(get_material_id_from_id(matid), translate_id(matid));
+ std::string efid = translate_id(matid) + "-effect";
+ addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid));
+ closeMaterial();
+ }
+ closeLibrary();
+ }
+ }
+
}
bool MaterialsExporter::hasMaterials(Scene *sce)
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 8f3bf88af65..6ca53c64299 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -27,7 +27,7 @@
#include <algorithm>
-#if !defined(WIN32) || defined(FREE_WINDOWS)
+#if !defined(WIN32)
#include <iostream>
#endif
@@ -1173,8 +1173,9 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
BKE_mesh_assign_object(ob, new_mesh);
BKE_mesh_calc_normals(new_mesh);
- if (old_mesh->id.us == 0) BKE_libblock_free(G.main, old_mesh);
-
+ id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */
+ BKE_libblock_free_us(G.main, old_mesh);
+
char layername[100];
layername[0] = '\0';
MTFace *texture_face = NULL;
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 30cd6ddf197..73945539931 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -151,7 +151,10 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
COLLADASW::InstanceGeometry instGeom(mSW);
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
instGeom.setName(translate_id(id_name(ob)));
- InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(instGeom.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
instGeom.add();
}
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 71875d6274a..c48c060dc95 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -27,7 +27,7 @@
#include <algorithm>
-#if !defined(WIN32) || defined(FREE_WINDOWS)
+#if !defined(WIN32)
#include <stdint.h>
#endif
diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp
index f8f31304d28..7f742be7e30 100644
--- a/source/blender/collada/TransformReader.cpp
+++ b/source/blender/collada/TransformReader.cpp
@@ -34,7 +34,21 @@ TransformReader::TransformReader(UnitConverter *conv) : unit_converter(conv)
/* pass */
}
-void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob)
+void TransformReader::get_node_mat(
+ float mat[4][4],
+ COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Animation> *animation_map,
+ Object *ob)
+{
+ get_node_mat(mat, node, animation_map, ob, NULL);
+}
+
+void TransformReader::get_node_mat(
+ float mat[4][4],
+ COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Animation> *animation_map,
+ Object *ob,
+ float parent_mat[4][4])
{
float cur[4][4];
float copy[4][4];
@@ -52,6 +66,9 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
// then this is considered as redundant information.
// So if we find a Matrix we use that and return.
dae_matrix_to_mat4(tm, mat);
+ if (parent_mat) {
+ mul_m4_m4m4(mat, parent_mat, mat);
+ }
return;
case COLLADAFW::Transformation::TRANSLATE:
dae_translate_to_mat4(tm, cur);
@@ -80,6 +97,10 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
(*animation_map)[anim_list_id] = anim;
}
}
+
+ if (parent_mat) {
+ mul_m4_m4m4(mat, parent_mat, mat);
+ }
}
void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4])
diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h
index ab974b9ba85..08bb17ccac1 100644
--- a/source/blender/collada/TransformReader.h
+++ b/source/blender/collada/TransformReader.h
@@ -43,7 +43,7 @@
//struct Object;
-class TransformReader : public TransformBase
+class TransformReader
{
protected:
@@ -59,7 +59,8 @@ public:
TransformReader(UnitConverter *conv);
void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob);
-
+ void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob, float parent_mat[4][4]);
+
void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 908111ebae6..b7eeff3b074 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -27,11 +27,10 @@
#include "BKE_object.h"
+#include "BLI_math.h"
#include "TransformWriter.h"
-#include "BLI_math.h"
-
void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4])
{
float loc[3], rot[3], scale[3];
@@ -51,7 +50,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4],
converter->mat4_to_dae_double(dmat, local);
delete converter;
- TransformBase::decompose(local, loc, rot, NULL, scale);
+ bc_decompose(local, loc, rot, NULL, scale);
if (node.getType() == COLLADASW::Node::JOINT) {
// XXX Why are joints handled differently ?
@@ -116,7 +115,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
case BC_TRANSFORMATION_TYPE_TRANSROTLOC:
{
float loc[3], rot[3], scale[3];
- TransformBase::decompose(f_obmat, loc, rot, NULL, scale);
+ bc_decompose(f_obmat, loc, rot, NULL, scale);
add_transform(node, loc, rot, scale);
break;
}
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
index 7f69a4b9c95..5bb13d4aac9 100644
--- a/source/blender/collada/TransformWriter.h
+++ b/source/blender/collada/TransformWriter.h
@@ -33,9 +33,10 @@
#include "DNA_object_types.h"
#include "collada_internal.h"
+#include "collada_utils.h"
#include "collada.h"
-class TransformWriter : protected TransformBase
+class TransformWriter
{
protected:
void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index fe8b1d2320a..024bc4a4a5c 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -48,7 +48,8 @@ int collada_import(bContext *C,
int find_chains,
int auto_connect,
int fix_orientation,
- int min_chain_length)
+ int min_chain_length,
+ int keep_bind_info)
{
ImportSettings import_settings;
@@ -58,6 +59,7 @@ int collada_import(bContext *C,
import_settings.find_chains = find_chains != 0;
import_settings.fix_orientation = fix_orientation != 0;
import_settings.min_chain_length = min_chain_length;
+ import_settings.keep_bind_info = keep_bind_info !=0;
DocumentImporter imp(C, &import_settings);
if (imp.import()) return 1;
@@ -78,8 +80,7 @@ int collada_export(Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -87,7 +88,9 @@ int collada_export(Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim)
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info)
{
ExportSettings export_settings;
@@ -102,8 +105,7 @@ int collada_export(Scene *sce,
export_settings.deform_bones_only = deform_bones_only != 0;
export_settings.active_uv_only = active_uv_only != 0;
- export_settings.include_uv_textures = include_uv_textures != 0;
- export_settings.include_material_textures= include_material_textures != 0;
+ export_settings.export_texture_type = export_texture_type;
export_settings.use_texture_copies = use_texture_copies != 0;
export_settings.triangulate = triangulate != 0;
@@ -112,7 +114,8 @@ int collada_export(Scene *sce,
export_settings.sort_by_name = sort_by_name != 0;
export_settings.export_transformation_type = export_transformation_type;
export_settings.open_sim = open_sim != 0;
-
+ export_settings.limit_precision = limit_precision != 0;
+ export_settings.keep_bind_info = keep_bind_info !=0;
int includeFilter = OB_REL_NONE;
if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index a4416608584..d31f5a8ba62 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -46,6 +46,11 @@ typedef enum BC_export_transformation_type {
BC_TRANSFORMATION_TYPE_TRANSROTLOC
} BC_export_transformation_type;
+typedef enum BC_export_texture_type {
+ BC_TEXTURE_TYPE_MAT,
+ BC_TEXTURE_TYPE_UV
+} BC_export_texture_type;
+
struct bContext;
struct Scene;
@@ -58,7 +63,9 @@ int collada_import(struct bContext *C,
int find_chains,
int auto_connect,
int fix_orientation,
- int min_chain_length);
+ int min_chain_length,
+
+ int keep_bind_info);
int collada_export(struct Scene *sce,
const char *filepath,
@@ -72,8 +79,7 @@ int collada_export(struct Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -81,9 +87,10 @@ int collada_export(struct Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim);
-
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info);
#ifdef __cplusplus
}
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index e1a13559b08..8974acb3460 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -162,18 +162,6 @@ void UnitConverter::calculate_scale(Scene &sce)
size_to_mat4(scale_mat4, rescale);
}
-void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
-{
- mat4_to_size(size, mat);
- if (eul) {
- mat4_to_eul(eul, mat);
- }
- if (quat) {
- mat4_to_quat(quat, mat);
- }
- copy_v3_v3(loc, mat[3]);
-}
-
/**
* Translation map.
* Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
@@ -341,7 +329,12 @@ std::string get_light_id(Object *ob)
std::string get_joint_id(Bone *bone, Object *ob_arm)
{
- return translate_id(/*id_name(ob_arm) + "_" +*/ bone->name);
+ return translate_id(id_name(ob_arm) + "_" + bone->name);
+}
+
+std::string get_joint_sid(Bone *bone, Object *ob_arm)
+{
+ return translate_id(bone->name);
}
std::string get_camera_id(Object *ob)
@@ -351,7 +344,13 @@ std::string get_camera_id(Object *ob)
std::string get_material_id(Material *mat)
{
- return translate_id(id_name(mat)) + "-material";
+ std::string id = id_name(mat);
+ return get_material_id_from_id(id);
+}
+
+std::string get_material_id_from_id(std::string id)
+{
+ return translate_id(id) + "-material";
}
std::string get_morph_id(Object *ob)
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 4aa637a6876..5f3fa34edc1 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -85,12 +85,6 @@ public:
};
-class TransformBase
-{
-public:
- void decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size);
-};
-
extern void clear_global_id_map();
/** Look at documentation of translate_map */
extern std::string translate_id(const std::string &id);
@@ -104,10 +98,12 @@ extern std::string get_geometry_id(Object *ob, bool use_instantiation);
extern std::string get_light_id(Object *ob);
extern std::string get_joint_id(Bone *bone, Object *ob_arm);
+extern std::string get_joint_sid(Bone *bone, Object *ob_arm);
extern std::string get_camera_id(Object *ob);
extern std::string get_material_id(Material *mat);
+extern std::string get_material_id_from_id(std::string id);
extern std::string get_morph_id(Object *ob);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 2efa8b21d81..b09732f9102 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -32,7 +32,7 @@
#include "COLLADAFWMeshPrimitive.h"
#include "COLLADAFWMeshVertexData.h"
-#include "collada_utils.h"
+#include <set>
extern "C" {
#include "DNA_modifier_types.h"
@@ -63,6 +63,9 @@ extern "C" {
#include "bmesh_tools.h"
}
+#include "collada_utils.h"
+#include "ExportSettings.h"
+
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
{
if (index >= array.getValuesCount())
@@ -352,6 +355,28 @@ void bc_match_scale(std::vector<Object *> *objects_done,
}
}
+/*
+ Convenience function to get only the needed components of a matrix
+*/
+void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
+{
+ if (size) {
+ mat4_to_size(size, mat);
+ }
+
+ if (eul) {
+ mat4_to_eul(eul, mat);
+ }
+
+ if (quat) {
+ mat4_to_quat(quat, mat);
+ }
+
+ if (loc) {
+ copy_v3_v3(loc, mat[3]);
+ }
+}
+
void bc_triangulate_mesh(Mesh *me)
{
bool use_beauty = false;
@@ -612,3 +637,356 @@ int BoneExtended::get_use_connect()
{
return this->use_connect;
}
+
+/**
+* Stores a 4*4 matrix as a custom bone property array of size 16
+*/
+void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
+{
+ IDProperty *idgroup = (IDProperty *)ebone->prop;
+ if (idgroup == NULL)
+ {
+ IDPropertyTemplate val = { 0 };
+ idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
+ ebone->prop = idgroup;
+ }
+
+ IDPropertyTemplate val = { 0 };
+ val.array.len = 16;
+ val.array.type = IDP_FLOAT;
+
+ IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
+ float *array = (float *)IDP_Array(data);
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ array[4 * i + j] = mat[i][j];
+
+ IDP_AddToGroup(idgroup, data);
+}
+
+#if 0
+/**
+* Stores a Float value as a custom bone property
+*
+* Note: This function is currently not needed. Keep for future usage
+*/
+static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
+{
+ if (ebone->prop == NULL)
+ {
+ IDPropertyTemplate val = { 0 };
+ ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
+ }
+
+ IDProperty *pgroup = (IDProperty *)ebone->prop;
+ IDPropertyTemplate val = { 0 };
+ IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
+ IDP_Float(prop) = value;
+ IDP_AddToGroup(pgroup, prop);
+
+}
+#endif
+
+/*
+* Get a custom property when it exists.
+* This function is also used to check if a property exists.
+*/
+IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
+{
+ return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
+}
+
+/**
+* Read a custom bone property and convert to float
+* Return def if the property does not exist.
+*/
+float bc_get_property(Bone *bone, std::string key, float def)
+{
+ float result = def;
+ IDProperty *property = bc_get_IDProperty(bone, key);
+ if (property) {
+ switch (property->type) {
+ case IDP_INT:
+ result = (float)(IDP_Int(property));
+ break;
+ case IDP_FLOAT:
+ result = (float)(IDP_Float(property));
+ break;
+ case IDP_DOUBLE:
+ result = (float)(IDP_Double(property));
+ break;
+ default:
+ result = def;
+ }
+ }
+ return result;
+}
+
+/**
+* Read a custom bone property and convert to matrix
+* Return true if conversion was succesfull
+*
+* Return false if:
+* - the property does not exist
+* - is not an array of size 16
+*/
+bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
+{
+ IDProperty *property = bc_get_IDProperty(bone, key);
+ if (property && property->type == IDP_ARRAY && property->len == 16) {
+ float *array = (float *)IDP_Array(property);
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ mat[i][j] = array[4 * i + j];
+ return true;
+ }
+ return false;
+}
+
+/**
+* get a vector that is stored in 3 custom properties (used in Blender <= 2.78)
+*/
+void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
+{
+ val[0] = bc_get_property(bone, key + "_x", def[0]);
+ val[1] = bc_get_property(bone, key + "_y", def[1]);
+ val[2] = bc_get_property(bone, key + "_z", def[2]);
+}
+
+/**
+* Check if vector exist stored in 3 custom properties (used in Blender <= 2.78)
+*/
+static bool has_custom_props(Bone *bone, bool enabled, std::string key)
+{
+ if (!enabled)
+ return false;
+
+ return (bc_get_IDProperty(bone, key + "_x")
+ || bc_get_IDProperty(bone, key + "_y")
+ || bc_get_IDProperty(bone, key + "_z"));
+
+}
+
+/**
+* Check if custom information about bind matrix exists and modify the from_mat
+* accordingly.
+*
+* Note: This is old style for Blender <= 2.78 only kept for compatibility
+*/
+void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
+{
+ float loc[3];
+ float rot[3];
+ float scale[3];
+ static const float V0[3] = { 0, 0, 0 };
+
+ if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
+ !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
+ !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale"))
+ {
+ /* No need */
+ copy_m4_m4(to_mat, from_mat);
+ return;
+ }
+
+ bc_decompose(from_mat, loc, rot, NULL, scale);
+ loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
+
+ if (export_settings->keep_bind_info) {
+ bc_get_property_vector(bone, "restpose_loc", loc, loc);
+
+ if (use_local_space && bone->parent) {
+ Bone *b = bone;
+ while (b->parent) {
+ b = b->parent;
+ float ploc[3];
+ bc_get_property_vector(b, "restpose_loc", ploc, V0);
+ loc[0] += ploc[0];
+ loc[1] += ploc[1];
+ loc[2] += ploc[2];
+ }
+ }
+ }
+
+ if (export_settings->keep_bind_info) {
+ if (bc_get_IDProperty(bone, "restpose_rot_x"))
+ rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
+ if (bc_get_IDProperty(bone, "restpose_rot_y"))
+ rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
+ if (bc_get_IDProperty(bone, "restpose_rot_z"))
+ rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
+ }
+
+ if (export_settings->keep_bind_info) {
+ bc_get_property_vector(bone, "restpose_scale", scale, scale);
+ }
+
+ loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
+
+}
+
+/*
+ Make 4*4 matrices better readable
+*/
+void bc_sanitize_mat(float mat[4][4], int precision)
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ mat[i][j] = double_round(mat[i][j], precision);
+}
+
+/*
+* Returns name of Active UV Layer or empty String if no active UV Layer defined.
+* Assuming the Object is of type MESH
+*/
+std::string bc_get_active_uvlayer_name(Object *ob)
+{
+ Mesh *me = (Mesh *)ob->data;
+ return bc_get_active_uvlayer_name(me);
+}
+
+/*
+ * Returns name of Active UV Layer or empty String if no active UV Layer defined
+ */
+std::string bc_get_active_uvlayer_name(Mesh *me)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers) {
+ return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
+ }
+ return "";
+}
+
+/*
+ * Returns UV Layer name or empty string if layer index is out of range
+ */
+std::string bc_get_uvlayer_name(Mesh *me, int layer)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers && layer < num_layers) {
+ return std::string(bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer));
+ }
+ return "";
+}
+
+/**********************************************************************
+*
+* Return the list of Mesh objects with assigned UVtextures and Images
+* Note: We need to create artificaial materials for each of them
+*
+***********************************************************************/
+std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
+{
+ std::set <Object *> UVObjects;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ has_uvimage = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (has_uvimage) {
+ UVObjects.insert(ob);
+ }
+ }
+ base = base->next;
+ }
+ return UVObjects;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images from all exported Mesh Items
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ base = base->next;
+ }
+ return UVImages;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images for the given Object
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ return UVImages;
+} \ No newline at end of file
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 7fdbef3b6cb..5447c39e902 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -34,6 +34,7 @@
#include <vector>
#include <map>
+#include <set>
#include <algorithm>
extern "C" {
@@ -53,8 +54,10 @@ extern "C" {
#include "BKE_object.h"
#include "BKE_DerivedMesh.h"
#include "BKE_scene.h"
+#include "BKE_idprop.h"
}
+#include "ImportSettings.h"
#include "ExportSettings.h"
#include "collada_internal.h"
@@ -78,6 +81,7 @@ extern void bc_set_mark(Object *ob);
extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n);
extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type);
+extern char *bc_CustomData_get_layer_name(const CustomData *data, int layer_index, int type);
extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
@@ -88,11 +92,32 @@ extern std::string bc_url_encode(std::string data);
extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene);
extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene);
+extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size);
+
extern void bc_triangulate_mesh(Mesh *me);
extern bool bc_is_leaf_bone(Bone *bone);
extern EditBone *bc_get_edit_bone(bArmature * armature, char *name);
extern int bc_set_layer(int bitfield, int layer, bool enable);
extern int bc_set_layer(int bitfield, int layer);
+extern void bc_sanitize_mat(float mat[4][4], int precision);
+
+extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key);
+extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value);
+extern void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]);
+
+extern float bc_get_property(Bone *bone, std::string key, float def);
+extern void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]);
+extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]);
+
+extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
+
+extern std::string bc_get_active_uvlayer_name(Object *ob);
+extern std::string bc_get_active_uvlayer_name(Mesh *me);
+extern std::string bc_get_uvlayer_name(Mesh *me, int layer);
+
+extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers);
+extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers);
+extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers);
class BCPolygonNormalsIndices
{
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 3180e7e4154..3e1dd83112a 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -551,8 +551,4 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
- add_definitions(-DWITH_CYCLES_DEBUG)
-endif()
-
blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index a5d7704a708..3b24f9c69a2 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -331,19 +331,6 @@ void COM_deinitialize(void);
*/
// void COM_clearCaches(void); // NOT YET WRITTEN
-/**
- * @brief Return a list of highlighted bnodes pointers.
- * @return
- */
-void COM_startReadHighlights(void);
-
-/**
- * @brief check if a bnode is highlighted
- * @param bnode
- * @return
- */
-int COM_isHighlightedbNode(bNode *bnode);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index 39147f3ab84..68f934008a4 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -75,82 +75,6 @@ static bool g_openclInitialized = false;
#endif
#endif
-#define MAX_HIGHLIGHT 8
-static bool g_highlightInitialized = false;
-extern "C" {
-static int g_highlightIndex;
-static void **g_highlightedNodes;
-static void **g_highlightedNodesRead;
-
-/* XXX highlighting disabled for now
- * This requires pointers back to DNA data (bNodeTree/bNode) in operations, which is bad!
- * Instead IF we want to keep this feature it should use a weak reference such as bNodeInstanceKey
- */
-#if 0
-#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
-#define HIGHLIGHT(wp) \
-{ \
- ExecutionGroup *group = wp->getExecutionGroup(); \
- if (group->isComplex()) { \
- NodeOperation *operation = group->getOutputOperation(); \
- if (operation->isWriteBufferOperation()) { \
- WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation; \
- NodeOperation *complexOperation = writeOperation->getInput(); \
- bNode *node = complexOperation->getbNode(); \
- if (node) { \
- if (node->original) { \
- node = node->original; \
- } \
- if (g_highlightInitialized && g_highlightedNodes) { \
- if (g_highlightIndex < MAX_HIGHLIGHT) { \
- g_highlightedNodes[g_highlightIndex++] = node; \
- } \
- } \
- } \
- } \
- } \
-}
-#endif /* COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE */
-#else
-# if COM_CURRENT_THREADING_MODEL != COM_TM_NOTHREAD
-#define HIGHLIGHT(wp) {}
-# endif
-#endif
-
-void COM_startReadHighlights()
-{
- if (!g_highlightInitialized) {
- return;
- }
-
- if (g_highlightedNodesRead) {
- MEM_freeN(g_highlightedNodesRead);
- }
-
- g_highlightedNodesRead = g_highlightedNodes;
- g_highlightedNodes = (void **)MEM_callocN(sizeof(void *) * MAX_HIGHLIGHT, __func__);
- g_highlightIndex = 0;
-}
-
-int COM_isHighlightedbNode(bNode *bnode)
-{
- if (!g_highlightInitialized) {
- return false;
- }
-
- if (!g_highlightedNodesRead) {
- return false;
- }
-
- for (int i = 0; i < MAX_HIGHLIGHT; i++) {
- void *p = g_highlightedNodesRead[i];
- if (!p) return false;
- if (p == bnode) return true;
- }
- return false;
-}
-} // end extern "C"
-
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
void *WorkScheduler::thread_execute_cpu(void *data)
{
@@ -158,7 +82,6 @@ void *WorkScheduler::thread_execute_cpu(void *data)
WorkPackage *work;
BLI_thread_local_set(g_thread_device, device);
while ((work = (WorkPackage *)BLI_thread_queue_pop(g_cpuqueue))) {
- HIGHLIGHT(work);
device->execute(work);
delete work;
}
@@ -172,7 +95,6 @@ void *WorkScheduler::thread_execute_gpu(void *data)
WorkPackage *work;
while ((work = (WorkPackage *)BLI_thread_queue_pop(g_gpuqueue))) {
- HIGHLIGHT(work);
device->execute(work);
delete work;
}
@@ -289,19 +211,6 @@ static void CL_CALLBACK clContextError(const char *errinfo,
void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads)
{
- /* initialize highlighting */
- if (!g_highlightInitialized) {
- if (g_highlightedNodesRead) MEM_freeN(g_highlightedNodesRead);
- if (g_highlightedNodes) MEM_freeN(g_highlightedNodes);
-
- g_highlightedNodesRead = NULL;
- g_highlightedNodes = NULL;
-
- COM_startReadHighlights();
-
- g_highlightInitialized = true;
- }
-
#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE
/* deinitialize if number of threads doesn't match */
if (g_cpudevices.size() != num_cpu_threads) {
@@ -439,20 +348,6 @@ void WorkScheduler::deinitialize()
}
#endif
#endif
-
- /* deinitialize highlighting */
- if (g_highlightInitialized) {
- g_highlightInitialized = false;
- if (g_highlightedNodes) {
- MEM_freeN(g_highlightedNodes);
- g_highlightedNodes = NULL;
- }
-
- if (g_highlightedNodesRead) {
- MEM_freeN(g_highlightedNodesRead);
- g_highlightedNodesRead = NULL;
- }
- }
}
int WorkScheduler::current_thread_id()
diff --git a/source/blender/compositor/nodes/COM_BrightnessNode.cpp b/source/blender/compositor/nodes/COM_BrightnessNode.cpp
index 053f286c66e..6729571fac0 100644
--- a/source/blender/compositor/nodes/COM_BrightnessNode.cpp
+++ b/source/blender/compositor/nodes/COM_BrightnessNode.cpp
@@ -31,7 +31,9 @@ BrightnessNode::BrightnessNode(bNode *editorNode) : Node(editorNode)
void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
+ bNode *bnode = this->getbNode();
BrightnessOperation *operation = new BrightnessOperation();
+ operation->setUsePremultiply((bnode->custom1 & 1) != 0);
converter.addOperation(operation);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index facd422c217..81891d853d2 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -95,17 +95,14 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
NodeOperation *operation = NULL;
socket = this->getOutputSocket(index);
bNodeSocket *bnodeSocket = socket->getbNodeSocket();
- RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name));
+ NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
+ RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name));
int view = 0;
- /* 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
+ if (STREQ(storage->pass_name, RE_PASSNAME_COMBINED) && STREQ(bnodeSocket->name, "Alpha")) {
+ /* Alpha output is already handled with the associated combined output. */
+ continue;
+ }
/* returns the image view to use for the current active view */
if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) {
@@ -147,17 +144,25 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
if (index == 0 && operation) {
converter.addPreview(operation->getOutputSocket());
}
- if (rpass->passtype == SCE_PASS_COMBINED) {
- BLI_assert(operation != NULL);
- BLI_assert(index < numberOfOutputs - 1);
- NodeOutput *outputSocket = this->getOutputSocket(index + 1);
- SeparateChannelOperation *separate_operation;
- separate_operation = new SeparateChannelOperation();
- separate_operation->setChannel(3);
- converter.addOperation(separate_operation);
- converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0));
- converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket());
- index++;
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
+ for (int alphaIndex = 0; alphaIndex < numberOfOutputs; alphaIndex++) {
+ NodeOutput *alphaSocket = this->getOutputSocket(alphaIndex);
+ bNodeSocket *bnodeAlphaSocket = alphaSocket->getbNodeSocket();
+ if (!STREQ(bnodeAlphaSocket->name, "Alpha")) {
+ continue;
+ }
+ NodeImageLayer *alphaStorage = (NodeImageLayer *)bnodeSocket->storage;
+ if (!STREQ(alphaStorage->pass_name, RE_PASSNAME_COMBINED)) {
+ continue;
+ }
+ SeparateChannelOperation *separate_operation;
+ separate_operation = new SeparateChannelOperation();
+ separate_operation->setChannel(3);
+ converter.addOperation(separate_operation);
+ converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0));
+ converter.mapOutputSocket(alphaSocket, separate_operation->getOutputSocket());
+ break;
+ }
}
}
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
index 842edcf35c9..75128de2d84 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
@@ -27,76 +27,61 @@
#include "COM_ScaleOperation.h"
#include "COM_SetValueOperation.h"
-#ifdef WITH_CYCLES_DEBUG
-# include "RE_pipeline.h"
-#endif
-
RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
}
void RenderLayersNode::testSocketLink(NodeConverter &converter, const CompositorContext &context,
- int outputSocketNumber, RenderLayersBaseProg *operation) const
+ NodeOutput *output, RenderLayersProg *operation,
+ Scene *scene, int layerId, bool is_preview) const
{
- NodeOutput *outputSocket = this->getOutputSocket(outputSocketNumber);
- Scene *scene = (Scene *)this->getbNode()->id;
- short layerId = this->getbNode()->custom1;
-
operation->setScene(scene);
operation->setLayerId(layerId);
operation->setRenderData(context.getRenderData());
operation->setViewName(context.getViewName());
- converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
+ converter.mapOutputSocket(output, operation->getOutputSocket());
converter.addOperation(operation);
- if (outputSocketNumber == 0) /* only for image socket */
+ if (is_preview) /* only for image socket */
converter.addPreview(operation->getOutputSocket());
}
void RenderLayersNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
- testSocketLink(converter, context, 0, new RenderLayersColorProg());
- testSocketLink(converter, context, 1, new RenderLayersAlphaProg());
- testSocketLink(converter, context, 2, new RenderLayersDepthProg());
- testSocketLink(converter, context, 3, new RenderLayersNormalOperation());
- testSocketLink(converter, context, 4, new RenderLayersUVOperation());
- testSocketLink(converter, context, 5, new RenderLayersSpeedOperation());
- testSocketLink(converter, context, 6, new RenderLayersColorOperation());
- testSocketLink(converter, context, 7, new RenderLayersDiffuseOperation());
- testSocketLink(converter, context, 8, new RenderLayersSpecularOperation());
- testSocketLink(converter, context, 9, new RenderLayersShadowOperation());
- testSocketLink(converter, context, 10, new RenderLayersAOOperation());
- testSocketLink(converter, context, 11, new RenderLayersReflectionOperation());
- testSocketLink(converter, context, 12, new RenderLayersRefractionOperation());
- testSocketLink(converter, context, 13, new RenderLayersIndirectOperation());
- testSocketLink(converter, context, 14, new RenderLayersObjectIndexOperation());
- testSocketLink(converter, context, 15, new RenderLayersMaterialIndexOperation());
- testSocketLink(converter, context, 16, new RenderLayersMistOperation());
- testSocketLink(converter, context, 17, new RenderLayersEmitOperation());
- testSocketLink(converter, context, 18, new RenderLayersEnvironmentOperation());
+ Scene *scene = (Scene *)this->getbNode()->id;
+ short layerId = this->getbNode()->custom1;
+ Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
+ int numberOfOutputs = this->getNumberOfOutputSockets();
- // cycles passes
- testSocketLink(converter, context, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT));
- testSocketLink(converter, context, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT));
- testSocketLink(converter, context, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR));
- testSocketLink(converter, context, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT));
- testSocketLink(converter, context, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT));
- testSocketLink(converter, context, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR));
- testSocketLink(converter, context, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT));
- testSocketLink(converter, context, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT));
- testSocketLink(converter, context, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR));
- testSocketLink(converter, context, 28, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_DIRECT));
- testSocketLink(converter, context, 29, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_INDIRECT));
- testSocketLink(converter, context, 30, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_COLOR));
-
-#ifdef WITH_CYCLES_DEBUG
- {
- Scene *scene = (Scene *)this->getbNode()->id;
- Render *re = RE_GetRender(scene->id.name);
- int debug_pass_type = ((re != NULL) ? RE_debug_pass_type_get(re) : scene->r.debug_pass_type);
- testSocketLink(converter, context, 31, new RenderLayersCyclesDebugOperation(SCE_PASS_DEBUG, debug_pass_type));
+ if (re) {
+ RenderResult *rr = RE_AcquireResultRead(re);
+ if (rr) {
+ SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, layerId);
+ if (srl) {
+ RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
+ if (rl) {
+ for (int i = 0; i < numberOfOutputs; i++) {
+ NodeOutput *output = this->getOutputSocket(i);
+ NodeImageLayer *storage = (NodeImageLayer*) output->getbNodeSocket()->storage;
+ RenderPass *rpass = (RenderPass*) BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name));
+ if (rpass) {
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && STREQ(output->getbNodeSocket()->name, "Alpha")) {
+ testSocketLink(converter, context, output, new RenderLayersAlphaProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false);
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
+ testSocketLink(converter, context, output, new RenderLayersDepthProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false);
+ }
+ else {
+ DataType type = ((rpass->channels == 4)? COM_DT_COLOR : ((rpass->channels == 3)? COM_DT_VECTOR : COM_DT_VALUE));
+ testSocketLink(converter, context, output, new RenderLayersProg(rpass->name, type, rpass->channels), scene, layerId, STREQ(output->getbNodeSocket()->name, "Image"));
+ }
+ }
+ }
+ }
+ }
+ }
+ RE_ReleaseResult(re);
}
-#endif
}
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h
index 5863cbb390c..1f733a9f4bb 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.h
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h
@@ -33,5 +33,11 @@ public:
RenderLayersNode(bNode *editorNode);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
private:
- void testSocketLink(NodeConverter &converter, const CompositorContext &context, int outputSocketNumber, RenderLayersBaseProg *operation) const;
+ void testSocketLink(NodeConverter &converter,
+ const CompositorContext &context,
+ NodeOutput *output,
+ RenderLayersProg *operation,
+ Scene *scene,
+ int layerId,
+ bool is_preview) const;
};
diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.cpp b/source/blender/compositor/operations/COM_BrightnessOperation.cpp
index 33e35c3fe3b..c7ba86b66bc 100644
--- a/source/blender/compositor/operations/COM_BrightnessOperation.cpp
+++ b/source/blender/compositor/operations/COM_BrightnessOperation.cpp
@@ -29,7 +29,14 @@ BrightnessOperation::BrightnessOperation() : NodeOperation()
this->addInputSocket(COM_DT_VALUE);
this->addOutputSocket(COM_DT_COLOR);
this->m_inputProgram = NULL;
+ this->m_use_premultiply = false;
}
+
+void BrightnessOperation::setUsePremultiply(bool use_premultiply)
+{
+ this->m_use_premultiply = use_premultiply;
+}
+
void BrightnessOperation::initExecution()
{
this->m_inputProgram = this->getInputSocketReader(0);
@@ -64,11 +71,16 @@ void BrightnessOperation::executePixelSampled(float output[4], float x, float y,
delta *= -1;
b = a * (brightness + delta);
}
-
+ if (this->m_use_premultiply) {
+ premul_to_straight_v4(inputValue);
+ }
output[0] = a * inputValue[0] + b;
output[1] = a * inputValue[1] + b;
output[2] = a * inputValue[2] + b;
output[3] = inputValue[3];
+ if (this->m_use_premultiply) {
+ straight_to_premul_v4(output);
+ }
}
void BrightnessOperation::deinitExecution()
diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.h b/source/blender/compositor/operations/COM_BrightnessOperation.h
index 22086ae11e8..ff492f2b102 100644
--- a/source/blender/compositor/operations/COM_BrightnessOperation.h
+++ b/source/blender/compositor/operations/COM_BrightnessOperation.h
@@ -34,6 +34,8 @@ private:
SocketReader *m_inputBrightnessProgram;
SocketReader *m_inputContrastProgram;
+ bool m_use_premultiply;
+
public:
BrightnessOperation();
@@ -52,5 +54,6 @@ public:
*/
void deinitExecution();
+ void setUsePremultiply(bool use_premultiply);
};
#endif
diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp
index 325ef83a529..aa58c0571cf 100644
--- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp
+++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp
@@ -65,11 +65,11 @@ void DifferenceMatteOperation::executePixelSampled(float output[4], float x, flo
difference = difference / 3.0f;
/* make 100% transparent */
- if (difference < tolerance) {
+ if (difference <= tolerance) {
output[0] = 0.0f;
}
/*in the falloff region, make partially transparent */
- else if (difference < falloff + tolerance) {
+ else if (difference <= falloff + tolerance) {
difference = difference - tolerance;
alpha = difference / falloff;
/*only change if more transparent than before */
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp
index fb8730c9fa0..d6affa6eee9 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp
@@ -29,8 +29,6 @@
#include "BLI_math_color.h"
extern "C" {
-# include "BLI_jitter.h"
-
# include "BKE_node.h"
}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp
index a56aa0cbaa6..070b7562b2d 100644
--- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp
@@ -29,8 +29,6 @@
#include "BLI_math_color.h"
extern "C" {
-# include "BLI_jitter.h"
-
# include "BKE_movieclip.h"
# include "BKE_node.h"
# include "BKE_tracking.h"
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index 099208ce600..f2f1b211a97 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -34,17 +34,18 @@ extern "C" {
/* ******** Render Layers Base Prog ******** */
-RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation()
+RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elementsize) : NodeOperation(), m_passName(passName)
{
- this->m_renderpass = renderpass;
this->setScene(NULL);
this->m_inputBuffer = NULL;
this->m_elementsize = elementsize;
this->m_rd = NULL;
+
+ this->addOutputSocket(type);
}
-void RenderLayersBaseProg::initExecution()
+void RenderLayersProg::initExecution()
{
Scene *scene = this->getScene();
Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
@@ -59,10 +60,7 @@ void RenderLayersBaseProg::initExecution()
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
if (rl) {
- this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass, this->m_viewName);
- if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) {
- this->m_inputBuffer = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, this->m_viewName);
- }
+ this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_passName.c_str(), this->m_viewName);
}
}
}
@@ -72,7 +70,7 @@ void RenderLayersBaseProg::initExecution()
}
}
-void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
+void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler)
{
unsigned int offset;
int width = this->getWidth(), height = this->getHeight();
@@ -111,7 +109,7 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi
}
}
-void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void RenderLayersProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
#if 0
const RenderData *rd = this->m_rd;
@@ -173,12 +171,12 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y
}
}
-void RenderLayersBaseProg::deinitExecution()
+void RenderLayersProg::deinitExecution()
{
this->m_inputBuffer = NULL;
}
-void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
+void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2])
{
Scene *sce = this->getScene();
Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL;
@@ -207,13 +205,6 @@ void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsig
}
/* ******** Render Layers AO Operation ******** */
-
-RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3)
-{
- this->addOutputSocket(COM_DT_COLOR);
-}
-
-
void RenderLayersAOOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
float *inputBuffer = this->getInputBuffer();
@@ -227,12 +218,6 @@ void RenderLayersAOOperation::executePixelSampled(float output[4], float x, floa
}
/* ******** Render Layers Alpha Operation ******** */
-
-RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4)
-{
- this->addOutputSocket(COM_DT_VALUE);
-}
-
void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
float *inputBuffer = this->getInputBuffer();
@@ -247,27 +232,7 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float
}
}
-/* ******** 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_VECTOR);
-}
-
/* ******** Render Layers Depth Operation ******** */
-
-RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1)
-{
- this->addOutputSocket(COM_DT_VALUE);
-}
-
void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/)
{
int ix = x;
@@ -281,135 +246,4 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float
unsigned int offset = (iy * this->getWidth() + ix);
output[0] = inputBuffer[offset];
}
-}
-
-/* ******** Render Layers Diffuse Operation ******** */
-
-RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
-
-/* ******** Render Layers Emit Operation ******** */
-
-RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
-
-/* ******** Render Layers Environment Operation ******** */
-
-RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
-
-/* ******** 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_VECTOR);
-}
-
-/* ******** 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_VECTOR);
-}
-
-/* ******** Render Layers Refraction Operation ******** */
-
-RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
-
-/* ******** Render Layers Shadow Operation ******** */
-
-RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
-
-/* ******** Render Layers Specular Operation ******** */
-
-RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3)
-{
- this->addOutputSocket(COM_DT_VECTOR);
-}
-
-/* ******** 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);
-}
-
-/* ******** Debug Render Layers Cycles Operation ******** */
-
-#ifdef WITH_CYCLES_DEBUG
-
-RenderLayersCyclesDebugOperation::RenderLayersCyclesDebugOperation(
- int pass,
- int debug_pass_type)
- : RenderLayersBaseProg(pass, RE_debug_pass_num_channels_get(debug_pass_type))
-{
- switch (m_elementsize) {
- case 1:
- this->addOutputSocket(COM_DT_VALUE);
- break;
- case 3:
- this->addOutputSocket(COM_DT_VECTOR);
- break;
- case 4:
- this->addOutputSocket(COM_DT_COLOR);
- break;
- default:
- BLI_assert(!"Unkown debug pass type element size.");
- }
-}
-
-#endif
+} \ No newline at end of file
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index 89eb2a6954d..1be15906770 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -40,7 +40,7 @@ extern "C" {
*
* @todo: rename to operation.
*/
-class RenderLayersBaseProg : public NodeOperation {
+class RenderLayersProg : public NodeOperation {
protected:
/**
* Reference to the scene object.
@@ -65,7 +65,7 @@ protected:
/**
* renderpass where this operation needs to get its data from
*/
- int m_renderpass;
+ std::string m_passName;
int m_elementsize;
@@ -73,11 +73,6 @@ protected:
* @brief render data used for active rendering
*/
const RenderData *m_rd;
-
- /**
- * Constructor
- */
- RenderLayersBaseProg(int renderpass, int elementsize);
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
@@ -92,6 +87,10 @@ protected:
void doInterpolation(float output[4], float x, float y, PixelSampler sampler);
public:
/**
+ * Constructor
+ */
+ RenderLayersProg(const char *passName, DataType type, int elementsize);
+ /**
* setter for the scene field. Will be called from
* @see RenderLayerNode to set the actual scene where
* the data will be retrieved from.
@@ -108,116 +107,25 @@ public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
-class RenderLayersAOOperation : public RenderLayersBaseProg {
+class RenderLayersAOOperation : public RenderLayersProg {
public:
- RenderLayersAOOperation();
+ RenderLayersAOOperation(const char *passName, DataType type, int elementsize)
+ : RenderLayersProg(passName, type, elementsize) {}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
-class RenderLayersAlphaProg : public RenderLayersBaseProg {
+class RenderLayersAlphaProg : public RenderLayersProg {
public:
- RenderLayersAlphaProg();
+ RenderLayersAlphaProg(const char *passName, DataType type, int elementsize)
+ : RenderLayersProg(passName, type, elementsize) {}
void executePixelSampled(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 {
+class RenderLayersDepthProg : public RenderLayersProg {
public:
- RenderLayersDepthProg();
+ RenderLayersDepthProg(const char *passName, DataType type, int elementsize)
+ : RenderLayersProg(passName, type, elementsize) {}
void executePixelSampled(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();
-};
-
-#ifdef WITH_CYCLES_DEBUG
-class RenderLayersCyclesDebugOperation : public RenderLayersBaseProg {
-public:
- RenderLayersCyclesDebugOperation(int pass,
- int debug_pass_type);
-};
-#endif
-
#endif
diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp
index 6bfd8ae3888..d0c72935b16 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.cpp
+++ b/source/blender/compositor/operations/COM_TextureOperation.cpp
@@ -41,6 +41,7 @@ TextureBaseOperation::TextureBaseOperation() : NodeOperation()
this->m_rd = NULL;
this->m_pool = NULL;
this->m_sceneColorManage = false;
+ setComplex(true);
}
TextureOperation::TextureOperation() : TextureBaseOperation()
{
@@ -155,31 +156,3 @@ void TextureBaseOperation::executePixelSampled(float output[4], float x, float y
output[0] = output[1] = output[2] = output[3];
}
}
-
-MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti * /*rect2*/)
-{
- int height = getHeight();
- int width = getWidth();
- DataType datatype = this->getOutputSocket()->getDataType();
- int add = 4;
- if (datatype == COM_DT_VALUE) {
- add = 1;
- }
-
- rcti rect;
- rect.xmin = 0;
- rect.ymin = 0;
- rect.xmax = width;
- rect.ymax = height;
- MemoryBuffer *result = new MemoryBuffer(datatype, &rect);
-
- float *data = result->getBuffer();
-
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++, data += add) {
- this->executePixelSampled(data, x, y, COM_PS_NEAREST);
- }
- }
-
- return result;
-}
diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h
index 4cc203b54a2..59ff58a7289 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.h
+++ b/source/blender/compositor/operations/COM_TextureOperation.h
@@ -59,8 +59,6 @@ protected:
* Constructor
*/
TextureBaseOperation();
-
- MemoryBuffer *createMemoryBuffer(rcti *rect2);
public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index e635256cda6..33a7628c68d 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -87,8 +87,8 @@ set(SRC
intern/depsgraph_intern.h
intern/depsgraph_types.h
+ util/deg_util_foreach.h
util/deg_util_function.h
- util/deg_util_hash.h
)
if(WITH_CXX11)
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index fdc86540171..b65d921cfd1 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -153,7 +153,8 @@ void DEG_add_object_cache_relation(struct DepsNodeHandle *handle,
eDepsObjectComponentType component,
const char *description);
-/* TODO(sergey): Remove once all geometry update is granular. */
+
+struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle);
void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag);
/* Utility functions for physics modifiers */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index cb2f057a090..086fd0c1144 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -30,15 +30,13 @@
#include "intern/builder/deg_builder.h"
-// TODO(sergey): Use own wrapper over STD.
-#include <stack>
-
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_ID.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLI_stack.h"
#include "intern/depsgraph.h"
#include "intern/depsgraph_types.h"
@@ -52,14 +50,6 @@
namespace DEG {
-string deg_fcurve_id_name(const FCurve *fcu)
-{
- char index_buf[32];
- // TODO(sergey): Use int-to-string utility or so.
- BLI_snprintf(index_buf, sizeof(index_buf), "[%d]", fcu->array_index);
- return string(fcu->rna_path) + index_buf;
-}
-
static bool check_object_needs_evaluation(Object *object)
{
if (object->recalc & OB_RECALC_ALL) {
@@ -77,72 +67,79 @@ static bool check_object_needs_evaluation(Object *object)
return false;
}
-void deg_graph_build_finalize(Depsgraph *graph)
+void deg_graph_build_flush_layers(Depsgraph *graph)
{
- /* STEP 1: Make sure new invisible dependencies are ready for use.
- *
- * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
- * to do it ahead of a time and don't spend time on flushing updates on
- * every frame change.
- */
- GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
- {
- if (id_node->layers == 0) {
- ID *id = id_node->id;
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if (check_object_needs_evaluation(object)) {
- id_node->tag_update(graph);
- }
- }
- }
- }
- GHASH_FOREACH_END();
- /* STEP 2: Flush visibility layers from children to parent. */
- std::stack<OperationDepsNode *> stack;
+ BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode*),
+ "DEG flush layers stack");
foreach (OperationDepsNode *node, graph->operations) {
IDDepsNode *id_node = node->owner->owner;
node->done = 0;
node->num_links_pending = 0;
foreach (DepsRelation *rel, node->outlinks) {
- if ((rel->from->type == DEPSNODE_TYPE_OPERATION) &&
+ if ((rel->from->type == DEG_NODE_TYPE_OPERATION) &&
(rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
{
++node->num_links_pending;
}
}
if (node->num_links_pending == 0) {
- stack.push(node);
+ BLI_stack_push(stack, &node);
node->done = 1;
}
node->owner->layers = id_node->layers;
id_node->id->tag |= LIB_TAG_DOIT;
}
- while (!stack.empty()) {
- OperationDepsNode *node = stack.top();
- stack.pop();
+ while (!BLI_stack_is_empty(stack)) {
+ OperationDepsNode *node;
+ BLI_stack_pop(stack, &node);
/* Flush layers to parents. */
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
OperationDepsNode *from = (OperationDepsNode *)rel->from;
from->owner->layers |= node->owner->layers;
}
}
/* Schedule parent nodes. */
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
OperationDepsNode *from = (OperationDepsNode *)rel->from;
if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
BLI_assert(from->num_links_pending > 0);
--from->num_links_pending;
}
if (from->num_links_pending == 0 && from->done == 0) {
- stack.push(from);
+ BLI_stack_push(stack, &from);
from->done = 1;
}
}
}
}
+ BLI_stack_free(stack);
+}
+
+void deg_graph_build_finalize(Depsgraph *graph)
+{
+ /* STEP 1: Make sure new invisible dependencies are ready for use.
+ *
+ * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
+ * to do it ahead of a time and don't spend time on flushing updates on
+ * every frame change.
+ */
+ GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
+ {
+ if (id_node->layers == 0) {
+ ID *id = id_node->id;
+ if (GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ if (check_object_needs_evaluation(object)) {
+ id_node->tag_update(graph);
+ }
+ }
+ }
+ }
+ GHASH_FOREACH_END();
+ /* STEP 2: Flush visibility layers from children to parent. */
+ deg_graph_build_flush_layers(graph);
/* STEP 3: Re-tag IDs for update if it was tagged before the relations
* update tag.
*/
@@ -154,7 +151,7 @@ void deg_graph_build_finalize(Depsgraph *graph)
}
GHASH_FOREACH_END();
- if ((id_node->layers & graph->layers) != 0) {
+ if ((id_node->layers & graph->layers) != 0 || graph->layers == 0) {
ID *id = id_node->id;
if ((id->tag & LIB_TAG_ID_RECALC_ALL) &&
(id->tag & LIB_TAG_DOIT))
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
index bdc030e3810..b8ea8c8e599 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -38,9 +38,7 @@ namespace DEG {
struct Depsgraph;
-/* Get unique identifier for FCurves and Drivers */
-string deg_fcurve_id_name(const FCurve *fcu);
-
void deg_graph_build_finalize(struct Depsgraph *graph);
+void deg_graph_build_flush_layers(struct Depsgraph *graph);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index 9b37aaa12ff..3eed0697b5e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -32,11 +32,9 @@
// TOO(sergey): Use some wrappers over those?
#include <cstdio>
#include <cstdlib>
-#include <stack>
-extern "C" {
#include "BLI_utildefines.h"
-}
+#include "BLI_stack.h"
#include "util/deg_util_foreach.h"
@@ -48,12 +46,6 @@ extern "C" {
namespace DEG {
-struct StackEntry {
- OperationDepsNode *node;
- StackEntry *from;
- DepsRelation *via_relation;
-};
-
void deg_graph_detect_cycles(Depsgraph *graph)
{
enum {
@@ -65,11 +57,19 @@ void deg_graph_detect_cycles(Depsgraph *graph)
NODE_IN_STACK = 2,
};
- std::stack<StackEntry> traversal_stack;
+ struct StackEntry {
+ OperationDepsNode *node;
+ StackEntry *from;
+ DepsRelation *via_relation;
+ };
+
+ BLI_Stack *traversal_stack = BLI_stack_new(sizeof(StackEntry),
+ "DEG detect cycles stack");
+
foreach (OperationDepsNode *node, graph->operations) {
bool has_inlinks = false;
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
has_inlinks = true;
}
}
@@ -78,7 +78,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
entry.node = node;
entry.from = NULL;
entry.via_relation = NULL;
- traversal_stack.push(entry);
+ BLI_stack_push(traversal_stack, &entry);
node->tag = NODE_IN_STACK;
}
else {
@@ -87,13 +87,13 @@ void deg_graph_detect_cycles(Depsgraph *graph)
node->done = 0;
}
- while (!traversal_stack.empty()) {
- StackEntry& entry = traversal_stack.top();
- OperationDepsNode *node = entry.node;
+ while (!BLI_stack_is_empty(traversal_stack)) {
+ StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack);
+ OperationDepsNode *node = entry->node;
bool all_child_traversed = true;
for (int i = node->done; i < node->outlinks.size(); ++i) {
DepsRelation *rel = node->outlinks[i];
- if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
+ if (rel->to->type == DEG_NODE_TYPE_OPERATION) {
OperationDepsNode *to = (OperationDepsNode *)rel->to;
if (to->tag == NODE_IN_STACK) {
printf("Dependency cycle detected:\n");
@@ -102,7 +102,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
node->full_identifier().c_str(),
rel->name);
- StackEntry *current = &entry;
+ StackEntry *current = entry;
while (current->node != to) {
BLI_assert(current != NULL);
printf(" '%s' depends on '%s' through '%s'\n",
@@ -117,9 +117,9 @@ void deg_graph_detect_cycles(Depsgraph *graph)
else if (to->tag == NODE_NOT_VISITED) {
StackEntry new_entry;
new_entry.node = to;
- new_entry.from = &entry;
+ new_entry.from = entry;
new_entry.via_relation = rel;
- traversal_stack.push(new_entry);
+ BLI_stack_push(traversal_stack, &new_entry);
to->tag = NODE_IN_STACK;
all_child_traversed = false;
node->done = i;
@@ -129,9 +129,11 @@ void deg_graph_detect_cycles(Depsgraph *graph)
}
if (all_child_traversed) {
node->tag = NODE_VISITED;
- traversal_stack.pop();
+ BLI_stack_discard(traversal_stack);
}
}
+
+ BLI_stack_free(traversal_stack);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 6b7fb5246ca..55f1f93be6a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -37,11 +37,11 @@
#include "MEM_guardedalloc.h"
-extern "C" {
#include "BLI_blenlib.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+extern "C" {
#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -94,13 +94,13 @@ extern "C" {
#include "BKE_tracking.h"
#include "BKE_world.h"
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-
#include "RNA_access.h"
#include "RNA_types.h"
} /* extern "C" */
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "intern/builder/deg_builder.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
@@ -160,55 +160,14 @@ DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
{
}
-RootDepsNode *DepsgraphNodeBuilder::add_root_node()
-{
- return m_graph->add_root_node();
-}
-
IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
{
return m_graph->add_id_node(id, id->name);
}
-TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id)
+TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source()
{
- /* determine which node to attach timesource to */
- if (id) {
-#if 0 /* XXX TODO */
- /* get ID node */
- IDDepsNode id_node = m_graph->find_id_node(id);
-
- /* depends on what this is... */
- switch (GS(id->name)) {
- case ID_SCE: /* Scene - Usually sequencer strip causing time remapping... */
- {
- // TODO...
- }
- break;
-
- case ID_GR: /* Group */
- {
- // TODO...
- }
- break;
-
- // XXX: time source...
-
- default: /* Unhandled */
- printf("%s(): Unhandled ID - %s \n", __func__, id->name);
- break;
- }
-#endif
- }
- else {
- /* root-node */
- RootDepsNode *root_node = m_graph->root_node;
- if (root_node) {
- return root_node->add_time_source("Time Source");
- }
- }
-
- return NULL;
+ return m_graph->add_time_source();
}
ComponentDepsNode *DepsgraphNodeBuilder::add_component_node(
@@ -224,8 +183,7 @@ ComponentDepsNode *DepsgraphNodeBuilder::add_component_node(
OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ComponentDepsNode *comp_node,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
@@ -234,7 +192,7 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
name,
name_tag);
if (op_node == NULL) {
- op_node = comp_node->add_operation(optype, op, opcode, name, name_tag);
+ op_node = comp_node->add_operation(op, opcode, name, name_tag);
m_graph->operations.push_back(op_node);
}
else {
@@ -252,21 +210,19 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
{
ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name);
- return add_operation_node(comp_node, optype, op, opcode, name, name_tag);
+ return add_operation_node(comp_node, op, opcode, name, name_tag);
}
OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
ID *id,
eDepsNode_Type comp_type,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
@@ -274,7 +230,6 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
return add_operation_node(id,
comp_type,
"",
- optype,
op,
opcode,
name,
@@ -352,41 +307,6 @@ void DepsgraphNodeBuilder::build_group(Scene *scene,
}
}
-SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
-{
- /* sanity checks */
- if (!group)
- return NULL;
-
- /* create new subgraph's data */
- Depsgraph *subgraph = reinterpret_cast<Depsgraph *>(DEG_graph_new());
-
- DepsgraphNodeBuilder subgraph_builder(m_bmain, subgraph);
-
- /* add group objects */
- LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
- /*Object *ob = go->ob;*/
-
- /* Each "group object" is effectively a separate instance of the
- * underlying object data. When the group is evaluated, the transform
- * results and/or some other attributes end up getting overridden by
- * the group.
- */
- }
-
- /* Create a node for representing subgraph. */
- SubgraphDepsNode *subgraph_node = m_graph->add_subgraph_node(&group->id);
- subgraph_node->graph = subgraph;
-
- /* Make a copy of the data this node will need? */
- /* XXX: do we do this now, or later? */
- /* TODO: need API function which queries graph's ID's hash, and duplicates
- * those blocks thoroughly with all outside links removed.
- */
-
- return subgraph_node;
-}
-
void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
{
const bool has_object = (ob->id.tag & LIB_TAG_DOIT);
@@ -427,12 +347,11 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
BuilderWalkUserData data;
data.builder = this;
data.scene = scene;
- modifiers_foreachObjectLink(ob, modifier_walk, &data);
BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
}
/* Object data. */
- if (ob->data) {
+ if (ob->data != NULL) {
/* type-specific data... */
switch (ob->type) {
case OB_MESH: /* Geometry */
@@ -490,27 +409,41 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
build_animdata(&ob->id);
/* particle systems */
- if (ob->particlesystem.first) {
+ if (ob->particlesystem.first != NULL) {
build_particles(scene, ob);
}
- /* grease pencil */
- if (ob->gpd) {
+ /* Grease pencil. */
+ if (ob->gpd != NULL) {
build_gpencil(ob->gpd);
}
+
+ /* Object that this is a proxy for. */
+ if (ob->proxy) {
+ ob->proxy->proxy_from = ob;
+ build_object(scene, base, ob->proxy);
+ }
+
+ /* Object dupligroup. */
+ if (ob->dup_group != NULL) {
+ build_group(scene, base, ob->dup_group);
+ }
}
void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
{
+ OperationDepsNode *op_node;
+
/* local transforms (from transform channels - loc/rot/scale + deltas) */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_INIT, function_bind(BKE_object_eval_local_transform, _1, scene, ob),
- DEG_OPCODE_TRANSFORM_LOCAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_local_transform, _1, scene, ob),
+ DEG_OPCODE_TRANSFORM_LOCAL);
+ op_node->set_as_entry();
/* object parent */
if (ob->parent) {
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_parent, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_parent, _1, scene, ob),
DEG_OPCODE_TRANSFORM_PARENT);
}
@@ -526,14 +459,15 @@ void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
*
* TODO(sergey): Get rid of this node.
*/
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_uber_transform, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_uber_transform, _1, scene, ob),
DEG_OPCODE_OBJECT_UBEREVAL);
/* object transform is done */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_POST, function_bind(BKE_object_eval_done, _1, ob),
- DEG_OPCODE_TRANSFORM_FINAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_done, _1, ob),
+ DEG_OPCODE_TRANSFORM_FINAL);
+ op_node->set_as_exit();
}
/**
@@ -556,8 +490,8 @@ void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
void DepsgraphNodeBuilder::build_object_constraints(Scene *scene, Object *ob)
{
/* create node for constraint stack */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_constraints, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_object_eval_constraints, _1, scene, ob),
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
}
@@ -579,8 +513,8 @@ void DepsgraphNodeBuilder::build_animdata(ID *id)
/* actions and NLA - as a single unit for now, as it gets complicated to schedule otherwise */
if ((adt->action) || (adt->nla_tracks.first)) {
/* create the node */
- add_operation_node(id, DEPSNODE_TYPE_ANIMATION,
- DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_animdata, _1, id),
+ add_operation_node(id, DEG_NODE_TYPE_ANIMATION,
+ function_bind(BKE_animsys_eval_animdata, _1, id),
DEG_OPCODE_ANIMATION, id->name);
// TODO: for each channel affected, we might also want to add some support for running RNA update callbacks on them
@@ -610,18 +544,17 @@ OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
* and use some tagging magic instead.
*/
OperationDepsNode *driver_op = find_operation_node(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
- fcu->rna_path,
+ fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
if (driver_op == NULL) {
driver_op = add_operation_node(id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC,
+ DEG_NODE_TYPE_PARAMETERS,
function_bind(BKE_animsys_eval_driver, _1, id, fcu),
DEG_OPCODE_DRIVER,
- fcu->rna_path,
+ fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
}
@@ -642,12 +575,13 @@ void DepsgraphNodeBuilder::build_world(World *world)
return;
}
- /* world itself */
- add_id_node(world_id); /* world shading/params? */
-
build_animdata(world_id);
- /* TODO: other settings? */
+ /* world itself */
+ add_component_node(world_id, DEG_NODE_TYPE_PARAMETERS);
+
+ add_operation_node(world_id, DEG_NODE_TYPE_PARAMETERS, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
/* textures */
build_texture_stack(world->mtex);
@@ -682,14 +616,14 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
/* XXX: is this the right component, or do we want to use another one instead? */
/* init/rebuild operation */
- /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_REBUILD, function_bind(BKE_rigidbody_rebuild_sim, _1, scene),
+ /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_rebuild_sim, _1, scene),
DEG_OPCODE_RIGIDBODY_REBUILD);
/* do-sim operation */
// XXX: what happens if we need to split into several groups?
- OperationDepsNode *sim_node = add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_SIM, function_bind(BKE_rigidbody_eval_simulation, _1, scene),
+ OperationDepsNode *sim_node = add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_eval_simulation, _1, scene),
DEG_OPCODE_RIGIDBODY_SIM);
/* XXX: For now, the sim node is the only one that really matters here. If any other
@@ -709,8 +643,8 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
/* 2) create operation for flushing results */
/* object's transform component - where the rigidbody operation lives */
- add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM,
- DEPSOP_TYPE_EXEC, function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob),
DEG_OPCODE_TRANSFORM_RIGIDBODY);
}
}
@@ -734,7 +668,8 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
*/
/* component for all particle systems */
- ComponentDepsNode *psys_comp = add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
+ ComponentDepsNode *psys_comp =
+ add_component_node(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
/* particle systems */
LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
@@ -747,11 +682,11 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
/* this particle system */
// TODO: for now, this will just be a placeholder "ubereval" node
add_operation_node(psys_comp,
- DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval,
- _1,
- scene,
- ob,
- psys),
+ function_bind(BKE_particle_system_eval,
+ _1,
+ scene,
+ ob,
+ psys),
DEG_OPCODE_PSYS_EVAL,
psys->name);
}
@@ -760,12 +695,25 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
// TODO...
}
+void DepsgraphNodeBuilder::build_cloth(Scene *scene, Object *object)
+{
+ ComponentDepsNode *cache_comp = add_component_node(&object->id,
+ DEG_NODE_TYPE_CACHE);
+ add_operation_node(cache_comp,
+ function_bind(BKE_object_eval_cloth,
+ _1,
+ scene,
+ object),
+ DEG_OPCODE_PLACEHOLDER,
+ "Cloth Modifier");
+}
+
/* Shapekeys */
void DepsgraphNodeBuilder::build_shapekeys(Key *key)
{
build_animdata(&key->id);
- add_operation_node(&key->id, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(&key->id, DEG_NODE_TYPE_GEOMETRY, NULL,
DEG_OPCODE_PLACEHOLDER, "Shapekey Eval");
}
@@ -774,18 +722,19 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key)
void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
{
ID *obdata = (ID *)ob->data;
+ OperationDepsNode *op_node;
/* TODO(sergey): This way using this object's properties as driver target
* works fine.
*
* Does this depend on other nodes?
*/
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_POST,
- NULL,
- DEG_OPCODE_PLACEHOLDER,
- "Parameters Eval");
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "Parameters Eval");
+ op_node->set_as_exit();
/* Temporary uber-update node, which does everything.
* It is for the being we're porting old dependencies into the new system.
@@ -794,48 +743,34 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
*
* TODO(sergey): Get rid of this node.
*/
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_POST,
- function_bind(BKE_object_eval_uber_data, _1, scene, ob),
- DEG_OPCODE_GEOMETRY_UBEREVAL);
-
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- NULL,
- DEG_OPCODE_PLACEHOLDER,
- "Eval Init");
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_object_eval_uber_data, _1, scene, ob),
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+ op_node->set_as_exit();
+
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "Eval Init");
+ op_node->set_as_entry();
// TODO: "Done" operation
- /* Modifiers */
+ /* Cloyth modifier. */
LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_EXEC,
- function_bind(BKE_object_eval_modifier,
- _1,
- scene,
- ob,
- md),
- DEG_OPCODE_GEOMETRY_MODIFIER,
- md->name);
+ if (md->type == eModifierType_Cloth) {
+ build_cloth(scene, ob);
+ }
}
/* materials */
- if (ob->totcol != 0) {
- for (int a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
- if (ma != NULL) {
- build_material(ma);
- }
+ for (int a = 1; a <= ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a);
+ if (ma != NULL) {
+ build_material(ma);
}
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_SHADING,
- DEPSOP_TYPE_EXEC,
- NULL,
- DEG_OPCODE_PLACEHOLDER, "Material Update");
}
/* geometry collision */
@@ -864,14 +799,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
//Mesh *me = (Mesh *)ob->data;
/* evaluation operations */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_mesh_eval_geometry,
- _1,
- (Mesh *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_mesh_eval_geometry,
+ _1,
+ (Mesh *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
break;
}
@@ -883,14 +818,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
if (mom == ob) {
/* metaball evaluation operations */
/* NOTE: only the motherball gets evaluated! */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_mball_eval_geometry,
- _1,
- (MetaBall *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_mball_eval_geometry,
+ _1,
+ (MetaBall *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
}
break;
}
@@ -901,20 +836,19 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
{
/* Curve/nurms evaluation operations. */
/* - calculate curve geometry (including path) */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_curve_eval_geometry,
- _1,
- (Curve *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_curve_eval_geometry,
+ _1,
+ (Curve *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
/* Calculate curve path - this is used by constraints, etc. */
if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_EXEC,
+ DEG_NODE_TYPE_GEOMETRY,
function_bind(BKE_curve_eval_path,
_1,
(Curve *)obdata),
@@ -941,24 +875,24 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
case OB_LATTICE:
{
/* Lattice evaluation operations. */
- add_operation_node(obdata,
- DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_lattice_eval_geometry,
- _1,
- (Lattice *)obdata),
- DEG_OPCODE_PLACEHOLDER,
- "Geometry Eval");
+ op_node = add_operation_node(obdata,
+ DEG_NODE_TYPE_GEOMETRY,
+ function_bind(BKE_lattice_eval_geometry,
+ _1,
+ (Lattice *)obdata),
+ DEG_OPCODE_PLACEHOLDER,
+ "Geometry Eval");
+ op_node->set_as_entry();
break;
}
}
- add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY,
- DEPSOP_TYPE_POST, NULL,
- DEG_OPCODE_PLACEHOLDER, "Eval Done");
+ op_node = add_operation_node(obdata, DEG_NODE_TYPE_GEOMETRY, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Eval Done");
+ op_node->set_as_exit();
/* Parameters for driver sources. */
- add_operation_node(obdata, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(obdata, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
}
@@ -974,15 +908,13 @@ void DepsgraphNodeBuilder::build_camera(Object *ob)
build_animdata(&cam->id);
- add_operation_node(camera_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(camera_id, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
if (cam->dof_ob != NULL) {
/* TODO(sergey): For now parametrs are on object level. */
- add_operation_node(&ob->id, DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC, NULL,
- DEG_OPCODE_PLACEHOLDER,
- "Camera DOF");
+ add_operation_node(&ob->id, DEG_NODE_TYPE_PARAMETERS, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Camera DOF");
}
}
@@ -998,10 +930,10 @@ void DepsgraphNodeBuilder::build_lamp(Object *ob)
build_animdata(&la->id);
/* node for obdata */
- add_component_node(lamp_id, DEPSNODE_TYPE_PARAMETERS);
+ add_component_node(lamp_id, DEG_NODE_TYPE_PARAMETERS);
/* TODO(sergey): Is it really how we're supposed to work with drivers? */
- add_operation_node(lamp_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(lamp_id, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
/* lamp's nodetree */
@@ -1020,12 +952,14 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
/* nodetree itself */
ID *ntree_id = &ntree->id;
+ OperationDepsNode *op_node;
build_animdata(ntree_id);
/* Parameters for drivers. */
- add_operation_node(ntree_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_POST, NULL,
- DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+ op_node = add_operation_node(ntree_id, DEG_NODE_TYPE_PARAMETERS, NULL,
+ DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+ op_node->set_as_exit();
/* nodetree's nodes... */
LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
@@ -1064,8 +998,7 @@ void DepsgraphNodeBuilder::build_material(Material *ma)
/* material itself */
add_id_node(ma_id);
- add_operation_node(ma_id, DEPSNODE_TYPE_SHADING,
- DEPSOP_TYPE_EXEC, NULL,
+ add_operation_node(ma_id, DEG_NODE_TYPE_SHADING, NULL,
DEG_OPCODE_PLACEHOLDER, "Material Update");
/* material animation */
@@ -1121,8 +1054,7 @@ void DepsgraphNodeBuilder::build_image(Image *image) {
add_id_node(image_id);
/* Placeholder so we can add relations and tag ID node for update. */
add_operation_node(image_id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC,
+ DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
"Image Eval");
@@ -1133,10 +1065,10 @@ void DepsgraphNodeBuilder::build_compositor(Scene *scene)
/* For now, just a plain wrapper? */
// TODO: create compositing component?
// XXX: component type undefined!
- //graph->get_node(&scene->id, NULL, DEPSNODE_TYPE_COMPOSITING, NULL);
+ //graph->get_node(&scene->id, NULL, DEG_NODE_TYPE_COMPOSITING, NULL);
/* for now, nodetrees are just parameters; compositing occurs in internals of renderer... */
- add_component_node(&scene->id, DEPSNODE_TYPE_PARAMETERS);
+ add_component_node(&scene->id, DEG_NODE_TYPE_PARAMETERS);
build_nodetree(scene->nodetree);
}
@@ -1158,9 +1090,8 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
{
ID *cache_file_id = &cache_file->id;
- add_component_node(cache_file_id, DEPSNODE_TYPE_CACHE);
- add_operation_node(cache_file_id, DEPSNODE_TYPE_CACHE,
- DEPSOP_TYPE_EXEC, NULL,
+ add_component_node(cache_file_id, DEG_NODE_TYPE_CACHE);
+ add_operation_node(cache_file_id, DEG_NODE_TYPE_CACHE, NULL,
DEG_OPCODE_PLACEHOLDER, "Cache File Update");
add_id_node(cache_file_id);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index c5035f35f6e..a54b1c76c77 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -61,8 +61,6 @@ namespace DEG {
struct Depsgraph;
struct DepsNode;
-struct RootDepsNode;
-struct SubgraphDepsNode;
struct IDDepsNode;
struct TimeSourceDepsNode;
struct ComponentDepsNode;
@@ -74,32 +72,28 @@ struct DepsgraphNodeBuilder {
void begin_build(Main *bmain);
- RootDepsNode *add_root_node();
IDDepsNode *add_id_node(ID *id);
- TimeSourceDepsNode *add_time_source(ID *id);
+ TimeSourceDepsNode *add_time_source();
ComponentDepsNode *add_component_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name = "");
OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name = "",
int name_tag = -1);
OperationDepsNode *add_operation_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name = "",
int name_tag = -1);
OperationDepsNode *add_operation_node(ID *id,
eDepsNode_Type comp_type,
- eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name = "",
int name_tag = -1);
@@ -125,14 +119,14 @@ struct DepsgraphNodeBuilder {
int name_tag = -1);
void build_scene(Main *bmain, Scene *scene);
- SubgraphDepsNode *build_subgraph(Group *group);
void build_group(Scene *scene, Base *base, Group *group);
void build_object(Scene *scene, Base *base, Object *ob);
void build_object_transform(Scene *scene, Object *ob);
void build_object_constraints(Scene *scene, Object *ob);
- void build_pose_constraints(Object *ob, bPoseChannel *pchan);
+ void build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan);
void build_rigidbody(Scene *scene);
void build_particles(Scene *scene, Object *ob);
+ void build_cloth(Scene *scene, Object *object);
void build_animdata(ID *id);
OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
void build_ik_pose(Scene *scene,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index f2437ce1fac..fe7ccaa7fc0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -37,11 +37,11 @@
#include "MEM_guardedalloc.h"
-extern "C" {
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
+extern "C" {
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
@@ -49,10 +49,10 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/nodes/deg_node.h"
@@ -64,11 +64,11 @@ extern "C" {
namespace DEG {
-void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan)
+void DepsgraphNodeBuilder::build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan)
{
/* create node for constraint stack */
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ function_bind(BKE_pose_constraints_evaluate, _1, scene, ob, pchan),
DEG_OPCODE_BONE_CONSTRAINTS);
}
@@ -80,15 +80,15 @@ void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel
/* Find the chain's root. */
bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
- if (has_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+ if (has_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
DEG_OPCODE_POSE_IK_SOLVER))
{
return;
}
/* Operation node for evaluating/running IK Solver. */
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
- DEPSOP_TYPE_SIM, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
+ function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan),
DEG_OPCODE_POSE_IK_SOLVER);
}
@@ -103,8 +103,8 @@ void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseCh
/* Operation node for evaluating/running Spline IK Solver.
* Store the "root bone" of this chain in the solver, so it knows where to start.
*/
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
- DEPSOP_TYPE_SIM, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan),
+ add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
+ function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan),
DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
}
@@ -112,6 +112,7 @@ void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseCh
void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
{
bArmature *arm = (bArmature *)ob->data;
+ OperationDepsNode *op_node;
/* animation and/or drivers linking posebones to base-armature used to define them
* NOTE: AnimData here is really used to control animated deform properties,
@@ -124,8 +125,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
/* Make sure pose is up-to-date with armature updates. */
add_operation_node(&arm->id,
- DEPSNODE_TYPE_PARAMETERS,
- DEPSOP_TYPE_EXEC,
+ DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
"Armature Eval");
@@ -174,34 +174,41 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
*/
/* pose eval context */
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT);
-
- add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE);
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose),
+ DEG_OPCODE_POSE_INIT);
+ op_node->set_as_entry();
+
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose),
+ DEG_OPCODE_POSE_DONE);
+ op_node->set_as_exit();
/* bones */
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
/* node for bone eval */
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local
- DEG_OPCODE_BONE_LOCAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL,
+ DEG_OPCODE_BONE_LOCAL);
+ op_node->set_as_entry();
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan),
DEG_OPCODE_BONE_POSE_PARENT);
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, /* NOTE: dedicated noop for easier relationship construction */
DEG_OPCODE_BONE_READY);
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan),
- DEG_OPCODE_BONE_DONE);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ function_bind(BKE_pose_bone_done, _1, pchan),
+ DEG_OPCODE_BONE_DONE);
+ op_node->set_as_exit();
/* constraints */
if (pchan->constraints.first != NULL) {
- build_pose_constraints(ob, pchan);
+ build_pose_constraints(scene, ob, pchan);
}
/**
@@ -235,6 +242,8 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
{
ID *obdata = (ID *)ob->data;
+ OperationDepsNode *op_node;
+
build_animdata(obdata);
BLI_assert(ob->pose != NULL);
@@ -245,31 +254,28 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
BKE_pose_update_constraint_flags(ob->pose);
}
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_INIT,
- function_bind(BKE_pose_eval_proxy_copy, _1, ob),
- DEG_OPCODE_POSE_INIT);
+ op_node = add_operation_node(&ob->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ function_bind(BKE_pose_eval_proxy_copy, _1, ob),
+ DEG_OPCODE_POSE_INIT);
+ op_node->set_as_entry();
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_INIT, NULL,
- DEG_OPCODE_BONE_LOCAL);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, DEG_OPCODE_BONE_LOCAL);
+ op_node->set_as_entry();
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_EXEC, NULL,
- DEG_OPCODE_BONE_READY);
+ add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, DEG_OPCODE_BONE_READY);
- add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
- DEPSOP_TYPE_POST, NULL,
- DEG_OPCODE_BONE_DONE);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
+ NULL, DEG_OPCODE_BONE_DONE);
+ op_node->set_as_exit();
}
- add_operation_node(&ob->id,
- DEPSNODE_TYPE_EVAL_POSE,
- DEPSOP_TYPE_POST,
- NULL,
- DEG_OPCODE_POSE_DONE);
+ op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE,
+ NULL, DEG_OPCODE_POSE_DONE);
+ op_node->set_as_exit();
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
index 99e61692231..3249867e416 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -37,21 +37,21 @@
#include "MEM_guardedalloc.h"
-extern "C" {
+#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
+extern "C" {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_main.h"
#include "BKE_node.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/nodes/deg_node.h"
@@ -69,7 +69,7 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
add_id_node(&scene->id);
/* timesource */
- add_time_source(NULL);
+ add_time_source();
/* build subgraph for set, and link this in... */
// XXX: depending on how this goes, that scene itself could probably store its
@@ -81,21 +81,7 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
/* scene objects */
LINKLIST_FOREACH (Base *, base, &scene->base) {
Object *ob = base->object;
-
- /* object itself */
build_object(scene, base, ob);
-
- /* object that this is a proxy for */
- // XXX: the way that proxies work needs to be completely reviewed!
- if (ob->proxy) {
- ob->proxy->proxy_from = ob;
- build_object(scene, base, ob->proxy);
- }
-
- /* Object dupligroup. */
- if (ob->dup_group) {
- build_group(scene, base, ob->dup_group);
- }
}
/* rigidbody */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
index f870a33fb68..59eb7ed8cf1 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
@@ -33,10 +33,8 @@
#include <stdio.h>
#include <string.h>
-extern "C" {
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-}
namespace DEG {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 94cff521edc..dbe8a5f1984 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -38,10 +38,10 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+extern "C" {
#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -92,13 +92,13 @@ extern "C" {
#include "BKE_tracking.h"
#include "BKE_world.h"
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-
#include "RNA_access.h"
#include "RNA_types.h"
} /* extern "C" */
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "intern/builder/deg_builder.h"
#include "intern/builder/deg_builder_pchanmap.h"
@@ -113,6 +113,41 @@ extern "C" {
namespace DEG {
+namespace {
+
+struct BuilderWalkUserData {
+ DepsgraphRelationBuilder *builder;
+ Main *bmain;
+ Scene *scene;
+};
+
+static void modifier_walk(void *user_data,
+ struct Object * /*ob*/,
+ struct Object **obpoin,
+ int /*cb_flag*/)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ if (*obpoin) {
+ data->builder->build_object(data->bmain, data->scene, *obpoin);
+ }
+}
+
+void constraint_walk(bConstraint * /*con*/,
+ ID **idpoin,
+ bool /*is_reference*/,
+ void *user_data)
+{
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ if (*idpoin) {
+ ID *id = *idpoin;
+ if (GS(id->name) == ID_OB) {
+ data->builder->build_object(data->bmain, data->scene, (Object *)id);
+ }
+ }
+}
+
+} /* namespace */
+
/* ***************** */
/* Relations Builder */
@@ -163,13 +198,6 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Depsgraph *graph) :
{
}
-RootDepsNode *DepsgraphRelationBuilder::find_node(const RootKey &key) const
-{
- (void)key;
- BLI_assert(!"Doesn't seem to be correct");
- return m_graph->root_node;
-}
-
TimeSourceDepsNode *DepsgraphRelationBuilder::find_node(
const TimeSourceKey &key) const
{
@@ -178,7 +206,7 @@ TimeSourceDepsNode *DepsgraphRelationBuilder::find_node(
return NULL;
}
else {
- return m_graph->root_node->time_source;
+ return m_graph->time_source;
}
}
@@ -247,7 +275,7 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
const char *description)
{
if (timesrc && node_to) {
- m_graph->add_new_relation(timesrc, node_to, DEPSREL_TYPE_TIME, description);
+ m_graph->add_new_relation(timesrc, node_to, description);
}
else {
DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n",
@@ -260,17 +288,16 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
void DepsgraphRelationBuilder::add_operation_relation(
OperationDepsNode *node_from,
OperationDepsNode *node_to,
- eDepsRelation_Type type,
const char *description)
{
if (node_from && node_to) {
- m_graph->add_new_relation(node_from, node_to, type, description);
+ m_graph->add_new_relation(node_from, node_to, description);
}
else {
- DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %d, %s) Failed\n",
+ DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
node_from, (node_from) ? node_from->identifier().c_str() : "<None>",
node_to, (node_to) ? node_to->identifier().c_str() : "<None>",
- type, description);
+ description);
}
}
@@ -283,11 +310,11 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key,
{
Object *ob1 = collobjs[i];
- ComponentKey trf_key(&ob1->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, name);
+ ComponentKey trf_key(&ob1->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(trf_key, key, name);
- ComponentKey coll_key(&ob1->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(coll_key, key, DEPSREL_TYPE_STANDARD, name);
+ ComponentKey coll_key(&ob1->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(coll_key, key, name);
}
if (collobjs)
@@ -301,31 +328,31 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
if (effectors) {
for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
if (eff->ob != ob) {
- ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
+ ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(eff_key, key, name);
}
if (eff->psys) {
if (eff->ob != ob) {
- ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
- add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
+ ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
+ add_relation(eff_key, key, name);
/* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */
- ComponentKey mod_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(mod_key, key, DEPSREL_TYPE_STANDARD, name);
+ ComponentKey mod_key(&eff->ob->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(mod_key, key, name);
}
else if (eff->psys != psys) {
- OperationKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name);
- add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
+ OperationKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name);
+ add_relation(eff_key, key, name);
}
}
if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
- ComponentKey trf_key(&eff->pd->f_source->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain");
+ ComponentKey trf_key(&eff->pd->f_source->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(trf_key, key, "Smoke Force Domain");
- ComponentKey eff_key(&eff->pd->f_source->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain");
+ ComponentKey eff_key(&eff->pd->f_source->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(eff_key, key, "Smoke Force Domain");
}
if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
@@ -337,6 +364,11 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
pdEndEffectors(&effectors);
}
+Depsgraph *DepsgraphRelationBuilder::getGraph()
+{
+ return m_graph;
+}
+
/* **** Functions to build relations between entities **** */
void DepsgraphRelationBuilder::begin_build(Main *bmain)
@@ -363,17 +395,14 @@ void DepsgraphRelationBuilder::build_group(Main *bmain,
ID *group_id = &group->id;
bool group_done = (group_id->tag & LIB_TAG_DOIT) != 0;
OperationKey object_local_transform_key(&object->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_LOCAL);
LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
if (!group_done) {
build_object(bmain, scene, go->ob);
}
- ComponentKey dupli_transform_key(&go->ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dupli_transform_key,
- object_local_transform_key,
- DEPSREL_TYPE_TRANSFORM,
- "Dupligroup");
+ ComponentKey dupli_transform_key(&go->ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
}
group_id->tag |= LIB_TAG_DOIT;
}
@@ -387,39 +416,61 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
/* Object Transforms */
eDepsOperation_Code base_op = (ob->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
- OperationKey base_op_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, base_op);
+ OperationKey base_op_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, base_op);
- OperationKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
- OperationKey parent_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
- OperationKey final_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ OperationKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
+ OperationKey parent_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
+ OperationKey final_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- OperationKey ob_ubereval_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL);
+ OperationKey ob_ubereval_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL);
/* parenting */
- if (ob->parent) {
+ if (ob->parent != NULL) {
/* parent relationship */
build_object_parent(ob);
/* local -> parent */
- add_relation(local_transform_key, parent_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObLocal -> ObParent]");
+ add_relation(local_transform_key, parent_transform_key, "[ObLocal -> ObParent]");
+ }
+
+ if (ob->modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.bmain = bmain;
+ data.scene = scene;
+ modifiers_foreachObjectLink(ob, modifier_walk, &data);
+ }
+ if (ob->constraints.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.bmain = bmain;
+ data.scene = scene;
+ BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
}
/* object constraints */
- if (ob->constraints.first) {
- OperationKey constraint_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+ if (ob->constraints.first != NULL) {
+ OperationKey constraint_key(&ob->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_CONSTRAINTS);
/* constraint relations */
// TODO: provide base op
// XXX: this is broken
- build_constraints(scene, &ob->id, DEPSNODE_TYPE_TRANSFORM, "", &ob->constraints, NULL);
+ build_constraints(scene,
+ &ob->id,
+ DEG_NODE_TYPE_TRANSFORM,
+ "",
+ &ob->constraints,
+ NULL);
/* operation order */
- add_relation(base_op_key, constraint_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObBase-> Constraint Stack]");
- add_relation(constraint_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObConstraints -> Done]");
+ add_relation(base_op_key, constraint_key, "[ObBase-> Constraint Stack]");
+ add_relation(constraint_key, final_transform_key, "[ObConstraints -> Done]");
// XXX
- add_relation(constraint_key, ob_ubereval_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
- add_relation(ob_ubereval_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
+ add_relation(constraint_key, ob_ubereval_key, "Temp Ubereval");
+ add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval");
}
else {
/* NOTE: Keep an eye here, we skip some relations here to "streamline"
@@ -430,28 +481,20 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
/* Rigid body will hook up another node inbetween, so skip
* relation here to avoid transitive relation.
*/
- add_relation(base_op_key,
- ob_ubereval_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "Temp Ubereval");
+ add_relation(base_op_key, ob_ubereval_key, "Temp Ubereval");
}
- add_relation(ob_ubereval_key,
- final_transform_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "Temp Ubereval");
+ add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval");
}
-
/* AnimData */
build_animdata(&ob->id);
// XXX: This should be hooked up by the build_animdata code
if (needs_animdata_node(&ob->id)) {
- ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(adt_key, local_transform_key, DEPSREL_TYPE_OPERATION, "Object Animation");
+ ComponentKey adt_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(adt_key, local_transform_key, "Object Animation");
}
-
/* object data */
if (ob->data) {
ID *obdata_id = (ID *)ob->data;
@@ -492,44 +535,64 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
Key *key = BKE_key_from_object(ob);
if (key != NULL) {
- ComponentKey geometry_key((ID *)ob->data, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(key_key, geometry_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys");
+ ComponentKey geometry_key((ID *)ob->data, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(key_key, geometry_key, "Shapekeys");
}
}
- /* particle systems */
- if (ob->particlesystem.first) {
+ /* Particle systems. */
+ if (ob->particlesystem.first != NULL) {
build_particles(scene, ob);
}
- /* grease pencil */
- if (ob->gpd) {
+ /* Grease pencil. */
+ if (ob->gpd != NULL) {
build_gpencil(ob->gpd);
}
+
+ /* Object that this is a proxy for. */
+ if (ob->proxy != NULL) {
+ ob->proxy->proxy_from = ob;
+ build_object(bmain, scene, ob->proxy);
+ /* TODO(sergey): This is an inverted relation, matches old depsgraph
+ * behavior and need to be investigated if it still need to be inverted.
+ */
+ ComponentKey ob_pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey proxy_pose_key(&ob->proxy->id, DEG_NODE_TYPE_EVAL_POSE);
+ add_relation(ob_pose_key, proxy_pose_key, "Proxy");
+ }
+
+ /* Object dupligroup. */
+ if (ob->dup_group != NULL) {
+ build_group(bmain, scene, ob, ob->dup_group);
+ }
}
void DepsgraphRelationBuilder::build_object_parent(Object *ob)
{
- /* XXX: for now, need to use the component key (not just direct to the parent op), or else the matrix doesn't get reset */
- // XXX: @sergey - it would be good if we got that backwards flushing working when tagging for updates
- //OperationKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
- ComponentKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
+ /* XXX: for now, need to use the component key (not just direct to the parent op),
+ * or else the matrix doesn't get reset/
+ */
+ // XXX: @sergey - it would be good if we got that backwards flushing working
+ // when tagging for updates.
+ //OperationKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
+ ComponentKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
/* type-specific links */
switch (ob->partype) {
case PARSKEL: /* Armature Deform (Virtual Modifier) */
{
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Armature Deform Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, "Armature Deform Parent");
break;
}
case PARVERT1: /* Vertex Parent */
case PARVERT3:
{
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Vertex Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(parent_key, ob_key, "Vertex Parent");
/* XXX not sure what this is for or how you could be done properly - lukas */
OperationDepsNode *parent_node = find_operation_node(parent_key);
@@ -537,27 +600,21 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
parent_node->customdata_mask |= CD_MASK_ORIGINDEX;
}
- ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Vertex Parent TFM");
+ ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(transform_key, ob_key, "Vertex Parent TFM");
break;
}
case PARBONE: /* Bone Parent */
{
ComponentKey parent_bone_key(&ob->parent->id,
- DEPSNODE_TYPE_BONE,
+ DEG_NODE_TYPE_BONE,
ob->parsubstr);
OperationKey parent_transform_key(&ob->parent->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(parent_bone_key,
- ob_key,
- DEPSREL_TYPE_TRANSFORM,
- "Bone Parent");
- add_relation(parent_transform_key,
- ob_key,
- DEPSREL_TYPE_TRANSFORM,
- "Armature Parent");
+ add_relation(parent_bone_key, ob_key, "Bone Parent");
+ add_relation(parent_transform_key, ob_key, "Armature Parent");
break;
}
@@ -566,33 +623,33 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
if (ob->parent->type == OB_LATTICE) {
/* Lattice Deform Parent - Virtual Modifier */
// XXX: no virtual modifiers should be left!
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- ComponentKey geom_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ ComponentKey geom_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent");
- add_relation(geom_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent Geom");
+ add_relation(parent_key, ob_key, "Lattice Deform Parent");
+ add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
}
else if (ob->parent->type == OB_CURVE) {
Curve *cu = (Curve *)ob->parent->data;
if (cu->flag & CU_PATH) {
/* Follow Path */
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(parent_key, ob_key, "Curve Follow Parent");
- ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow TFM");
+ ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(transform_key, ob_key, "Curve Follow TFM");
}
else {
/* Standard Parent */
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, "Curve Parent");
}
}
else {
/* Standard Parent */
- ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Parent");
+ ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(parent_key, ob_key, "Parent");
}
break;
}
@@ -608,7 +665,7 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
ListBase *constraints, RootPChanMap *root_map)
{
OperationKey constraint_op_key(id, component_type, component_subdata,
- (component_type == DEPSNODE_TYPE_BONE) ? DEG_OPCODE_BONE_CONSTRAINTS : DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+ (component_type == DEG_NODE_TYPE_BONE) ? DEG_OPCODE_BONE_CONSTRAINTS : DEG_OPCODE_TRANSFORM_CONSTRAINTS);
/* add dependencies for each constraint in turn */
for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) {
@@ -631,8 +688,8 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
if (data->depth_ob) {
// DAG_RL_DATA_OB | DAG_RL_OB_OB
- ComponentKey depth_key(&data->depth_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(depth_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey depth_key(&data->depth_ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(depth_key, constraint_op_key, cti->name);
}
}
else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
@@ -641,24 +698,24 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
if (depends_on_camera && scene->camera) {
// DAG_RL_DATA_OB | DAG_RL_OB_OB
- ComponentKey camera_key(&scene->camera->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(camera_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey camera_key(&scene->camera->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(camera_key, constraint_op_key, cti->name);
}
/* TODO(sergey): This is more a TimeSource -> MovieClip -> Constraint dependency chain. */
TimeSourceKey time_src_key;
- add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
+ add_relation(time_src_key, constraint_op_key, "[TimeSrc -> Animation]");
}
else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
/* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint dependency chain. */
TimeSourceKey time_src_key;
- add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
+ add_relation(time_src_key, constraint_op_key, "[TimeSrc -> Animation]");
bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
if (data->cache_file) {
- ComponentKey cache_key(&data->cache_file->id, DEPSNODE_TYPE_CACHE);
- add_relation(cache_key, constraint_op_key, DEPSREL_TYPE_CACHE, cti->name);
+ ComponentKey cache_key(&data->cache_file->id, DEG_NODE_TYPE_CACHE);
+ add_relation(cache_key, constraint_op_key, cti->name);
}
}
else if (cti->get_constraint_targets) {
@@ -675,8 +732,8 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
}
else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
/* these constraints require path geometry data... */
- ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name); // XXX: type = geom_transform
+ ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name); // XXX: type = geom_transform
// TODO: path dependency
}
else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
@@ -695,20 +752,20 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
target_key_opcode = DEG_OPCODE_BONE_DONE;
}
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, target_key_opcode);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_BONE, ct->subtarget, target_key_opcode);
+ add_relation(target_key, constraint_op_key, cti->name);
}
else {
/* different armature - we can safely use the result of that */
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, DEG_OPCODE_BONE_DONE);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_BONE, ct->subtarget, DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, constraint_op_key, cti->name);
}
}
else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
/* vertex group */
/* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name);
+ ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
if (ct->tar->type == OB_MESH) {
OperationDepsNode *node2 = find_operation_node(target_key);
@@ -719,12 +776,12 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
}
else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
/* Constraints which requires the target object surface. */
- ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
/* NOTE: obdata eval now doesn't necessarily depend on the object's transform... */
- ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey target_transform_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
}
else {
/* standard object relation */
@@ -736,19 +793,19 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
* - If however it is a real self targetting case, just make it depend on the
* previous constraint (or the pre-constraint state)...
*/
- if ((ct->tar->type == OB_ARMATURE) && (component_type == DEPSNODE_TYPE_BONE)) {
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ if ((ct->tar->type == OB_ARMATURE) && (component_type == DEG_NODE_TYPE_BONE)) {
+ OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
}
else {
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
+ add_relation(target_key, constraint_op_key, cti->name);
}
}
else {
/* normal object dependency */
- OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
}
}
@@ -762,8 +819,8 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
CONSTRAINT_TYPE_TRANSLIKE))
{
/* TODO(sergey): Add used space check. */
- ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name);
+ ComponentKey target_transform_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
}
}
@@ -781,13 +838,13 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
if (adt == NULL)
return;
- ComponentKey adt_key(id, DEPSNODE_TYPE_ANIMATION);
+ ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
/* animation */
if (adt->action || adt->nla_tracks.first) {
/* wire up dependency to time source */
TimeSourceKey time_src_key;
- add_relation(time_src_key, adt_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]");
+ add_relation(time_src_key, adt_key, "[TimeSrc -> Animation]");
// XXX: Hook up specific update callbacks for special properties which may need it...
@@ -797,9 +854,9 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
/* drivers */
LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) {
OperationKey driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
- fcu->rna_path,
+ fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
/* create the driver's relations to targets */
@@ -821,7 +878,8 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
FCurve *fcu_prev = NULL;
LINKLIST_FOREACH (FCurve *, fcu_candidate, &adt->drivers) {
/* Writing to different RNA paths is */
- if (!STREQ(fcu_candidate->rna_path, fcu->rna_path)) {
+ const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+ if (!STREQ(fcu_candidate->rna_path, rna_path)) {
continue;
}
/* We only do relation from previous fcurve to previous one. */
@@ -837,26 +895,22 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
}
if (fcu_prev != NULL) {
OperationKey prev_driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
- fcu_prev->rna_path,
+ fcu_prev->rna_path ? fcu_prev->rna_path : "",
fcu_prev->array_index);
OperationKey driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
- fcu->rna_path,
+ fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
- add_relation(prev_driver_key,
- driver_key,
- DEPSREL_TYPE_OPERATION,
- "[Driver Order]");
+ add_relation(prev_driver_key, driver_key, "[Driver Order]");
}
}
/* prevent driver from occurring before own animation... */
if (adt->action || adt->nla_tracks.first) {
- add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION,
- "[AnimData Before Drivers]");
+ add_relation(adt_key, driver_key, "[AnimData Before Drivers]");
}
}
}
@@ -865,26 +919,28 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{
ChannelDriver *driver = fcu->driver;
OperationKey driver_key(id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_DRIVER,
- fcu->rna_path,
+ fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
bPoseChannel *pchan = NULL;
+ const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+
/* create dependency between driver and data affected by it */
/* - direct property relationship... */
//RNAPathKey affected_key(id, fcu->rna_path);
- //add_relation(driver_key, affected_key, DEPSREL_TYPE_DRIVER, "[Driver -> Data] DepsRel");
+ //add_relation(driver_key, affected_key, "[Driver -> Data] DepsRel");
/* driver -> data components (for interleaved evaluation - bones/constraints/modifiers) */
// XXX: this probably should probably be moved out into a separate function
- if (strstr(fcu->rna_path, "pose.bones[") != NULL) {
+ if (strstr(rna_path, "pose.bones[") != NULL) {
/* interleaved drivers during bone eval */
// TODO: ideally, if this is for a constraint, it goes to said constraint
Object *ob = (Object *)id;
char *bone_name;
- bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ bone_name = BLI_str_quoted_substrN(rna_path, "pose.bones[");
pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
if (bone_name) {
@@ -893,21 +949,21 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
if (pchan) {
- OperationKey bone_key(id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Driver -> Bone]");
+ OperationKey bone_key(id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ add_relation(driver_key, bone_key, "[Driver -> Bone]");
}
else {
fprintf(stderr,
"Couldn't find bone name for driver path - '%s'\n",
- fcu->rna_path);
+ rna_path);
}
}
- else if (GS(id->name) == ID_AR && strstr(fcu->rna_path, "bones[")) {
+ else if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
/* drivers on armature-level bone settings (i.e. bbone stuff),
* which will affect the evaluation of corresponding pose bones
*/
IDDepsNode *arm_node = m_graph->find_id_node(id);
- char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "bones[");
+ char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
if (arm_node && bone_name) {
/* find objects which use this, and make their eval callbacks depend on this */
@@ -920,8 +976,8 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); // NOTE: ob->pose may be NULL
if (pchan) {
- OperationKey bone_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Arm Bone -> Driver -> Bone]");
+ OperationKey bone_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ add_relation(driver_key, bone_key, "[Arm Bone -> Driver -> Bone]");
}
}
}
@@ -933,48 +989,39 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
else {
fprintf(stderr,
"Couldn't find armature bone name for driver path - '%s'\n",
- fcu->rna_path);
+ rna_path);
}
}
- else if (GS(id->name) == ID_OB && strstr(fcu->rna_path, "modifiers[")) {
- /* modifier driver - connect directly to the modifier */
- char *modifier_name = BLI_str_quoted_substrN(fcu->rna_path, "modifiers[");
- if (modifier_name) {
- OperationKey modifier_key(id,
- DEPSNODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_MODIFIER,
- modifier_name);
- if (has_node(modifier_key)) {
- add_relation(driver_key, modifier_key, DEPSREL_TYPE_DRIVER, "[Driver -> Modifier]");
- }
- else {
- printf("Unexisting driver RNA path: %s\n", fcu->rna_path);
- }
-
- MEM_freeN(modifier_name);
+ else if (GS(id->name) == ID_OB && strstr(rna_path, "modifiers[")) {
+ OperationKey modifier_key(id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
+ if (has_node(modifier_key)) {
+ add_relation(driver_key, modifier_key, "[Driver -> Modifier]");
+ }
+ else {
+ printf("Unexisting driver RNA path: %s\n", rna_path);
}
}
- else if (GS(id->name) == ID_KE && strstr(fcu->rna_path, "key_blocks[")) {
+ else if (GS(id->name) == ID_KE && strstr(rna_path, "key_blocks[")) {
/* shape key driver - hook into the base geometry operation */
// XXX: double check where this points
Key *shape_key = (Key *)id;
- ComponentKey geometry_key(shape_key->from, DEPSNODE_TYPE_GEOMETRY);
- add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
+ ComponentKey geometry_key(shape_key->from, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, "[Driver -> ShapeKey Geom]");
}
- else if (strstr(fcu->rna_path, "key_blocks[")) {
- ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
+ else if (strstr(rna_path, "key_blocks[")) {
+ ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, "[Driver -> ShapeKey Geom]");
}
else {
if (GS(id->name) == ID_OB) {
/* assume that driver affects a transform... */
- OperationKey local_transform_key(id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
- add_relation(driver_key, local_transform_key, DEPSREL_TYPE_OPERATION, "[Driver -> Transform]");
+ OperationKey local_transform_key(id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL);
+ add_relation(driver_key, local_transform_key, "[Driver -> Transform]");
}
else if (GS(id->name) == ID_KE) {
- ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(driver_key, geometry_key, DEPSREL_TYPE_GEOMETRY_EVAL, "[Driver -> Shapekey Geometry]");
+ ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, "[Driver -> Shapekey Geometry]");
}
}
@@ -1007,14 +1054,14 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{
continue;
}
- OperationKey target_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Bone Target -> Driver]");
+ OperationKey target_key(dtar->id, DEG_NODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, driver_key, "[Bone Target -> Driver]");
}
}
else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
/* get node associated with the object's transforms */
- OperationKey target_key(dtar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
- add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Target -> Driver]");
+ OperationKey target_key(dtar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL);
+ add_relation(target_key, driver_key, "[Target -> Driver]");
}
else if (dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) {
/* workaround for ensuring that local bone transforms don't end up
@@ -1034,8 +1081,8 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{
continue;
}
- OperationKey bone_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(bone_key, driver_key, DEPSREL_TYPE_DRIVER, "[RNA Bone -> Driver]");
+ OperationKey bone_key(dtar->id, DEG_NODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_LOCAL);
+ add_relation(bone_key, driver_key, "[RNA Bone -> Driver]");
}
}
else {
@@ -1047,7 +1094,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
/* resolve path to get node */
RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : "");
- add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]");
+ add_relation(target_key, driver_key, "[RNA Target -> Driver]");
}
}
DRIVER_TARGETS_LOOPER_END
@@ -1061,7 +1108,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
python_driver_depends_on_time(driver))
{
TimeSourceKey time_src_key;
- add_relation(time_src_key, driver_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Driver]");
+ add_relation(time_src_key, driver_key, "[TimeSrc -> Driver]");
}
}
@@ -1081,27 +1128,29 @@ void DepsgraphRelationBuilder::build_world(World *world)
build_texture_stack(world->mtex);
/* world's nodetree */
- build_nodetree(world->nodetree);
+ if (world->nodetree != NULL) {
+ build_nodetree(world->nodetree);
+ ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey world_key(world_id, DEG_NODE_TYPE_PARAMETERS);
+ add_relation(ntree_key, world_key, "NTree->World Parameters");
+ }
}
void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
- OperationKey init_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD);
- OperationKey sim_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM);
+ OperationKey init_key(&scene->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD);
+ OperationKey sim_key(&scene->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM);
/* rel between the two sim-nodes */
- add_relation(init_key, sim_key, DEPSREL_TYPE_OPERATION, "Rigidbody [Init -> SimStep]");
+ add_relation(init_key, sim_key, "Rigidbody [Init -> SimStep]");
/* set up dependencies between these operations and other builtin nodes --------------- */
/* time dependency */
TimeSourceKey time_src_key;
- add_relation(time_src_key,
- init_key,
- DEPSREL_TYPE_TIME,
- "TimeSrc -> Rigidbody Reset/Rebuild (Optional)");
+ add_relation(time_src_key, init_key, "TimeSrc -> Rigidbody Reset/Rebuild (Optional)");
/* objects - simulation participants */
if (rbw->group) {
@@ -1119,12 +1168,12 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
* XXX: there's probably a difference between passive and active
* - passive don't change, so may need to know full transform...
*/
- OperationKey rbo_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ OperationKey rbo_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
eDepsOperation_Code trans_opcode = ob->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL;
- OperationKey trans_op(&ob->id, DEPSNODE_TYPE_TRANSFORM, trans_opcode);
+ OperationKey trans_op(&ob->id, DEG_NODE_TYPE_TRANSFORM, trans_opcode);
- add_relation(sim_key, rbo_key, DEPSREL_TYPE_COMPONENT_ORDER, "Rigidbody Sim Eval -> RBO Sync");
+ add_relation(sim_key, rbo_key, "Rigidbody Sim Eval -> RBO Sync");
/* if constraints exist, those depend on the result of the rigidbody sim
* - This allows constraints to modify the result of the sim (i.e. clamping)
@@ -1136,12 +1185,9 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
*/
if (ob->constraints.first) {
OperationKey constraint_key(&ob->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
- add_relation(rbo_key,
- constraint_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "RBO Sync -> Ob Constraints");
+ add_relation(rbo_key, constraint_key, "RBO Sync -> Ob Constraints");
}
else {
/* Final object transform depends on rigidbody.
@@ -1150,19 +1196,13 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
* If it is gone we'll need to reconsider relation here.
*/
OperationKey uber_key(&ob->id,
- DEPSNODE_TYPE_TRANSFORM,
+ DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_OBJECT_UBEREVAL);
- add_relation(rbo_key,
- uber_key,
- DEPSREL_TYPE_COMPONENT_ORDER,
- "RBO Sync -> Uber (Temp)");
+ add_relation(rbo_key, uber_key, "RBO Sync -> Uber (Temp)");
}
/* Needed to get correct base values. */
- add_relation(trans_op,
- sim_key,
- DEPSREL_TYPE_OPERATION,
- "Base Ob Transform -> Rigidbody Sim Eval");
+ add_relation(trans_op, sim_key, "Base Ob Transform -> Rigidbody Sim Eval");
}
}
@@ -1179,16 +1219,16 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* final result of the constraint object's transform controls how the
* constraint affects the physics sim for these objects
*/
- ComponentKey trans_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- OperationKey ob1_key(&rbc->ob1->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
- OperationKey ob2_key(&rbc->ob2->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ ComponentKey trans_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ OperationKey ob1_key(&rbc->ob1->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
+ OperationKey ob2_key(&rbc->ob2->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY);
/* - constrained-objects sync depends on the constraint-holder */
- add_relation(trans_key, ob1_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_1");
- add_relation(trans_key, ob2_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_2");
+ add_relation(trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1");
+ add_relation(trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2");
/* - ensure that sim depends on this constraint's transform */
- add_relation(trans_key, sim_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint Transform -> RB Simulation");
+ add_relation(trans_key, sim_key, "RigidBodyConstraint Transform -> RB Simulation");
}
}
}
@@ -1197,7 +1237,7 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
{
TimeSourceKey time_src_key;
OperationKey obdata_ubereval_key(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
+ DEG_NODE_TYPE_GEOMETRY,
DEG_OPCODE_GEOMETRY_UBEREVAL);
/* particle systems */
@@ -1208,7 +1248,7 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
build_animdata(&part->id);
/* this particle system */
- OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
+ OperationKey psys_key(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
/* XXX: if particle system is later re-enabled, we must do full rebuild? */
if (!psys_check_enabled(ob, psys, G.is_rendering))
@@ -1217,46 +1257,13 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
/* TODO(sergey): Are all particle systems depends on time?
* Hair without dynamics i.e.
*/
- add_relation(time_src_key, psys_key,
- DEPSREL_TYPE_TIME,
- "TimeSrc -> PSys");
+ add_relation(time_src_key, psys_key, "TimeSrc -> PSys");
/* TODO(sergey): Currently particle update is just a placeholder,
* hook it to the ubereval node so particle system is getting updated
* on playback.
*/
- add_relation(psys_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_OPERATION,
- "PSys -> UberEval");
-
-#if 0
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- LINKLIST_FOREACH (ParticleTarget *, pt, &psys->targets) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- LINKLIST_FOREACH (GroupObject *, go, &part->dup_group->gobject) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-#endif
+ add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval");
/* collisions */
if (part->type != PART_HAIR) {
@@ -1280,19 +1287,16 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
ruleob = ((BoidRuleFollowLeader *)rule)->ob;
if (ruleob) {
- ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule");
+ ComponentKey ruleob_key(&ruleob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(ruleob_key, psys_key, "Boid Rule");
}
}
}
}
if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- ComponentKey dup_ob_key(&part->dup_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dup_ob_key,
- psys_key,
- DEPSREL_TYPE_TRANSFORM,
- "Particle Object Visualization");
+ ComponentKey dup_ob_key(&part->dup_ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
}
}
@@ -1302,20 +1306,32 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
* TODO(sergey): This relation should be altered once real granular update
* is implemented.
*/
- ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_GEOMETRY_EVAL,
- "Partcile Eval");
+ ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
/* pointcache */
// TODO...
}
+void DepsgraphRelationBuilder::build_cloth(Scene * /*scene*/,
+ Object *object,
+ ModifierData * /*md*/)
+{
+ OperationKey cache_key(&object->id,
+ DEG_NODE_TYPE_CACHE,
+ DEG_OPCODE_PLACEHOLDER,
+ "Cloth Modifier");
+ /* Cache component affects on modifier. */
+ OperationKey modifier_key(&object->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+ add_relation(cache_key, modifier_key, "Cloth Cache -> Cloth");
+}
+
/* Shapekeys */
void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
{
- ComponentKey obdata_key(obdata, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey obdata_key(obdata, DEG_NODE_TYPE_GEOMETRY);
/* attach animdata to geometry */
build_animdata(&key->id);
@@ -1323,8 +1339,8 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
if (key->adt) {
// TODO: this should really be handled in build_animdata, since many of these cases will need it
if (key->adt->action || key->adt->nla_tracks.first) {
- ComponentKey adt_key(&key->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(adt_key, obdata_key, DEPSREL_TYPE_OPERATION, "Animation");
+ ComponentKey adt_key(&key->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(adt_key, obdata_key, "Animation");
}
/* NOTE: individual shapekey drivers are handled above already */
@@ -1332,8 +1348,8 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
/* attach to geometry */
// XXX: aren't shapekeys now done as a pseudo-modifier on object?
- //ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY); // FIXME: this doesn't exist
- //add_relation(key_key, obdata_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys");
+ //ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY); // FIXME: this doesn't exist
+ //add_relation(key_key, obdata_key, "Shapekeys");
}
/**
@@ -1361,34 +1377,26 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
ID *obdata = (ID *)ob->data;
/* Init operation of object-level geometry evaluation. */
- OperationKey geom_init_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init");
+ OperationKey geom_init_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init");
/* get nodes for result of obdata's evaluation, and geometry evaluation on object */
- ComponentKey obdata_geom_key(obdata, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey geom_key(&ob->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey obdata_geom_key(obdata, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey geom_key(&ob->id, DEG_NODE_TYPE_GEOMETRY);
/* link components to each other */
- add_relation(obdata_geom_key, geom_key, DEPSREL_TYPE_DATABLOCK, "Object Geometry Base Data");
+ add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
/* Modifiers */
- if (ob->modifiers.first) {
- OperationKey prev_mod_key;
+ if (ob->modifiers.first != NULL) {
+ OperationKey obdata_ubereval_key(&ob->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
- OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
-
- if (md->prev) {
- /* Stack relation: modifier depends on previous modifier in the stack */
- add_relation(prev_mod_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack");
- }
- else {
- /* Stack relation: first modifier depends on the geometry. */
- add_relation(geom_init_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack");
- }
if (mti->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(mod_key);
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
mti->updateDepsgraph(
md,
bmain,
@@ -1399,7 +1407,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
if (BKE_object_modifier_use_time(ob, md)) {
TimeSourceKey time_src_key;
- add_relation(time_src_key, mod_key, DEPSREL_TYPE_TIME, "Time Source");
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
/* Hacky fix for T45633 (Animated modifiers aren't updated)
*
@@ -1408,28 +1416,23 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
*/
/* XXX: Remove this hack when these links are added as part of build_animdata() instead */
if (modifier_dependsOnTime(md) == false && needs_animdata_node(&ob->id)) {
- ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, mod_key, DEPSREL_TYPE_OPERATION, "Modifier Animation");
+ ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, obdata_ubereval_key, "Modifier Animation");
}
}
- prev_mod_key = mod_key;
+ if (md->type == eModifierType_Cloth) {
+ build_cloth(scene, ob, md);
+ }
}
}
/* materials */
- if (ob->totcol != 0) {
- ComponentKey object_shading_key(&ob->id, DEPSNODE_TYPE_SHADING);
+ if (ob->totcol) {
for (int a = 1; a <= ob->totcol; a++) {
Material *ma = give_current_material(ob, a);
if (ma != NULL) {
build_material(ma);
- ComponentKey material_shading_key(&ma->id,
- DEPSNODE_TYPE_SHADING);
- add_relation(material_shading_key,
- object_shading_key,
- DEPSREL_TYPE_UPDATE,
- "Object Shading");
}
}
}
@@ -1445,15 +1448,8 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
*/
if (ob->type != OB_ARMATURE) {
/* Armatures does no longer require uber node. */
- OperationKey obdata_ubereval_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
- if (ob->modifiers.last) {
- ModifierData *md = (ModifierData *)ob->modifiers.last;
- OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
- add_relation(mod_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval");
- }
- else {
- add_relation(geom_init_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval");
- }
+ OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL);
+ add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
}
if (obdata->tag & LIB_TAG_DOIT) {
@@ -1462,9 +1458,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
obdata->tag |= LIB_TAG_DOIT;
/* Link object data evaluation node to exit operation. */
- OperationKey obdata_geom_eval_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
- OperationKey obdata_geom_done_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done");
- add_relation(obdata_geom_eval_key, obdata_geom_done_key, DEPSREL_TYPE_DATABLOCK, "ObData Geom Eval Done");
+ OperationKey obdata_geom_eval_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
+ OperationKey obdata_geom_done_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done");
+ add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
/* type-specific node/links */
switch (ob->type) {
@@ -1478,10 +1474,10 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
/* motherball - mom depends on children! */
if (mom != ob) {
/* non-motherball -> cannot be directly evaluated! */
- ComponentKey mom_key(&mom->id, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(geom_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball");
- add_relation(transform_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball");
+ ComponentKey mom_key(&mom->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(geom_key, mom_key, "Metaball Motherball");
+ add_relation(transform_key, mom_key, "Metaball Motherball");
}
break;
}
@@ -1494,20 +1490,20 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
/* curve's dependencies */
// XXX: these needs geom data, but where is geom stored?
if (cu->bevobj) {
- ComponentKey bevob_key(&cu->bevobj->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey bevob_key(&cu->bevobj->id, DEG_NODE_TYPE_GEOMETRY);
build_object(bmain, scene, cu->bevobj);
- add_relation(bevob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Bevel");
+ add_relation(bevob_key, geom_key, "Curve Bevel");
}
if (cu->taperobj) {
- ComponentKey taperob_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey taperob_key(&cu->taperobj->id, DEG_NODE_TYPE_GEOMETRY);
build_object(bmain, scene, cu->taperobj);
- add_relation(taperob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Taper");
+ add_relation(taperob_key, geom_key, "Curve Taper");
}
if (ob->type == OB_FONT) {
if (cu->textoncurve) {
- ComponentKey textoncurve_key(&cu->textoncurve->id, DEPSNODE_TYPE_GEOMETRY);
+ ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY);
build_object(bmain, scene, cu->textoncurve);
- add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve");
+ add_relation(textoncurve_key, geom_key, "Text on Curve");
}
}
break;
@@ -1531,14 +1527,13 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
}
if (needs_animdata_node(obdata)) {
- ComponentKey animation_key(obdata, DEPSNODE_TYPE_ANIMATION);
- ComponentKey parameters_key(obdata, DEPSNODE_TYPE_PARAMETERS);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Geom Parameters");
+ ComponentKey animation_key(obdata, DEG_NODE_TYPE_ANIMATION);
+ ComponentKey parameters_key(obdata, DEG_NODE_TYPE_PARAMETERS);
+ add_relation(animation_key, parameters_key, "Geom Parameters");
/* Evaluation usually depends on animation.
* TODO(sergey): Need to re-hook it after granular update is implemented..
*/
- add_relation(animation_key, obdata_geom_eval_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Animation");
+ add_relation(animation_key, obdata_geom_eval_key, "Animation");
}
}
@@ -1553,19 +1548,18 @@ void DepsgraphRelationBuilder::build_camera(Object *ob)
}
camera_id->tag |= LIB_TAG_DOIT;
- ComponentKey parameters_key(camera_id, DEPSNODE_TYPE_PARAMETERS);
+ ComponentKey parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS);
if (needs_animdata_node(camera_id)) {
- ComponentKey animation_key(camera_id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Camera Parameters");
+ ComponentKey animation_key(camera_id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key, "Camera Parameters");
}
/* DOF */
if (cam->dof_ob) {
- ComponentKey ob_param_key(&ob->id, DEPSNODE_TYPE_PARAMETERS);
- ComponentKey dof_ob_key(&cam->dof_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dof_ob_key, ob_param_key, DEPSREL_TYPE_TRANSFORM, "Camera DOF");
+ ComponentKey ob_param_key(&ob->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(dof_ob_key, ob_param_key, "Camera DOF");
}
}
@@ -1579,20 +1573,18 @@ void DepsgraphRelationBuilder::build_lamp(Object *ob)
}
lamp_id->tag |= LIB_TAG_DOIT;
- ComponentKey parameters_key(lamp_id, DEPSNODE_TYPE_PARAMETERS);
+ ComponentKey parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
if (needs_animdata_node(lamp_id)) {
- ComponentKey animation_key(lamp_id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Lamp Parameters");
+ ComponentKey animation_key(lamp_id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key, "Lamp Parameters");
}
/* lamp's nodetree */
if (la->nodetree) {
build_nodetree(la->nodetree);
- ComponentKey nodetree_key(&la->nodetree->id, DEPSNODE_TYPE_PARAMETERS);
- add_relation(nodetree_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "NTree->Lamp Parameters");
+ ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
+ add_relation(nodetree_key, parameters_key, "NTree->Lamp Parameters");
}
/* textures */
@@ -1609,7 +1601,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_animdata(ntree_id);
OperationKey parameters_key(ntree_id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Parameters Eval");
@@ -1629,19 +1621,17 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
group_ntree->id.tag |= LIB_TAG_DOIT;
}
OperationKey group_parameters_key(&group_ntree->id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Parameters Eval");
- add_relation(group_parameters_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "Group Node");
+ add_relation(group_parameters_key, parameters_key, "Group Node");
}
}
}
if (needs_animdata_node(ntree_id)) {
- ComponentKey animation_key(ntree_id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, parameters_key,
- DEPSREL_TYPE_COMPONENT_ORDER, "NTree Parameters");
+ ComponentKey animation_key(ntree_id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, parameters_key, "NTree Parameters");
}
}
@@ -1664,15 +1654,14 @@ void DepsgraphRelationBuilder::build_material(Material *ma)
if (ma->nodetree != NULL) {
build_nodetree(ma->nodetree);
OperationKey ntree_key(&ma->nodetree->id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Parameters Eval");
OperationKey material_key(&ma->id,
- DEPSNODE_TYPE_SHADING,
+ DEG_NODE_TYPE_SHADING,
DEG_OPCODE_PLACEHOLDER,
"Material Update");
- add_relation(ntree_key, material_key,
- DEPSREL_TYPE_UPDATE, "Material's NTree");
+ add_relation(ntree_key, material_key, "Material's NTree");
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 054e4103290..02f8fc69070 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -58,6 +58,7 @@ struct Main;
struct Mask;
struct Material;
struct MTex;
+struct ModifierData;
struct MovieClip;
struct bNodeTree;
struct Object;
@@ -77,17 +78,12 @@ struct Depsgraph;
struct DepsNode;
struct DepsNodeHandle;
struct RootDepsNode;
-struct SubgraphDepsNode;
struct IDDepsNode;
struct TimeSourceDepsNode;
struct ComponentDepsNode;
struct OperationDepsNode;
struct RootPChanMap;
-struct RootKey {
- RootKey();
-};
-
struct TimeSourceKey
{
TimeSourceKey();
@@ -176,19 +172,16 @@ struct DepsgraphRelationBuilder
template <typename KeyFrom, typename KeyTo>
void add_relation(const KeyFrom& key_from,
const KeyTo& key_to,
- eDepsRelation_Type type,
const char *description);
template <typename KeyTo>
void add_relation(const TimeSourceKey& key_from,
const KeyTo& key_to,
- eDepsRelation_Type type,
const char *description);
template <typename KeyType>
void add_node_handle_relation(const KeyType& key_from,
const DepsNodeHandle *handle,
- eDepsRelation_Type type,
const char *description);
void build_scene(Main *bmain, Scene *scene);
@@ -205,6 +198,7 @@ struct DepsgraphRelationBuilder
void build_world(World *world);
void build_rigidbody(Scene *scene);
void build_particles(Scene *scene, Object *ob);
+ void build_cloth(Scene *scene, Object *object, ModifierData *md);
void build_ik_pose(Object *ob,
bPoseChannel *pchan,
bConstraint *con,
@@ -235,8 +229,9 @@ struct DepsgraphRelationBuilder
template <typename KeyType>
OperationDepsNode *find_operation_node(const KeyType &key);
+ Depsgraph *getGraph();
+
protected:
- RootDepsNode *find_node(const RootKey &key) const;
TimeSourceDepsNode *find_node(const TimeSourceKey &key) const;
ComponentDepsNode *find_node(const ComponentKey &key) const;
OperationDepsNode *find_node(const OperationKey &key) const;
@@ -248,7 +243,6 @@ protected:
const char *description);
void add_operation_relation(OperationDepsNode *node_from,
OperationDepsNode *node_to,
- eDepsRelation_Type type,
const char *description);
template <typename KeyType>
@@ -288,7 +282,6 @@ OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType&
template <typename KeyFrom, typename KeyTo>
void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
const KeyTo &key_to,
- eDepsRelation_Type type,
const char *description)
{
DepsNode *node_from = find_node(key_from);
@@ -296,27 +289,27 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
if (op_from && op_to) {
- add_operation_relation(op_from, op_to, type, description);
+ add_operation_relation(op_from, op_to, description);
}
else {
if (!op_from) {
/* XXX TODO handle as error or report if needed */
node_from = find_node(key_from);
- fprintf(stderr, "add_relation(%d, %s) - Could not find op_from (%s)\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n",
+ description, key_from.identifier().c_str());
}
else {
- fprintf(stderr, "add_relation(%d, %s) - Failed, but op_from (%s) was ok\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n",
+ description, key_from.identifier().c_str());
}
if (!op_to) {
/* XXX TODO handle as error or report if needed */
- fprintf(stderr, "add_relation(%d, %s) - Could not find op_to (%s)\n",
- type, description, key_to.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n",
+ description, key_to.identifier().c_str());
}
else {
- fprintf(stderr, "add_relation(%d, %s) - Failed, but op_to (%s) was ok\n",
- type, description, key_to.identifier().c_str());
+ fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n",
+ description, key_to.identifier().c_str());
}
}
}
@@ -324,11 +317,8 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
template <typename KeyTo>
void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
const KeyTo &key_to,
- eDepsRelation_Type type,
const char *description)
{
- (void)type; /* Ignored in release builds. */
- BLI_assert(type == DEPSREL_TYPE_TIME);
TimeSourceDepsNode *time_from = find_node(key_from);
DepsNode *node_to = find_node(key_to);
OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
@@ -343,23 +333,22 @@ template <typename KeyType>
void DepsgraphRelationBuilder::add_node_handle_relation(
const KeyType &key_from,
const DepsNodeHandle *handle,
- eDepsRelation_Type type,
const char *description)
{
DepsNode *node_from = find_node(key_from);
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
OperationDepsNode *op_to = handle->node->get_entry_operation();
if (op_from && op_to) {
- add_operation_relation(op_from, op_to, type, description);
+ add_operation_relation(op_from, op_to, description);
}
else {
if (!op_from) {
- fprintf(stderr, "add_node_handle_relation(%d, %s) - Could not find op_from (%s)\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n",
+ description, key_from.identifier().c_str());
}
if (!op_to) {
- fprintf(stderr, "add_node_handle_relation(%d, %s) - Could not find op_to (%s)\n",
- type, description, key_from.identifier().c_str());
+ fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n",
+ description, key_from.identifier().c_str());
}
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
index feae8bca303..9d6ab3358a7 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
@@ -35,13 +35,6 @@
namespace DEG {
/////////////////////////////////////////
-// Root.
-
-RootKey::RootKey()
-{
-}
-
-/////////////////////////////////////////
// Time source.
TimeSourceKey::TimeSourceKey()
@@ -64,7 +57,7 @@ string TimeSourceKey::identifier() const
ComponentKey::ComponentKey()
: id(NULL),
- type(DEPSNODE_TYPE_UNDEFINED),
+ type(DEG_NODE_TYPE_UNDEFINED),
name("")
{
}
@@ -90,7 +83,7 @@ string ComponentKey::identifier() const
OperationKey::OperationKey()
: id(NULL),
- component_type(DEPSNODE_TYPE_UNDEFINED),
+ component_type(DEG_NODE_TYPE_UNDEFINED),
component_name(""),
opcode(DEG_OPCODE_OPERATION),
name(""),
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index 2b4c000f483..be666165a0b 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -38,10 +38,10 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+extern "C" {
#include "DNA_action_types.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -51,10 +51,10 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/builder/deg_builder_pchanmap.h"
@@ -83,7 +83,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* - see notes on direction of rel below...
*/
bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
- OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
+ OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
/* IK target */
// XXX: this should get handled as part of the constraint code
@@ -96,25 +96,25 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* testing IK solver.
*/
// FIXME: geometry targets...
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+ ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
/* TODO(sergey): This is only for until granular update stores intermediate result. */
if (data->tar != ob) {
/* different armature - can just read the results */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget);
+ add_relation(target_key, pose_key, con->name);
}
else {
/* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */
- OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ OperationKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
+ add_relation(target_key, solver_key, con->name);
}
}
else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
/* vertex group target */
/* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, solver_key, con->name);
if (data->tar->type == OB_MESH) {
OperationDepsNode *node2 = find_operation_node(target_key);
@@ -125,8 +125,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
}
else {
/* Standard Object Target */
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_key, pose_key, con->name);
}
if ((data->tar == ob) && (data->subtarget[0])) {
@@ -142,14 +142,14 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
if (data->poletar != NULL) {
if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
// XXX: same armature issues - ready vs done?
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->polesubtarget);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_BONE, data->polesubtarget);
+ add_relation(target_key, solver_key, con->name);
}
else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->polesubtarget[0])) {
/* vertex group target */
/* NOTE: for now, we don't need to represent vertex groups separately... */
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+ ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_GEOMETRY);
+ add_relation(target_key, solver_key, con->name);
if (data->poletar->type == OB_MESH) {
OperationDepsNode *node2 = find_operation_node(target_key);
@@ -159,8 +159,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
}
}
else {
- ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+ ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(target_key, solver_key, con->name);
}
}
@@ -170,19 +170,17 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
bPoseChannel *parchan = pchan;
/* exclude tip from chain? */
if (!(data->flag & CONSTRAINT_IK_TIP)) {
- OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+ OperationKey tip_transforms_key(&ob->id, DEG_NODE_TYPE_BONE,
parchan->name, DEG_OPCODE_BONE_LOCAL);
- add_relation(solver_key, tip_transforms_key,
- DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+ add_relation(solver_key, tip_transforms_key, "IK Solver Result");
parchan = pchan->parent;
}
root_map->add_bone(parchan->name, rootchan->name);
- OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+ OperationKey parchan_transforms_key(&ob->id, DEG_NODE_TYPE_BONE,
parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parchan_transforms_key, solver_key,
- DEPSREL_TYPE_TRANSFORM, "IK Solver Owner");
+ add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
/* Walk to the chain's root */
//size_t segcount = 0;
@@ -196,15 +194,15 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
* grab the result with IK solver results...
*/
if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent");
+ OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ add_relation(parent_key, solver_key, "IK Chain Parent");
- OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+ OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, done_key, "IK Chain Result");
}
else {
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+ OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "IK Solver Result");
}
parchan->flag |= POSE_DONE;
@@ -219,8 +217,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
parchan = parchan->parent;
}
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+ OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ add_relation(solver_key, flush_key, "PoseEval Result-Bone Link");
}
/* Spline IK Eval Steps */
@@ -231,14 +229,14 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
- OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
+ OperationKey transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
/* attach owner to IK Solver too
* - assume that owner is always part of chain
* - see notes on direction of rel below...
*/
- add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner");
+ add_relation(transforms_key, solver_key, "Spline IK Solver Owner");
/* attach path dependency to solver */
if (data->tar) {
@@ -247,14 +245,14 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
* See IK pose for a bit more information.
*/
// TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
- ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel");
+ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY);
+ ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ add_relation(target_key, pose_key, "[Curve.Path -> Spline IK] DepsRel");
}
pchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result");
+ OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "Spline IK Result");
root_map->add_bone(pchan->name, rootchan->name);
@@ -270,16 +268,16 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
* grab the result with IK solver results...
*/
if (parchan != pchan) {
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
- add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update");
+ OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+ add_relation(parent_key, solver_key, "Spline IK Solver Update");
- OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+ OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, done_key, "IK Chain Result");
}
parchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result");
+ OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "Spline IK Solver Result");
root_map->add_bone(parchan->name, rootchan->name);
@@ -288,8 +286,8 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */
}
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+ OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ add_relation(solver_key, flush_key, "PoseEval Result-Bone Link");
}
/* Pose/Armature Bones Graph */
@@ -301,21 +299,21 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
// TODO: selection status?
/* attach links between pose operations */
- OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ OperationKey init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
- add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]");
+ add_relation(init_key, flush_key, "[Pose Init -> Pose Cleanup]");
/* Make sure pose is up-to-date with armature updates. */
OperationKey armature_key(&arm->id,
- DEPSNODE_TYPE_PARAMETERS,
+ DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PLACEHOLDER,
"Armature Eval");
- add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency");
+ add_relation(armature_key, init_key, "Data dependency");
if (needs_animdata_node(&ob->id)) {
- ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
+ ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION);
+ add_relation(animation_key, init_key, "Rig Animation");
}
/* IK Solvers...
@@ -370,26 +368,25 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
/* TODO(sergey): Once partial updates are possible use relation between
* object transform and solver itself in it's build function.
*/
- ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms");
+ ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE);
+ ComponentKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
+ add_relation(local_transform_key, pose_key, "Local Transforms");
}
-
/* links between operations for each bone */
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
- OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_pose_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
+ OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
pchan->flag &= ~POSE_DONE;
/* pose init to bone local */
- add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link");
+ add_relation(init_key, bone_local_key, "PoseEval Source-Bone Link");
/* local to pose parenting operation */
- add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link");
+ add_relation(bone_local_key, bone_pose_key, "Bone Local - PoseSpace Link");
/* parent relation */
if (pchan->parent != NULL) {
@@ -403,26 +400,26 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
parent_key_opcode = DEG_OPCODE_BONE_DONE;
}
- OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
- add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]");
+ OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
+ add_relation(parent_key, bone_pose_key, "[Parent Bone -> Child Bone]");
}
/* constraints */
if (pchan->constraints.first != NULL) {
/* constraints stack and constraint dependencies */
- build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
+ build_constraints(scene, &ob->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
/* pose -> constraints */
- OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
- add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack");
+ OperationKey constraints_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
+ add_relation(bone_pose_key, constraints_key, "Constraints Stack");
/* constraints -> ready */
// TODO: when constraint stack is exploded, this step should occur before the first IK solver
- add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready");
+ add_relation(constraints_key, bone_ready_key, "Constraints -> Ready");
}
else {
/* pose -> ready */
- add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready");
+ add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
}
/* bone ready -> done
@@ -430,25 +427,25 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
* For IK chains however, an additional rel is created from IK to done,
* with transitive reduction removing this one...
*/
- add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
+ add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
/* assume that all bones must be done for the pose to be ready (for deformers) */
- add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+ add_relation(bone_done_key, flush_key, "PoseEval Result-Bone Link");
}
}
void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
{
- OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
- OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+ OperationKey pose_init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+ OperationKey pose_done_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
- OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
- OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local");
- add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready");
- add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
- add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done");
+ OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+ OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+ OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
+ add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
+ add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
+ add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done");
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
index 8a3476cff45..6a9568e7e8d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -38,20 +38,20 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_blenlib.h"
+extern "C" {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_main.h"
#include "BKE_node.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/builder/deg_builder.h"
#include "intern/builder/deg_builder_pchanmap.h"
@@ -76,26 +76,7 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
/* scene objects */
LINKLIST_FOREACH (Base *, base, &scene->base) {
Object *ob = base->object;
-
- /* object itself */
build_object(bmain, scene, ob);
-
- /* object that this is a proxy for */
- if (ob->proxy) {
- ob->proxy->proxy_from = ob;
- build_object(bmain, scene, ob->proxy);
- /* TODO(sergey): This is an inverted relation, matches old depsgraph
- * behavior and need to be investigated if it still need to be inverted.
- */
- ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
- add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
- }
-
- /* Object dupligroup. */
- if (ob->dup_group) {
- build_group(bmain, scene, ob, ob->dup_group);
- }
}
/* rigidbody */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
index da71db09f3d..b12af21fc8d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
@@ -30,9 +30,7 @@
#include "intern/builder/deg_builder_transitive.h"
-extern "C" {
#include "MEM_guardedalloc.h"
-}
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
@@ -105,7 +103,7 @@ void deg_graph_transitive_reduction(Depsgraph *graph)
/* Increment in advance, so we can safely remove the relation. */
++it_rel;
- if (rel->from->type == DEPSNODE_TYPE_TIMESOURCE) {
+ if (rel->from->type == DEG_NODE_TYPE_TIMESOURCE) {
/* HACK: time source nodes don't get "done" flag set/cleared. */
/* TODO: there will be other types in future, so iterators above
* need modifying.
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
index 0d56ce71c7d..51d4ed91419 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
@@ -35,10 +35,10 @@
extern "C" {
#include "DNA_listBase.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
-} /* extern "C" */
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
@@ -77,20 +77,18 @@ static const char *deg_debug_colors_light[] = {
#ifdef COLOR_SCHEME_NODE_TYPE
static const int deg_debug_node_type_color_map[][2] = {
- {DEPSNODE_TYPE_ROOT, 0},
- {DEPSNODE_TYPE_TIMESOURCE, 1},
- {DEPSNODE_TYPE_ID_REF, 2},
- {DEPSNODE_TYPE_SUBGRAPH, 3},
+ {DEG_NODE_TYPE_TIMESOURCE, 0},
+ {DEG_NODE_TYPE_ID_REF, 2},
/* Outer Types */
- {DEPSNODE_TYPE_PARAMETERS, 4},
- {DEPSNODE_TYPE_PROXY, 5},
- {DEPSNODE_TYPE_ANIMATION, 6},
- {DEPSNODE_TYPE_TRANSFORM, 7},
- {DEPSNODE_TYPE_GEOMETRY, 8},
- {DEPSNODE_TYPE_SEQUENCER, 9},
- {DEPSNODE_TYPE_SHADING, 10},
- {DEPSNODE_TYPE_CACHE, 11},
+ {DEG_NODE_TYPE_PARAMETERS, 2},
+ {DEG_NODE_TYPE_PROXY, 3},
+ {DEG_NODE_TYPE_ANIMATION, 4},
+ {DEG_NODE_TYPE_TRANSFORM, 5},
+ {DEG_NODE_TYPE_GEOMETRY, 6},
+ {DEG_NODE_TYPE_SEQUENCER, 7},
+ {DEG_NODE_TYPE_SHADING, 8},
+ {DEG_NODE_TYPE_CACHE, 9},
{-1, 0}
};
#endif
@@ -100,9 +98,9 @@ static int deg_debug_node_color_index(const DepsNode *node)
#ifdef COLOR_SCHEME_NODE_CLASS
/* Some special types. */
switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_ID_REF:
return 5;
- case DEPSNODE_TYPE_OPERATION:
+ case DEG_NODE_TYPE_OPERATION:
{
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->is_noop())
@@ -115,9 +113,9 @@ static int deg_debug_node_color_index(const DepsNode *node)
}
/* Do others based on class. */
switch (node->tclass) {
- case DEPSNODE_CLASS_OPERATION:
+ case DEG_NODE_CLASS_OPERATION:
return 4;
- case DEPSNODE_CLASS_COMPONENT:
+ case DEG_NODE_CLASS_COMPONENT:
return 1;
default:
return 9;
@@ -201,7 +199,7 @@ static void deg_debug_graphviz_node_color(const DebugContext &ctx,
const char *color_update = "dodgerblue3";
const char *color = color_default;
if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (node->tclass == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
color = color_modified;
@@ -222,7 +220,7 @@ static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx,
float penwidth_update = 4.0f;
float penwidth = penwidth_default;
if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (node->tclass == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
penwidth = penwidth_modified;
@@ -260,7 +258,7 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNod
{
const char *base_style = "filled"; /* default style */
if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (node->tclass == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
base_style = "striped";
@@ -268,13 +266,13 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNod
}
}
switch (node->tclass) {
- case DEPSNODE_CLASS_GENERIC:
+ case DEG_NODE_CLASS_GENERIC:
deg_debug_fprintf(ctx, "\"%s\"", base_style);
break;
- case DEPSNODE_CLASS_COMPONENT:
+ case DEG_NODE_CLASS_COMPONENT:
deg_debug_fprintf(ctx, "\"%s\"", base_style);
break;
- case DEPSNODE_CLASS_OPERATION:
+ case DEG_NODE_CLASS_OPERATION:
deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style);
break;
}
@@ -286,13 +284,13 @@ static void deg_debug_graphviz_node_single(const DebugContext &ctx,
const char *shape = "box";
string name = node->identifier();
float priority = -1.0f;
- if (node->type == DEPSNODE_TYPE_ID_REF) {
+ if (node->type == DEG_NODE_TYPE_ID_REF) {
IDDepsNode *id_node = (IDDepsNode *)node;
char buf[256];
BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers);
name += buf;
}
- if (ctx.show_eval_priority && node->tclass == DEPSNODE_CLASS_OPERATION) {
+ if (ctx.show_eval_priority && node->tclass == DEG_NODE_CLASS_OPERATION) {
priority = ((OperationDepsNode *)node)->eval_priority;
}
deg_debug_fprintf(ctx, "// %s\n", name.c_str());
@@ -322,7 +320,7 @@ static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
const DepsNode *node)
{
string name = node->identifier();
- if (node->type == DEPSNODE_TYPE_ID_REF) {
+ if (node->type == DEG_NODE_TYPE_ID_REF) {
IDDepsNode *id_node = (IDDepsNode *)node;
char buf[256];
BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers);
@@ -363,7 +361,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
const DepsNode *node)
{
switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_ID_REF:
{
const IDDepsNode *id_node = (const IDDepsNode *)node;
if (BLI_ghash_size(id_node->components) == 0) {
@@ -380,30 +378,17 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
}
break;
}
- case DEPSNODE_TYPE_SUBGRAPH:
- {
- SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
- if (sub_node->graph) {
- deg_debug_graphviz_node_cluster_begin(ctx, node);
- deg_debug_graphviz_graph_nodes(ctx, sub_node->graph);
- deg_debug_graphviz_node_cluster_end(ctx);
- }
- else {
- deg_debug_graphviz_node_single(ctx, node);
- }
- break;
- }
- case DEPSNODE_TYPE_PARAMETERS:
- case DEPSNODE_TYPE_ANIMATION:
- case DEPSNODE_TYPE_TRANSFORM:
- case DEPSNODE_TYPE_PROXY:
- case DEPSNODE_TYPE_GEOMETRY:
- case DEPSNODE_TYPE_SEQUENCER:
- case DEPSNODE_TYPE_EVAL_POSE:
- case DEPSNODE_TYPE_BONE:
- case DEPSNODE_TYPE_SHADING:
- case DEPSNODE_TYPE_CACHE:
- case DEPSNODE_TYPE_EVAL_PARTICLES:
+ case DEG_NODE_TYPE_PARAMETERS:
+ case DEG_NODE_TYPE_ANIMATION:
+ case DEG_NODE_TYPE_TRANSFORM:
+ case DEG_NODE_TYPE_PROXY:
+ case DEG_NODE_TYPE_GEOMETRY:
+ case DEG_NODE_TYPE_SEQUENCER:
+ case DEG_NODE_TYPE_EVAL_POSE:
+ case DEG_NODE_TYPE_BONE:
+ case DEG_NODE_TYPE_SHADING:
+ case DEG_NODE_TYPE_CACHE:
+ case DEG_NODE_TYPE_EVAL_PARTICLES:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
if (!comp_node->operations.empty()) {
@@ -427,24 +412,19 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
static bool deg_debug_graphviz_is_cluster(const DepsNode *node)
{
switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_ID_REF:
{
const IDDepsNode *id_node = (const IDDepsNode *)node;
return BLI_ghash_size(id_node->components) > 0;
}
- case DEPSNODE_TYPE_SUBGRAPH:
- {
- SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
- return sub_node->graph != NULL;
- }
- case DEPSNODE_TYPE_PARAMETERS:
- case DEPSNODE_TYPE_ANIMATION:
- case DEPSNODE_TYPE_TRANSFORM:
- case DEPSNODE_TYPE_PROXY:
- case DEPSNODE_TYPE_GEOMETRY:
- case DEPSNODE_TYPE_SEQUENCER:
- case DEPSNODE_TYPE_EVAL_POSE:
- case DEPSNODE_TYPE_BONE:
+ case DEG_NODE_TYPE_PARAMETERS:
+ case DEG_NODE_TYPE_ANIMATION:
+ case DEG_NODE_TYPE_TRANSFORM:
+ case DEG_NODE_TYPE_PROXY:
+ case DEG_NODE_TYPE_GEOMETRY:
+ case DEG_NODE_TYPE_SEQUENCER:
+ case DEG_NODE_TYPE_EVAL_POSE:
+ case DEG_NODE_TYPE_BONE:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
return !comp_node->operations.empty();
@@ -458,14 +438,14 @@ static bool deg_debug_graphviz_is_owner(const DepsNode *node,
const DepsNode *other)
{
switch (node->tclass) {
- case DEPSNODE_CLASS_COMPONENT:
+ case DEG_NODE_CLASS_COMPONENT:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
if (comp_node->owner == other)
return true;
break;
}
- case DEPSNODE_CLASS_OPERATION:
+ case DEG_NODE_CLASS_OPERATION:
{
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->owner == other)
@@ -517,15 +497,12 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
const Depsgraph *graph)
{
- if (graph->root_node) {
- deg_debug_graphviz_node(ctx, graph->root_node);
- }
GHASH_FOREACH_BEGIN (DepsNode *, node, graph->id_hash)
{
deg_debug_graphviz_node(ctx, node);
}
GHASH_FOREACH_END();
- TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ TimeSourceDepsNode *time_source = graph->find_time_source();
if (time_source != NULL) {
deg_debug_graphviz_node(ctx, time_source);
}
@@ -546,7 +523,7 @@ static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
}
GHASH_FOREACH_END();
- TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ TimeSourceDepsNode *time_source = graph->find_time_source();
if (time_source != NULL) {
deg_debug_graphviz_node_relations(ctx, time_source);
}
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 5604044e123..aa21f0995be 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -69,26 +69,22 @@ static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
static DEG_EditorUpdateScenePreCb deg_editor_update_scene_pre_cb = NULL;
Depsgraph::Depsgraph()
- : root_node(NULL),
+ : time_source(NULL),
need_update(false),
layers(0)
{
BLI_spin_init(&lock);
id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
- subgraphs = BLI_gset_ptr_new("Depsgraph subgraphs");
entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags");
}
Depsgraph::~Depsgraph()
{
- /* Free root node - it won't have been freed yet... */
clear_id_nodes();
- clear_subgraph_nodes();
BLI_ghash_free(id_hash, NULL, NULL);
- BLI_gset_free(subgraphs, NULL);
BLI_gset_free(entry_tags, NULL);
- if (this->root_node != NULL) {
- OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
+ if (time_source != NULL) {
+ OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
}
BLI_spin_end(&lock);
}
@@ -131,7 +127,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
/* Bone - generally, we just want the bone component... */
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
*subdata = pchan->name;
return true;
@@ -141,7 +137,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
/* armature-level bone, but it ends up going to bone component anyway */
// TODO: the ID in thise case will end up being bArmature, not Object as needed!
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
*subdata = bone->name;
//*id = ...
@@ -155,7 +151,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
if (BLI_findindex(&ob->constraints, con) != -1) {
/* object transform */
// XXX: for now, we can't address the specific constraint or the constraint stack...
- *type = DEPSNODE_TYPE_TRANSFORM;
+ *type = DEG_NODE_TYPE_TRANSFORM;
return true;
}
else if (ob->pose) {
@@ -163,7 +159,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (BLI_findindex(&pchan->constraints, con) != -1) {
/* bone transforms */
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
*subdata = pchan->name;
return true;
}
@@ -178,7 +174,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
* so although we have unique ops for modifiers,
* we can't lump them together
*/
- *type = DEPSNODE_TYPE_BONE;
+ *type = DEG_NODE_TYPE_BONE;
//*subdata = md->name;
return true;
@@ -195,14 +191,14 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
strstr(prop_identifier, "scale") ||
strstr(prop_identifier, "matrix_"))
{
- *type = DEPSNODE_TYPE_TRANSFORM;
+ *type = DEG_NODE_TYPE_TRANSFORM;
return true;
}
else if (strstr(prop_identifier, "data")) {
/* We access object.data, most likely a geometry.
* Might be a bone tho..
*/
- *type = DEPSNODE_TYPE_GEOMETRY;
+ *type = DEG_NODE_TYPE_GEOMETRY;
return true;
}
}
@@ -212,21 +208,21 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
/* ShapeKeys are currently handled as geometry on the geometry that owns it */
*id = key->from; // XXX
- *type = DEPSNODE_TYPE_PARAMETERS;
+ *type = DEG_NODE_TYPE_PARAMETERS;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
Sequence *seq = (Sequence *)ptr->data;
/* Sequencer strip */
- *type = DEPSNODE_TYPE_SEQUENCER;
+ *type = DEG_NODE_TYPE_SEQUENCER;
*subdata = seq->name; // xxx?
return true;
}
if (prop) {
/* All unknown data effectively falls under "parameter evaluation" */
- *type = DEPSNODE_TYPE_PARAMETERS;
+ *type = DEG_NODE_TYPE_PARAMETERS;
return true;
}
@@ -263,72 +259,18 @@ static void id_node_deleter(void *value)
OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
}
-RootDepsNode *Depsgraph::add_root_node()
+TimeSourceDepsNode *Depsgraph::add_time_source()
{
- if (!root_node) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ROOT);
- root_node = (RootDepsNode *)factory->create_node(NULL, "", "Root (Scene)");
+ if (time_source == NULL) {
+ DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_TIMESOURCE);
+ time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", "Time Source");
}
- return root_node;
+ return time_source;
}
-TimeSourceDepsNode *Depsgraph::find_time_source(const ID *id) const
+TimeSourceDepsNode *Depsgraph::find_time_source() const
{
- /* Search for one attached to a particular ID? */
- if (id) {
- /* Check if it was added as a component
- * (as may be done for subgraphs needing timeoffset).
- */
- IDDepsNode *id_node = find_id_node(id);
- if (id_node) {
- // XXX: review this
-// return id_node->find_component(DEPSNODE_TYPE_TIMESOURCE);
- }
- BLI_assert(!"Not implemented yet");
- }
- else {
- /* Use "official" timesource. */
- return root_node->time_source;
- }
- return NULL;
-}
-
-SubgraphDepsNode *Depsgraph::add_subgraph_node(const ID *id)
-{
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_SUBGRAPH);
- SubgraphDepsNode *subgraph_node =
- (SubgraphDepsNode *)factory->create_node(id, "", id->name + 2);
-
- /* Add to subnodes list. */
- BLI_gset_insert(subgraphs, subgraph_node);
-
- /* if there's an ID associated, add to ID-nodes lookup too */
- if (id) {
-#if 0
- /* XXX subgraph node is NOT a true IDDepsNode - what is this supposed to do? */
- // TODO: what to do if subgraph's ID has already been added?
- BLI_assert(!graph->find_id_node(id));
- graph->id_hash[id] = this;
-#endif
- }
-
- return subgraph_node;
-}
-
-void Depsgraph::remove_subgraph_node(SubgraphDepsNode *subgraph_node)
-{
- BLI_gset_remove(subgraphs, subgraph_node, NULL);
- OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
-}
-
-void Depsgraph::clear_subgraph_nodes()
-{
- GSET_FOREACH_BEGIN(SubgraphDepsNode *, subgraph_node, subgraphs)
- {
- OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
- }
- GSET_FOREACH_END();
- BLI_gset_clear(subgraphs, NULL);
+ return time_source;
}
IDDepsNode *Depsgraph::find_id_node(const ID *id) const
@@ -340,7 +282,7 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name)
{
IDDepsNode *id_node = find_id_node(id);
if (!id_node) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ID_REF);
+ DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_ID_REF);
id_node = (IDDepsNode *)factory->create_node(id, "", name);
id->tag |= LIB_TAG_DOIT;
/* register */
@@ -349,16 +291,6 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name)
return id_node;
}
-void Depsgraph::remove_id_node(const ID *id)
-{
- IDDepsNode *id_node = find_id_node(id);
- if (id_node) {
- /* unregister */
- BLI_ghash_remove(id_hash, id, NULL, NULL);
- OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
- }
-}
-
void Depsgraph::clear_id_nodes()
{
BLI_ghash_clear(id_hash, NULL, id_node_deleter);
@@ -367,15 +299,14 @@ void Depsgraph::clear_id_nodes()
/* Add new relationship between two nodes. */
DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
OperationDepsNode *to,
- eDepsRelation_Type type,
const char *description)
{
/* Create new relation, and add it to the graph. */
- DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description);
+ DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
/* TODO(sergey): Find a better place for this. */
#ifdef WITH_OPENSUBDIV
ComponentDepsNode *comp_node = from->owner;
- if (comp_node->type == DEPSNODE_TYPE_GEOMETRY) {
+ if (comp_node->type == DEG_NODE_TYPE_GEOMETRY) {
IDDepsNode *id_to = to->owner->owner;
IDDepsNode *id_from = from->owner->owner;
if (id_to != id_from && (id_to->id->tag & LIB_TAG_ID_RECALC_ALL)) {
@@ -391,11 +322,10 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
/* Add new relation between two nodes */
DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to,
- eDepsRelation_Type type,
const char *description)
{
/* Create new relation, and add it to the graph. */
- DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description);
+ DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
return rel;
}
@@ -404,12 +334,10 @@ DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to,
DepsRelation::DepsRelation(DepsNode *from,
DepsNode *to,
- eDepsRelation_Type type,
const char *description)
: from(from),
to(to),
name(description),
- type(type),
flag(0)
{
#ifndef NDEBUG
@@ -472,11 +400,10 @@ void Depsgraph::add_entry_tag(OperationDepsNode *node)
void Depsgraph::clear_all_nodes()
{
clear_id_nodes();
- clear_subgraph_nodes();
BLI_ghash_clear(id_hash, NULL, NULL);
- if (this->root_node) {
- OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
- root_node = NULL;
+ if (time_source != NULL) {
+ OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
+ time_source = NULL;
}
}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index e668facd645..f72f8dd9311 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -49,10 +49,8 @@ struct PropertyRNA;
namespace DEG {
struct DepsNode;
-struct RootDepsNode;
struct TimeSourceDepsNode;
struct IDDepsNode;
-struct SubgraphDepsNode;
struct ComponentDepsNode;
struct OperationDepsNode;
@@ -79,12 +77,10 @@ struct DepsRelation {
/* relationship attributes */
const char *name; /* label for debugging */
- eDepsRelation_Type type; /* type */
int flag; /* (eDepsRelation_Flag) */
DepsRelation(DepsNode *from,
DepsNode *to,
- eDepsRelation_Type type,
const char *description);
~DepsRelation();
@@ -111,28 +107,20 @@ struct Depsgraph {
*/
DepsNode *find_node_from_pointer(const PointerRNA *ptr, const PropertyRNA *prop) const;
- RootDepsNode *add_root_node();
-
- TimeSourceDepsNode *find_time_source(const ID *id = NULL) const;
-
- SubgraphDepsNode *add_subgraph_node(const ID *id);
- void remove_subgraph_node(SubgraphDepsNode *subgraph_node);
- void clear_subgraph_nodes();
+ TimeSourceDepsNode *add_time_source();
+ TimeSourceDepsNode *find_time_source() const;
IDDepsNode *find_id_node(const ID *id) const;
IDDepsNode *add_id_node(ID *id, const char *name = "");
- void remove_id_node(const ID *id);
void clear_id_nodes();
/* Add new relationship between two nodes. */
DepsRelation *add_new_relation(OperationDepsNode *from,
OperationDepsNode *to,
- eDepsRelation_Type type,
const char *description);
DepsRelation *add_new_relation(DepsNode *from,
DepsNode *to,
- eDepsRelation_Type type,
const char *description);
/* Tag a specific node as needing updates. */
@@ -147,11 +135,8 @@ struct Depsgraph {
* (for quick lookups). */
GHash *id_hash;
- /* "root" node - the one where all evaluation enters from. */
- RootDepsNode *root_node;
-
- /* Subgraphs referenced in tree. */
- GSet *subgraphs;
+ /* Top-level time source node. */
+ TimeSourceDepsNode *time_source;
/* Indicates whether relations needs to be updated. */
bool need_update;
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 3a69469053c..47bf5e7ecbb 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -34,12 +34,6 @@
// #define DEBUG_TIME
-extern "C" {
-#include "DNA_cachefile_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_force.h"
-
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -48,17 +42,22 @@ extern "C" {
# include "PIL_time_utildefines.h"
#endif
+extern "C" {
+#include "DNA_cachefile_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_force.h"
+
#include "BKE_main.h"
#include "BKE_collision.h"
#include "BKE_effect.h"
#include "BKE_modifier.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
-
#include "builder/deg_builder.h"
#include "builder/deg_builder_cycle.h"
#include "builder/deg_builder_nodes.h"
@@ -81,29 +80,29 @@ static DEG::eDepsNode_Type deg_build_scene_component_type(
eDepsSceneComponentType component)
{
switch (component) {
- case DEG_SCENE_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS;
- case DEG_SCENE_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION;
- case DEG_SCENE_COMP_SEQUENCER: return DEG::DEPSNODE_TYPE_SEQUENCER;
+ case DEG_SCENE_COMP_PARAMETERS: return DEG::DEG_NODE_TYPE_PARAMETERS;
+ case DEG_SCENE_COMP_ANIMATION: return DEG::DEG_NODE_TYPE_ANIMATION;
+ case DEG_SCENE_COMP_SEQUENCER: return DEG::DEG_NODE_TYPE_SEQUENCER;
}
- return DEG::DEPSNODE_TYPE_UNDEFINED;
+ return DEG::DEG_NODE_TYPE_UNDEFINED;
}
static DEG::eDepsNode_Type deg_build_object_component_type(
eDepsObjectComponentType component)
{
switch (component) {
- case DEG_OB_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS;
- case DEG_OB_COMP_PROXY: return DEG::DEPSNODE_TYPE_PROXY;
- case DEG_OB_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION;
- case DEG_OB_COMP_TRANSFORM: return DEG::DEPSNODE_TYPE_TRANSFORM;
- case DEG_OB_COMP_GEOMETRY: return DEG::DEPSNODE_TYPE_GEOMETRY;
- case DEG_OB_COMP_EVAL_POSE: return DEG::DEPSNODE_TYPE_EVAL_POSE;
- case DEG_OB_COMP_BONE: return DEG::DEPSNODE_TYPE_BONE;
- case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEPSNODE_TYPE_EVAL_PARTICLES;
- case DEG_OB_COMP_SHADING: return DEG::DEPSNODE_TYPE_SHADING;
- case DEG_OB_COMP_CACHE: return DEG::DEPSNODE_TYPE_CACHE;
+ case DEG_OB_COMP_PARAMETERS: return DEG::DEG_NODE_TYPE_PARAMETERS;
+ case DEG_OB_COMP_PROXY: return DEG::DEG_NODE_TYPE_PROXY;
+ case DEG_OB_COMP_ANIMATION: return DEG::DEG_NODE_TYPE_ANIMATION;
+ case DEG_OB_COMP_TRANSFORM: return DEG::DEG_NODE_TYPE_TRANSFORM;
+ case DEG_OB_COMP_GEOMETRY: return DEG::DEG_NODE_TYPE_GEOMETRY;
+ case DEG_OB_COMP_EVAL_POSE: return DEG::DEG_NODE_TYPE_EVAL_POSE;
+ case DEG_OB_COMP_BONE: return DEG::DEG_NODE_TYPE_BONE;
+ case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEG_NODE_TYPE_EVAL_PARTICLES;
+ case DEG_OB_COMP_SHADING: return DEG::DEG_NODE_TYPE_SHADING;
+ case DEG_OB_COMP_CACHE: return DEG::DEG_NODE_TYPE_CACHE;
}
- return DEG::DEPSNODE_TYPE_UNDEFINED;
+ return DEG::DEG_NODE_TYPE_UNDEFINED;
}
static DEG::DepsNodeHandle *get_handle(DepsNodeHandle *handle)
@@ -121,7 +120,6 @@ void DEG_add_scene_relation(DepsNodeHandle *handle,
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
description);
}
@@ -135,7 +133,6 @@ void DEG_add_object_relation(DepsNodeHandle *handle,
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
description);
}
@@ -149,7 +146,6 @@ void DEG_add_object_cache_relation(DepsNodeHandle *handle,
DEG::DepsNodeHandle *deg_handle = get_handle(handle);
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_CACHE,
description);
}
@@ -167,10 +163,16 @@ void DEG_add_bone_relation(DepsNodeHandle *handle,
*/
deg_handle->builder->add_node_handle_relation(comp_key,
deg_handle,
- DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
description);
}
+struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle)
+{
+ DEG::DepsNodeHandle *deg_handle = get_handle(handle);
+ DEG::DepsgraphRelationBuilder *relation_builder = deg_handle->builder;
+ return reinterpret_cast<Depsgraph *>(relation_builder->getGraph());
+}
+
void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
@@ -205,30 +207,14 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
/* 1) Generate all the nodes in the graph first */
DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
- /* create root node for scene first
- * - this way it should be the first in the graph,
- * reflecting its role as the entrypoint
- */
node_builder.begin_build(bmain);
- node_builder.add_root_node();
node_builder.build_scene(bmain, scene);
/* 2) Hook up relationships between operations - to determine evaluation
* order.
*/
DEG::DepsgraphRelationBuilder relation_builder(deg_graph);
- /* Hook scene up to the root node as entrypoint to graph. */
- /* XXX what does this relation actually mean?
- * it doesnt add any operations anyway and is not clear what part of the
- * scene is to be connected.
- */
relation_builder.begin_build(bmain);
-#if 0
- relation_builder.add_relation(RootKey(),
- IDKey(scene),
- DEPSREL_TYPE_ROOT_TO_ACTIVE,
- "Root to Active Scene");
-#endif
relation_builder.build_scene(bmain, scene);
/* Detect and solve cycles. */
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index d3b48930779..388b692d742 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -35,11 +35,11 @@
extern "C" {
#include "DNA_scene_types.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_build.h"
-} /* extern "C" */
#include "intern/eval/deg_eval_debug.h"
#include "intern/depsgraph_intern.h"
@@ -165,7 +165,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
return false;
}
foreach (DEG::DepsRelation *rel, node->outlinks) {
- if (rel->to->type == DEG::DEPSNODE_TYPE_OPERATION) {
+ if (rel->to->type == DEG::DEG_NODE_TYPE_OPERATION) {
DEG::OperationDepsNode *to = (DEG::OperationDepsNode *)rel->to;
BLI_assert(to->num_links_pending < to->inlinks.size());
++to->num_links_pending;
@@ -177,7 +177,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
foreach (DEG::OperationDepsNode *node, deg_graph->operations) {
int num_links_pending = 0;
foreach (DEG::DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEG::DEPSNODE_TYPE_OPERATION) {
+ if (rel->from->type == DEG::DEG_NODE_TYPE_OPERATION) {
++num_links_pending;
}
}
@@ -232,7 +232,7 @@ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
}
GHASH_FOREACH_END();
- DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source(NULL);
+ DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source();
if (time_source != NULL) {
tot_rels += time_source->inlinks.size();
}
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index c41f28b07e8..85a0d336d28 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -32,17 +32,17 @@
#include "MEM_guardedalloc.h"
-extern "C" {
-#include "DNA_scene_types.h"
-
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+extern "C" {
+#include "DNA_scene_types.h"
+
#include "BKE_depsgraph.h"
#include "BKE_scene.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
-} /* extern "C" */
#include "intern/eval/deg_eval.h"
#include "intern/eval/deg_eval_flush.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 7f2f6a65f5e..e58a7a32407 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -35,9 +35,9 @@
extern "C" {
#include "BKE_idcode.h"
#include "BKE_main.h"
+} /* extern "C" */
#include "DEG_depsgraph_query.h"
-} /* extern "C" */
#include "intern/depsgraph_intern.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index e8ed03666a6..31b4bbc7950 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -34,15 +34,16 @@
#include <cstring> /* required for memset */
#include <queue>
-extern "C" {
#include "BLI_utildefines.h"
+#include "BLI_task.h"
+#include "BLI_listbase.h"
+extern "C" {
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
-#include "BLI_task.h"
#include "BKE_idcode.h"
#include "BKE_library.h"
@@ -52,12 +53,12 @@ extern "C" {
#define new new_
#include "BKE_screen.h"
#undef new
+} /* extern "C" */
#include "DEG_depsgraph.h"
-} /* extern "C" */
+#include "intern/builder/deg_builder.h"
#include "intern/eval/deg_eval_flush.h"
-
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -336,7 +337,7 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
{
id_node->tag_update(graph);
DEG::ComponentDepsNode *anim_comp =
- id_node->find_component(DEG::DEPSNODE_TYPE_ANIMATION);
+ id_node->find_component(DEG::DEG_NODE_TYPE_ANIMATION);
if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) {
anim_comp->tag_update(graph);
}
@@ -346,6 +347,31 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
GHASH_FOREACH_END();
}
scene->lay_updated |= graph->layers;
+ /* Special trick to get local view to work. */
+ LINKLIST_FOREACH (Base *, base, &scene->base) {
+ Object *object = base->object;
+ DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
+ id_node->layers = 0;
+ }
+ LINKLIST_FOREACH (Base *, base, &scene->base) {
+ Object *object = base->object;
+ DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
+ id_node->layers |= base->lay;
+ if (object == scene->camera) {
+ /* Camera should always be updated, it used directly by viewport. */
+ id_node->layers |= (unsigned int)(-1);
+ }
+ }
+ DEG::deg_graph_build_flush_layers(graph);
+ LINKLIST_FOREACH (Base *, base, &scene->base) {
+ Object *object = base->object;
+ DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
+ GHASH_FOREACH_BEGIN(DEG::ComponentDepsNode *, comp, id_node->components)
+ {
+ id_node->layers |= comp->layers;
+ }
+ GHASH_FOREACH_END();
+ }
}
void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
index 39c189629f2..77454cd85ec 100644
--- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -32,12 +32,11 @@
#include <cstdlib> // for BLI_assert()
-extern "C" {
+
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "DEG_depsgraph.h"
-} /* extern "C" */
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
@@ -98,23 +97,17 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
#define STRINGIFY_OPCODE(name) case DEG_OPCODE_##name: return #name
STRINGIFY_OPCODE(OPERATION);
STRINGIFY_OPCODE(PLACEHOLDER);
- STRINGIFY_OPCODE(NOOP);
STRINGIFY_OPCODE(ANIMATION);
STRINGIFY_OPCODE(DRIVER);
- //STRINGIFY_OPCODE(PROXY);
STRINGIFY_OPCODE(TRANSFORM_LOCAL);
STRINGIFY_OPCODE(TRANSFORM_PARENT);
STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS);
- //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_INIT);
- //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINT);
- //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_DONE);
STRINGIFY_OPCODE(RIGIDBODY_REBUILD);
STRINGIFY_OPCODE(RIGIDBODY_SIM);
STRINGIFY_OPCODE(TRANSFORM_RIGIDBODY);
STRINGIFY_OPCODE(TRANSFORM_FINAL);
STRINGIFY_OPCODE(OBJECT_UBEREVAL);
STRINGIFY_OPCODE(GEOMETRY_UBEREVAL);
- STRINGIFY_OPCODE(GEOMETRY_MODIFIER);
STRINGIFY_OPCODE(GEOMETRY_PATH);
STRINGIFY_OPCODE(POSE_INIT);
STRINGIFY_OPCODE(POSE_DONE);
@@ -123,9 +116,6 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
STRINGIFY_OPCODE(BONE_LOCAL);
STRINGIFY_OPCODE(BONE_POSE_PARENT);
STRINGIFY_OPCODE(BONE_CONSTRAINTS);
- //STRINGIFY_OPCODE(BONE_CONSTRAINTS_INIT);
- //STRINGIFY_OPCODE(BONE_CONSTRAINT);
- //STRINGIFY_OPCODE(BONE_CONSTRAINTS_DONE);
STRINGIFY_OPCODE(BONE_READY);
STRINGIFY_OPCODE(BONE_DONE);
STRINGIFY_OPCODE(PSYS_EVAL);
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
index effd34a0eb9..c1a42941a7d 100644
--- a/source/blender/depsgraph/intern/depsgraph_types.h
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -44,9 +44,6 @@
#include <string>
#include <vector>
-using std::string;
-using std::vector;
-
struct bAction;
struct ChannelDriver;
struct ModifierData;
@@ -56,6 +53,9 @@ struct FCurve;
namespace DEG {
+using std::string;
+using std::vector;
+
/* Evaluation Operation for atomic operation */
// XXX: move this to another header that can be exposed?
typedef function<void(struct EvaluationContext *)> DepsEvalOperationCb;
@@ -67,74 +67,66 @@ typedef enum eDepsNode_Class {
/* Types generally unassociated with user-visible entities,
* but needed for graph functioning.
*/
- DEPSNODE_CLASS_GENERIC = 0,
+ DEG_NODE_CLASS_GENERIC = 0,
/* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring
* certain types of evaluation behavior.
*/
- DEPSNODE_CLASS_COMPONENT = 1,
+ DEG_NODE_CLASS_COMPONENT = 1,
/* [Inner Node] A glorified function-pointer/callback for scheduling up
* evaluation operations for components, subject to relationship
* requirements.
*/
- DEPSNODE_CLASS_OPERATION = 2,
+ DEG_NODE_CLASS_OPERATION = 2,
} eDepsNode_Class;
/* Types of Nodes */
typedef enum eDepsNode_Type {
/* Fallback type for invalid return value */
- DEPSNODE_TYPE_UNDEFINED = -1,
+ DEG_NODE_TYPE_UNDEFINED = -1,
/* Inner Node (Operation) */
- DEPSNODE_TYPE_OPERATION = 0,
+ DEG_NODE_TYPE_OPERATION = 0,
/* **** Generic Types **** */
- /* "Current Scene" - basically whatever kicks off the evaluation process. */
- DEPSNODE_TYPE_ROOT = 1,
/* Time-Source */
- DEPSNODE_TYPE_TIMESOURCE = 2,
+ DEG_NODE_TYPE_TIMESOURCE,
/* ID-Block reference - used as landmarks/collection point for components,
* but not usually part of main graph.
*/
- DEPSNODE_TYPE_ID_REF = 3,
- /* Isolated sub-graph - used for keeping instanced data separate from
- * instances using them.
- */
- DEPSNODE_TYPE_SUBGRAPH = 4,
+ DEG_NODE_TYPE_ID_REF,
/* **** Outer Types **** */
/* Parameters Component - Default when nothing else fits
* (i.e. just SDNA property setting).
*/
- DEPSNODE_TYPE_PARAMETERS = 11,
- /* Generic "Proxy-Inherit" Component
- * XXX: Also for instancing of subgraphs?
- */
- DEPSNODE_TYPE_PROXY = 12,
+ DEG_NODE_TYPE_PARAMETERS,
+ /* Generic "Proxy-Inherit" Component. */
+ DEG_NODE_TYPE_PROXY,
/* Animation Component
*
* XXX: merge in with parameters?
*/
- DEPSNODE_TYPE_ANIMATION = 13,
+ DEG_NODE_TYPE_ANIMATION,
/* Transform Component (Parenting/Constraints) */
- DEPSNODE_TYPE_TRANSFORM = 14,
+ DEG_NODE_TYPE_TRANSFORM,
/* Geometry Component (DerivedMesh/Displist) */
- DEPSNODE_TYPE_GEOMETRY = 15,
+ DEG_NODE_TYPE_GEOMETRY,
/* Sequencer Component (Scene Only) */
- DEPSNODE_TYPE_SEQUENCER = 16,
+ DEG_NODE_TYPE_SEQUENCER,
/* **** Evaluation-Related Outer Types (with Subdata) **** */
/* Pose Component - Owner/Container of Bones Eval */
- DEPSNODE_TYPE_EVAL_POSE = 21,
+ DEG_NODE_TYPE_EVAL_POSE,
/* Bone Component - Child/Subcomponent of Pose */
- DEPSNODE_TYPE_BONE = 22,
+ DEG_NODE_TYPE_BONE,
/* Particle Systems Component */
- DEPSNODE_TYPE_EVAL_PARTICLES = 23,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
/* Material Shading Component */
- DEPSNODE_TYPE_SHADING = 24,
+ DEG_NODE_TYPE_SHADING,
/* Cache Component */
- DEPSNODE_TYPE_CACHE = 25,
+ DEG_NODE_TYPE_CACHE,
} eDepsNode_Type;
/* Identifiers for common operations (as an enum). */
@@ -147,8 +139,6 @@ typedef enum eDepsOperation_Code {
// XXX: Placeholder while porting depsgraph code
DEG_OPCODE_PLACEHOLDER,
- DEG_OPCODE_NOOP,
-
/* Animation, Drivers, etc. ------------------------ */
/* NLA + Action */
@@ -157,9 +147,6 @@ typedef enum eDepsOperation_Code {
/* Driver */
DEG_OPCODE_DRIVER,
- /* Proxy Inherit? */
- //DEG_OPCODE_PROXY,
-
/* Transform --------------------------------------- */
/* Transform entry point - local transforms only */
@@ -170,9 +157,6 @@ typedef enum eDepsOperation_Code {
/* Constraints */
DEG_OPCODE_TRANSFORM_CONSTRAINTS,
- //DEG_OPCODE_TRANSFORM_CONSTRAINTS_INIT,
- //DEG_OPCODE_TRANSFORM_CONSTRAINT,
- //DEG_OPCODE_TRANSFORM_CONSTRAINTS_DONE,
/* Rigidbody Sim - Perform Sim */
DEG_OPCODE_RIGIDBODY_REBUILD,
@@ -192,9 +176,6 @@ typedef enum eDepsOperation_Code {
/* XXX: Placeholder - UberEval */
DEG_OPCODE_GEOMETRY_UBEREVAL,
- /* Modifier */
- DEG_OPCODE_GEOMETRY_MODIFIER,
-
/* Curve Objects - Path Calculation (used for path-following tools, */
DEG_OPCODE_GEOMETRY_PATH,
@@ -220,9 +201,6 @@ typedef enum eDepsOperation_Code {
/* Constraints */
DEG_OPCODE_BONE_CONSTRAINTS,
- //DEG_OPCODE_BONE_CONSTRAINTS_INIT,
- //DEG_OPCODE_BONE_CONSTRAINT,
- //DEG_OPCODE_BONE_CONSTRAINTS_DONE,
/* Bone transforms are ready
*
@@ -258,83 +236,4 @@ protected:
/* String defines for these opcodes, defined in depsgraph_type_defines.cpp */
extern DepsOperationStringifier DEG_OPNAMES;
-/* Type of operation */
-typedef enum eDepsOperation_Type {
- /* **** Primary operation types **** */
-
- /* Initialise evaluation data */
- DEPSOP_TYPE_INIT = 0,
- /* Standard evaluation step */
- DEPSOP_TYPE_EXEC = 1,
- /* Cleanup evaluation data + flush results */
- DEPSOP_TYPE_POST = 2,
-
- /* **** Additional operation types **** */
- /* Indicator for outputting a temporary result that other components
- * can use. // XXX?
- */
- DEPSOP_TYPE_OUT = 3,
- /* Indicator for things like IK Solvers and Rigidbody Sim steps which
- * modify final results of separate entities at once.
- */
- DEPSOP_TYPE_SIM = 4,
- /* Rebuild internal evaluation data - used for Rigidbody Reset and
- * Armature Rebuild-On-Load.
- */
- DEPSOP_TYPE_REBUILD = 5,
-} eDepsOperation_Type;
-
-/* Types of relationships between nodes
- *
- * This is used to provide additional hints to use when filtering
- * the graph, so that we can go without doing more extensive
- * data-level checks...
- */
-typedef enum eDepsRelation_Type {
- /* relationship type unknown/irrelevant */
- DEPSREL_TYPE_STANDARD = 0,
-
- /* root -> active scene or entity (screen, image, etc.) */
- DEPSREL_TYPE_ROOT_TO_ACTIVE,
-
- /* general datablock dependency */
- DEPSREL_TYPE_DATABLOCK,
-
- /* time dependency */
- DEPSREL_TYPE_TIME,
-
- /* component depends on results of another */
- DEPSREL_TYPE_COMPONENT_ORDER,
-
- /* relationship is just used to enforce ordering of operations
- * (e.g. "init()" callback done before "exec() and "cleanup()")
- */
- DEPSREL_TYPE_OPERATION,
-
- /* relationship results from a property driver affecting property */
- DEPSREL_TYPE_DRIVER,
-
- /* relationship is something driver depends on */
- DEPSREL_TYPE_DRIVER_TARGET,
-
- /* relationship is used for transform stack
- * (e.g. parenting, user transforms, constraints)
- */
- DEPSREL_TYPE_TRANSFORM,
-
- /* relationship is used for geometry evaluation
- * (e.g. metaball "motherball" or modifiers)
- */
- DEPSREL_TYPE_GEOMETRY_EVAL,
-
- /* relationship is used to trigger a post-change validity updates */
- DEPSREL_TYPE_UPDATE,
-
- /* relationship is used to trigger editor/screen updates */
- DEPSREL_TYPE_UPDATE_UI,
-
- /* cache dependency */
- DEPSREL_TYPE_CACHE,
-} eDepsRelation_Type;
-
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index e739bc9dbb5..98b10718404 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -34,16 +34,16 @@
#include "PIL_time.h"
-extern "C" {
#include "BLI_utildefines.h"
#include "BLI_task.h"
#include "BLI_ghash.h"
+extern "C" {
#include "BKE_depsgraph.h"
#include "BKE_global.h"
+} /* extern "C" */
#include "DEG_depsgraph.h"
-} /* extern "C" */
#include "atomic_ops.h"
@@ -126,7 +126,9 @@ static void deg_task_run_func(TaskPool *pool,
#endif
}
+ BLI_task_pool_delayed_push_begin(pool, thread_id);
schedule_children(pool, state->graph, node, state->layers, thread_id);
+ BLI_task_pool_delayed_push_end(pool, thread_id);
}
typedef struct CalculatePengindData {
@@ -150,7 +152,7 @@ static void calculate_pending_func(void *data_v, int i)
(node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
{
foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION &&
+ if (rel->from->type == DEG_NODE_TYPE_OPERATION &&
(rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
{
OperationDepsNode *from = (OperationDepsNode *)rel->from;
@@ -195,7 +197,7 @@ static void calculate_eval_priority(OperationDepsNode *node)
foreach (DepsRelation *rel, node->outlinks) {
OperationDepsNode *to = (OperationDepsNode *)rel->to;
- BLI_assert(to->type == DEPSNODE_TYPE_OPERATION);
+ BLI_assert(to->type == DEG_NODE_TYPE_OPERATION);
calculate_eval_priority(to);
node->eval_priority += to->eval_priority;
}
@@ -263,7 +265,7 @@ static void schedule_children(TaskPool *pool,
{
foreach (DepsRelation *rel, node->outlinks) {
OperationDepsNode *child = (OperationDepsNode *)rel->to;
- BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
+ BLI_assert(child->type == DEG_NODE_TYPE_OPERATION);
if (child->scheduled) {
/* Happens when having cyclic dependencies. */
continue;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_debug.cc b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
index 060544a4407..23f4adbaacd 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
@@ -34,16 +34,16 @@
#include <cstring> /* required for STREQ later on. */
-extern "C" {
#include "BLI_listbase.h"
#include "BLI_ghash.h"
-#include "DEG_depsgraph_debug.h"
-
+extern "C" {
#include "WM_api.h"
#include "WM_types.h"
} /* extern "C" */
+#include "DEG_depsgraph_debug.h"
+
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index e10f86f6e95..c230ab4c8fd 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -35,16 +35,16 @@
// TODO(sergey): Use some sort of wrapper.
#include <deque>
-extern "C" {
-#include "DNA_object_types.h"
-
#include "BLI_utildefines.h"
#include "BLI_task.h"
#include "BLI_ghash.h"
-#include "DEG_depsgraph.h"
+extern "C" {
+#include "DNA_object_types.h"
} /* extern "C" */
+#include "DEG_depsgraph.h"
+
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -139,18 +139,18 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
IDDepsNode *id_node = comp_node->owner;
ID *id = id_node->id;
- if(id_node->done == 0) {
+ if (id_node->done == 0) {
deg_editors_id_update(bmain, id);
lib_id_recalc_tag(bmain, id);
/* TODO(sergey): For until we've got proper data nodes in the graph. */
lib_id_recalc_data_tag(bmain, id);
}
- if(comp_node->done == 0) {
+ if (comp_node->done == 0) {
Object *object = NULL;
if (GS(id->name) == ID_OB) {
object = (Object *)id;
- if(id_node->done == 0) {
+ if (id_node->done == 0) {
++num_flushed_objects;
}
}
@@ -164,14 +164,30 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
* Plus it ensures visibility changes and relations and
* layers visibility update has proper flags to work with.
*/
- if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
- object->recalc |= OB_RECALC_TIME;
- }
- else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
- object->recalc |= OB_RECALC_OB;
- }
- else {
- object->recalc |= OB_RECALC_DATA;
+ switch (comp_node->type) {
+ case DEG_NODE_TYPE_UNDEFINED:
+ case DEG_NODE_TYPE_OPERATION:
+ case DEG_NODE_TYPE_TIMESOURCE:
+ case DEG_NODE_TYPE_ID_REF:
+ case DEG_NODE_TYPE_PARAMETERS:
+ case DEG_NODE_TYPE_SEQUENCER:
+ /* Ignore, does not translate to object component. */
+ break;
+ case DEG_NODE_TYPE_ANIMATION:
+ object->recalc |= OB_RECALC_TIME;
+ break;
+ case DEG_NODE_TYPE_TRANSFORM:
+ object->recalc |= OB_RECALC_OB;
+ break;
+ case DEG_NODE_TYPE_GEOMETRY:
+ case DEG_NODE_TYPE_EVAL_POSE:
+ case DEG_NODE_TYPE_BONE:
+ case DEG_NODE_TYPE_EVAL_PARTICLES:
+ case DEG_NODE_TYPE_SHADING:
+ case DEG_NODE_TYPE_CACHE:
+ case DEG_NODE_TYPE_PROXY:
+ object->recalc |= OB_RECALC_DATA;
+ break;
}
}
}
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc
index 57b25c10670..a15317586c1 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node.cc
@@ -41,15 +41,14 @@ extern "C" {
#include "DNA_anim_types.h"
#include "BKE_animsys.h"
+}
#include "DEG_depsgraph.h"
-}
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
-#include "util/deg_util_hash.h"
namespace DEG {
@@ -61,12 +60,12 @@ namespace DEG {
DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
{
this->type = type;
- if (type == DEPSNODE_TYPE_OPERATION)
- this->tclass = DEPSNODE_CLASS_OPERATION;
- else if (type < DEPSNODE_TYPE_PARAMETERS)
- this->tclass = DEPSNODE_CLASS_GENERIC;
+ if (type == DEG_NODE_TYPE_OPERATION)
+ this->tclass = DEG_NODE_CLASS_OPERATION;
+ else if (type < DEG_NODE_TYPE_PARAMETERS)
+ this->tclass = DEG_NODE_CLASS_GENERIC;
else
- this->tclass = DEPSNODE_CLASS_COMPONENT;
+ this->tclass = DEG_NODE_CLASS_COMPONENT;
this->tname = tname;
}
@@ -110,34 +109,9 @@ void TimeSourceDepsNode::tag_update(Depsgraph *graph)
}
}
-
-/* Root Node ============================================== */
-
-RootDepsNode::RootDepsNode() : scene(NULL), time_source(NULL)
-{
-}
-
-RootDepsNode::~RootDepsNode()
-{
- OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
-}
-
-TimeSourceDepsNode *RootDepsNode::add_time_source(const char *name)
-{
- if (!time_source) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
- time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", name);
- /*time_source->owner = this;*/ // XXX
- }
- return time_source;
-}
-
-DEG_DEPSNODE_DEFINE(RootDepsNode, DEPSNODE_TYPE_ROOT, "Root DepsNode");
-static DepsNodeFactoryImpl<RootDepsNode> DNTI_ROOT;
-
/* Time Source Node ======================================= */
-DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEPSNODE_TYPE_TIMESOURCE, "Time Source");
+DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEG_NODE_TYPE_TIMESOURCE, "Time Source");
static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
/* ID Node ================================================ */
@@ -158,8 +132,8 @@ static unsigned int id_deps_node_hash_key(const void *key_v)
{
const IDDepsNode::ComponentIDKey *key =
reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v);
- return hash_combine(BLI_ghashutil_uinthash(key->type),
- BLI_ghashutil_strhash_p(key->name));
+ return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->type),
+ BLI_ghashutil_strhash_p(key->name));
}
static bool id_deps_node_hash_key_cmp(const void *a, const void *b)
@@ -211,8 +185,9 @@ void IDDepsNode::init(const ID *id, const char *UNUSED(subdata))
/* Free 'id' node. */
IDDepsNode::~IDDepsNode()
{
- clear_components();
- BLI_ghash_free(components, id_deps_node_hash_key_free, NULL);
+ BLI_ghash_free(components,
+ id_deps_node_hash_key_free,
+ id_deps_node_hash_value_free);
}
ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
@@ -238,33 +213,13 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
return comp_node;
}
-void IDDepsNode::remove_component(eDepsNode_Type type, const char *name)
-{
- ComponentDepsNode *comp_node = find_component(type, name);
- if (comp_node) {
- /* Unregister. */
- ComponentIDKey key(type, name);
- BLI_ghash_remove(components,
- &key,
- id_deps_node_hash_key_free,
- id_deps_node_hash_value_free);
- }
-}
-
-void IDDepsNode::clear_components()
-{
- BLI_ghash_clear(components,
- id_deps_node_hash_key_free,
- id_deps_node_hash_value_free);
-}
-
void IDDepsNode::tag_update(Depsgraph *graph)
{
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
{
/* TODO(sergey): What about drievrs? */
- bool do_component_tag = comp_node->type != DEPSNODE_TYPE_ANIMATION;
- if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
+ bool do_component_tag = comp_node->type != DEG_NODE_TYPE_ANIMATION;
+ if (comp_node->type == DEG_NODE_TYPE_ANIMATION) {
AnimData *adt = BKE_animdata_from_id(id);
/* Animation data might be null if relations are tagged for update. */
if (adt != NULL && (adt->recalc & ADT_RECALC_ANIM)) {
@@ -287,46 +242,13 @@ void IDDepsNode::finalize_build()
GHASH_FOREACH_END();
}
-DEG_DEPSNODE_DEFINE(IDDepsNode, DEPSNODE_TYPE_ID_REF, "ID Node");
+DEG_DEPSNODE_DEFINE(IDDepsNode, DEG_NODE_TYPE_ID_REF, "ID Node");
static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF;
-/* Subgraph Node ========================================== */
-
-/* Initialize 'subgraph' node - from pointer data given. */
-void SubgraphDepsNode::init(const ID *id, const char *UNUSED(subdata))
-{
- /* Store ID-ref if provided. */
- this->root_id = (ID *)id;
-
- /* NOTE: graph will need to be added manually,
- * as we don't have any way of passing this down.
- */
-}
-
-/* Free 'subgraph' node */
-SubgraphDepsNode::~SubgraphDepsNode()
-{
- /* Only free if graph not shared, of if this node is the first
- * reference to it...
- */
- // XXX: prune these flags a bit...
- if ((this->flag & SUBGRAPH_FLAG_FIRSTREF) || !(this->flag & SUBGRAPH_FLAG_SHARED)) {
- /* Free the referenced graph. */
- DEG_graph_free(reinterpret_cast< ::Depsgraph* >(graph));
- graph = NULL;
- }
-}
-
-DEG_DEPSNODE_DEFINE(SubgraphDepsNode, DEPSNODE_TYPE_SUBGRAPH, "Subgraph Node");
-static DepsNodeFactoryImpl<SubgraphDepsNode> DNTI_SUBGRAPH;
-
void deg_register_base_depsnodes()
{
- deg_register_node_typeinfo(&DNTI_ROOT);
deg_register_node_typeinfo(&DNTI_TIMESOURCE);
-
deg_register_node_typeinfo(&DNTI_ID_REF);
- deg_register_node_typeinfo(&DNTI_SUBGRAPH);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.h b/source/blender/depsgraph/intern/nodes/deg_node.h
index 7c2f53840b6..9f1b61faf24 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node.h
@@ -127,22 +127,6 @@ struct TimeSourceDepsNode : public DepsNode {
DEG_DEPSNODE_DECLARE;
};
-/* Root Node. */
-struct RootDepsNode : public DepsNode {
- RootDepsNode();
- ~RootDepsNode();
-
- TimeSourceDepsNode *add_time_source(const char *name = "");
-
- /* scene that this corresponds to */
- Scene *scene;
-
- /* Entrypoint node for time-changed. */
- TimeSourceDepsNode *time_source;
-
- DEG_DEPSNODE_DECLARE;
-};
-
/* ID-Block Reference */
struct IDDepsNode : public DepsNode {
struct ComponentIDKey {
@@ -160,8 +144,6 @@ struct IDDepsNode : public DepsNode {
const char *name = "") const;
ComponentDepsNode *add_component(eDepsNode_Type type,
const char *name = "");
- void remove_component(eDepsNode_Type type, const char *name = "");
- void clear_components();
void tag_update(Depsgraph *graph);
@@ -185,41 +167,6 @@ struct IDDepsNode : public DepsNode {
DEG_DEPSNODE_DECLARE;
};
-/* Subgraph Reference. */
-struct SubgraphDepsNode : public DepsNode {
- void init(const ID *id, const char *subdata);
- ~SubgraphDepsNode();
-
- /* Instanced graph. */
- Depsgraph *graph;
-
- /* ID-block at root of subgraph (if applicable). */
- ID *root_id;
-
- /* Number of nodes which use/reference this subgraph - if just 1, it may be
- * possible to merge into main,
- */
- size_t num_users;
-
- /* (eSubgraphRef_Flag) assorted settings for subgraph node. */
- int flag;
-
- DEG_DEPSNODE_DECLARE;
-};
-
-/* Flags for subgraph node */
-typedef enum eSubgraphRef_Flag {
- /* Subgraph referenced is shared with another reference, so shouldn't
- * free on exit.
- */
- SUBGRAPH_FLAG_SHARED = (1 << 0),
-
- /* Node is first reference to subgraph, so it can be freed when we are
- * removed.
- */
- SUBGRAPH_FLAG_FIRSTREF = (1 << 1),
-} eSubgraphRef_Flag;
-
void deg_register_base_depsnodes();
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index 06f91ac7fdc..e87c87813e3 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -33,9 +33,10 @@
#include <stdio.h>
#include <cstring> /* required for STREQ later on. */
-extern "C" {
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+extern "C" {
#include "DNA_object_types.h"
#include "BKE_action.h"
@@ -44,7 +45,6 @@ extern "C" {
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
-#include "util/deg_util_hash.h"
namespace DEG {
@@ -95,8 +95,8 @@ static unsigned int comp_node_hash_key(const void *key_v)
{
const ComponentDepsNode::OperationIDKey *key =
reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v);
- return hash_combine(BLI_ghashutil_uinthash(key->opcode),
- BLI_ghashutil_strhash_p(key->name));
+ return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->opcode),
+ BLI_ghashutil_strhash_p(key->name));
}
static bool comp_node_hash_key_cmp(const void *a, const void *b)
@@ -198,32 +198,20 @@ OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
return has_operation(key);
}
-OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+OperationDepsNode *ComponentDepsNode::add_operation(const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag)
{
OperationDepsNode *op_node = has_operation(opcode, name, name_tag);
if (!op_node) {
- DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_OPERATION);
+ DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_OPERATION);
op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
/* register opnode in this component's operation set */
OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
BLI_ghash_insert(operations_map, key, op_node);
- /* set as entry/exit node of component (if appropriate) */
- if (optype == DEPSOP_TYPE_INIT) {
- BLI_assert(this->entry_operation == NULL);
- this->entry_operation = op_node;
- }
- else if (optype == DEPSOP_TYPE_POST) {
- // XXX: review whether DEPSOP_TYPE_OUT is better than DEPSOP_TYPE_POST, or maybe have both?
- BLI_assert(this->exit_operation == NULL);
- this->exit_operation = op_node;
- }
-
/* set backlink */
op_node->owner = this;
}
@@ -235,13 +223,24 @@ OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
/* attach extra data */
op_node->evaluate = op;
- op_node->optype = optype;
op_node->opcode = opcode;
op_node->name = name;
return op_node;
}
+void ComponentDepsNode::set_entry_operation(OperationDepsNode *op_node)
+{
+ BLI_assert(entry_operation == NULL);
+ entry_operation = op_node;
+}
+
+void ComponentDepsNode::set_exit_operation(OperationDepsNode *op_node)
+{
+ BLI_assert(exit_operation == NULL);
+ exit_operation = op_node;
+}
+
void ComponentDepsNode::clear_operations()
{
if (operations_map != NULL) {
@@ -336,37 +335,37 @@ void ComponentDepsNode::finalize_build()
/* Parameter Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEPSNODE_TYPE_PARAMETERS, "Parameters Component");
+DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEG_NODE_TYPE_PARAMETERS, "Parameters Component");
static DepsNodeFactoryImpl<ParametersComponentDepsNode> DNTI_PARAMETERS;
/* Animation Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEPSNODE_TYPE_ANIMATION, "Animation Component");
+DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEG_NODE_TYPE_ANIMATION, "Animation Component");
static DepsNodeFactoryImpl<AnimationComponentDepsNode> DNTI_ANIMATION;
/* Transform Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEPSNODE_TYPE_TRANSFORM, "Transform Component");
+DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEG_NODE_TYPE_TRANSFORM, "Transform Component");
static DepsNodeFactoryImpl<TransformComponentDepsNode> DNTI_TRANSFORM;
/* Proxy Component Defines ================================ */
-DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEPSNODE_TYPE_PROXY, "Proxy Component");
+DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEG_NODE_TYPE_PROXY, "Proxy Component");
static DepsNodeFactoryImpl<ProxyComponentDepsNode> DNTI_PROXY;
/* Geometry Component Defines ============================= */
-DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEPSNODE_TYPE_GEOMETRY, "Geometry Component");
+DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEG_NODE_TYPE_GEOMETRY, "Geometry Component");
static DepsNodeFactoryImpl<GeometryComponentDepsNode> DNTI_GEOMETRY;
/* Sequencer Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEPSNODE_TYPE_SEQUENCER, "Sequencer Component");
+DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEG_NODE_TYPE_SEQUENCER, "Sequencer Component");
static DepsNodeFactoryImpl<SequencerComponentDepsNode> DNTI_SEQUENCER;
/* Pose Component ========================================= */
-DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEPSNODE_TYPE_EVAL_POSE, "Pose Eval Component");
+DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEG_NODE_TYPE_EVAL_POSE, "Pose Eval Component");
static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE;
/* Bone Component ========================================= */
@@ -388,22 +387,22 @@ void BoneComponentDepsNode::init(const ID *id, const char *subdata)
this->pchan = BKE_pose_channel_find_name(ob->pose, subdata);
}
-DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEPSNODE_TYPE_BONE, "Bone Component");
+DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEG_NODE_TYPE_BONE, "Bone Component");
static DepsNodeFactoryImpl<BoneComponentDepsNode> DNTI_BONE;
/* Particles Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEPSNODE_TYPE_EVAL_PARTICLES, "Particles Component");
+DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEG_NODE_TYPE_EVAL_PARTICLES, "Particles Component");
static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES;
/* Shading Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component");
+DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEG_NODE_TYPE_SHADING, "Shading Component");
static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
/* Cache Component Defines ============================ */
-DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEPSNODE_TYPE_CACHE, "Cache Component");
+DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEG_NODE_TYPE_CACHE, "Cache Component");
static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE;
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index 969771a29c9..4ef7dad3ac6 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -99,12 +99,18 @@ struct ComponentDepsNode : public DepsNode {
* \param op: The operation to perform
* \param name: Identifier for operation - used to find/locate it again
*/
- OperationDepsNode *add_operation(eDepsOperation_Type optype,
- DepsEvalOperationCb op,
+ OperationDepsNode *add_operation(const DepsEvalOperationCb& op,
eDepsOperation_Code opcode,
const char *name,
int name_tag);
+ /* Entry/exit operations management.
+ *
+ * Use those instead of direct set since this will perform sanity checks.
+ */
+ void set_entry_operation(OperationDepsNode *op_node);
+ void set_exit_operation(OperationDepsNode *op_node);
+
void clear_operations();
void tag_update(Depsgraph *graph);
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
index 9eed4dfe8d8..7467264f612 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
@@ -32,13 +32,11 @@
#include "MEM_guardedalloc.h"
-extern "C" {
#include "BLI_utildefines.h"
-} /* extern "C" */
+#include "BLI_ghash.h"
#include "intern/depsgraph.h"
#include "intern/depsgraph_intern.h"
-#include "util/deg_util_hash.h"
namespace DEG {
@@ -67,7 +65,7 @@ string OperationDepsNode::identifier() const
string OperationDepsNode::full_identifier() const
{
string owner_str = "";
- if (owner->type == DEPSNODE_TYPE_BONE) {
+ if (owner->type == DEG_NODE_TYPE_BONE) {
owner_str = string(owner->owner->name) + "." + owner->name;
}
else {
@@ -86,7 +84,19 @@ void OperationDepsNode::tag_update(Depsgraph *graph)
graph->add_entry_tag(this);
}
-DEG_DEPSNODE_DEFINE(OperationDepsNode, DEPSNODE_TYPE_OPERATION, "Operation");
+void OperationDepsNode::set_as_entry()
+{
+ BLI_assert(owner != NULL);
+ owner->set_entry_operation(this);
+}
+
+void OperationDepsNode::set_as_exit()
+{
+ BLI_assert(owner != NULL);
+ owner->set_exit_operation(this);
+}
+
+DEG_DEPSNODE_DEFINE(OperationDepsNode, DEG_NODE_TYPE_OPERATION, "Operation");
static DepsNodeFactoryImpl<OperationDepsNode> DNTI_OPERATION;
void deg_register_operation_depsnodes()
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.h b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
index 598393054db..1e5c3832d03 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
@@ -44,9 +44,6 @@ typedef enum eDepsOperation_Flag {
DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
/* node was directly modified, causing need for update */
- /* XXX: intention is to make it easier to tell when we just need to
- * take subgraphs.
- */
DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
/* Operation is evaluated using CPython; has GIL and security
@@ -57,8 +54,6 @@ typedef enum eDepsOperation_Flag {
/* Atomic Operation - Base type for all operations */
struct OperationDepsNode : public DepsNode {
-
-
OperationDepsNode();
~OperationDepsNode();
@@ -72,21 +67,21 @@ struct OperationDepsNode : public DepsNode {
OperationDepsNode *get_entry_operation() { return this; }
OperationDepsNode *get_exit_operation() { return this; }
+ /* Set this operation as compoonent's entry/exit operation. */
+ void set_as_entry();
+ void set_as_exit();
+
/* Component that contains the operation. */
ComponentDepsNode *owner;
/* Callback for operation. */
DepsEvalOperationCb evaluate;
-
/* How many inlinks are we still waiting on before we can be evaluated. */
uint32_t num_links_pending;
float eval_priority;
bool scheduled;
- /* Stage of evaluation */
- eDepsOperation_Type optype;
-
/* Identifier for the operation being performed. */
eDepsOperation_Code opcode;
diff --git a/source/blender/depsgraph/util/deg_util_foreach.h b/source/blender/depsgraph/util/deg_util_foreach.h
index 87d37168d51..cb7361fc708 100644
--- a/source/blender/depsgraph/util/deg_util_foreach.h
+++ b/source/blender/depsgraph/util/deg_util_foreach.h
@@ -46,28 +46,3 @@
# define foreach(x, y) for (x; false; (void)y)
#endif
-
-#define GHASH_FOREACH_BEGIN(type, var, what) \
- do { \
- GHashIterator gh_iter##var; \
- GHASH_ITER(gh_iter##var, what) { \
- type var = reinterpret_cast<type>(BLI_ghashIterator_getValue(&gh_iter##var)); \
-
-#define GHASH_FOREACH_END() \
- } \
- } while(0)
-
-#define GSET_FOREACH_BEGIN(type, var, what) \
- do { \
- GSetIterator gh_iter##var; \
- GSET_ITER(gh_iter##var, what) { \
- type var = reinterpret_cast<type>(BLI_gsetIterator_getKey(&gh_iter##var)); \
-
-#define GSET_FOREACH_END() \
- } \
- } while(0)
-
-#define LINKLIST_FOREACH(type, var, list) \
- for (type var = (type)((list)->first); \
- var != NULL; \
- var = (type)(((Link*)(var))->next))
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 98900812bb2..a6febdb575e 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -579,6 +579,7 @@ void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
break;
}
/* else drop through, keep range instead */
+ ATTR_FALLTHROUGH;
case ZOOM_FRAME_MODE_KEEP_RANGE:
default:
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 823cde75334..aafd7ebb1f9 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -888,7 +888,8 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even
ed_marker_move_cancel(C, op);
return OPERATOR_CANCELLED;
}
- /* else continue; <--- see if release event should be caught for tweak-end */
+ /* else continue; <--- see if release event should be caught for tweak-end */
+ ATTR_FALLTHROUGH;
case RETKEY:
case PADENTER:
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 4571df0f077..9d25fc9e1a3 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -452,7 +452,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
ok |= KEYFRAME_OK_H2; \
} \
} (void)0
-
+
/* ------------------------ */
static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt)
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index c928508237d..db4b642fe91 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -311,8 +311,8 @@ typedef struct BoneFlipNameData {
* This way if we are flipping related bones (e.g., Bone.L, Bone.R) at the same time
* all the bones are safely renamed, without conflicting with each other.
*
- * \param arm Armature the bones belong to
- * \param bones ListBase of BoneConflict elems, populated via ED_armature_bones_flip_names_add
+ * \param arm: Armature the bones belong to
+ * \param bones_names: List of BoneConflict elems.
*/
void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names)
{
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 21cb405c32b..8dfcd5acab8 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -885,6 +885,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
default:
+ {
if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) {
float value;
@@ -972,6 +973,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* allow to pass through */
return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
}
+ }
}
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index 661a8e1de9f..2bcf3099104 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -2240,9 +2240,9 @@ static void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e
else {
a1 = nextArcMappedToEdge(a1, e1);
}
+ }
}
}
-}
static void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2)
{
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 47f42ab5321..8a366ce6a81 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -4160,7 +4160,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
*/
bp = nu->bp;
- if (bp[nu->pntsu - 1].f1 & SELECT) {
+ if (bp[nu->pntsu - 1].f1 & SELECT) {
if (nu2 == NULL) {
nu2 = nu;
}
@@ -5850,6 +5850,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
BLI_assert(points_stride + dims == points + (points_len * dims));
float tan_l[3], tan_r[3], error_sq_dummy;
+ unsigned int error_index_dummy;
sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]);
normalize_v3(tan_l);
@@ -5860,7 +5861,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
points, points_len, NULL, dims, FLT_EPSILON,
tan_l, tan_r,
bezt_prev->vec[2], bezt_next->vec[0],
- &error_sq_dummy);
+ &error_sq_dummy, &error_index_dummy);
if (!ELEM(bezt_prev->h2, HD_FREE, HD_ALIGN)) {
bezt_prev->h2 = (bezt_prev->h2 == HD_VECT) ? HD_FREE : HD_ALIGN;
@@ -6047,6 +6048,9 @@ int join_curve_exec(bContext *C, wmOperator *op)
cu = ob->data;
BLI_movelisttolist(&cu->nurb, &tempbase);
+ /* Account for mixed 2D/3D curves when joining */
+ BKE_curve_curve_dimension_update(cu);
+
DAG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index a542bf8fa11..ecab37c729f 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -528,15 +528,15 @@ static void gp_draw_stroke_fill(
}
else {
/* As an initial implementation, we use the OpenGL filled polygon drawing
- * here since it's the easiest option to implement for this case. It does
- * come with limitations (notably for concave shapes), though it shouldn't
- * be much of an issue in most cases.
- *
- * We keep this legacy implementation around despite now having the high quality
- * fills, as this is necessary for keeping everything working nicely for files
- * created using old versions of Blender which may have depended on the artifacts
- * the old fills created.
- */
+ * here since it's the easiest option to implement for this case. It does
+ * come with limitations (notably for concave shapes), though it shouldn't
+ * be much of an issue in most cases.
+ *
+ * We keep this legacy implementation around despite now having the high quality
+ * fills, as this is necessary for keeping everything working nicely for files
+ * created using old versions of Blender which may have depended on the artifacts
+ * the old fills created.
+ */
bGPDspoint *pt;
glBegin(GL_POLYGON);
@@ -701,24 +701,25 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
*/
{
bGPDspoint *pt1, *pt2;
- float pm[2];
+ float s0[2], s1[2]; /* segment 'center' points */
+ float pm[2]; /* normal from previous segment. */
int i;
float fpt[3];
glShadeModel(GL_FLAT);
glBegin(GL_QUADS);
-
+
+ /* get x and y coordinates from first point */
+ mul_v3_m4v3(fpt, diff_mat, &points->x);
+ gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s0);
+
for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
- float s0[2], s1[2]; /* segment 'center' points */
float t0[2], t1[2]; /* tessellated coordinates */
float m1[2], m2[2]; /* gradient and normal */
float mt[2], sc[2]; /* gradient for thickness, point for end-cap */
float pthick; /* thickness at segment point */
- /* get x and y coordinates from points */
- mul_v3_m4v3(fpt, diff_mat, &pt1->x);
- gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s0);
-
+ /* get x and y coordinates from point2 (point1 has already been computed in previous iteration). */
mul_v3_m4v3(fpt, diff_mat, &pt2->x);
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1);
@@ -846,6 +847,8 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
glVertex2fv(t0);
}
+ /* store computed point2 coordinates as point1 ones of next segment. */
+ copy_v2_v2(s0, s1);
/* store stroke's 'natural' normal for next stroke to use */
copy_v2_v2(pm, m2);
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index ec5a42c23a5..5332bec0c64 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -297,9 +297,9 @@ static bool gp_brush_strength_apply(
float inf;
/* Compute strength of effect
- * - We divide the strength by 10, so that users can set "sane" values.
- * Otherwise, good default values are in the range of 0.093
- */
+ * - We divide the strength by 10, so that users can set "sane" values.
+ * Otherwise, good default values are in the range of 0.093
+ */
inf = gp_brush_influence_calc(gso, radius, co) / 10.0f;
/* apply */
@@ -773,6 +773,9 @@ typedef struct tGPSB_CloneBrushData {
/* for "stamp" mode, the currently pasted brushes */
bGPDstroke **new_strokes;
+
+ /* mapping from colors referenced per stroke, to the new colours in the "pasted" strokes */
+ GHash *new_colors;
} tGPSB_CloneBrushData;
/* Initialise "clone" brush data */
@@ -816,6 +819,11 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso)
if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) {
data->new_strokes = MEM_callocN(sizeof(bGPDstroke *) * data->totitems, "cloned strokes ptr array");
}
+
+ /* Init colormap for mapping between the pasted stroke's source colour(names)
+ * and the final colours that will be used here instead...
+ */
+ data->new_colors = gp_copybuf_validate_colormap(gso->gpd);
}
/* Free custom data used for "clone" brush */
@@ -829,6 +837,12 @@ static void gp_brush_clone_free(tGP_BrushEditData *gso)
data->new_strokes = NULL;
}
+ /* free copybuf colormap */
+ if (data->new_colors) {
+ BLI_ghash_free(data->new_colors, NULL, NULL);
+ data->new_colors = NULL;
+ }
+
/* free the customdata itself */
MEM_freeN(data);
gso->customdata = NULL;
@@ -869,6 +883,13 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
+ /* Fix color references */
+ BLI_assert(new_stroke->colorname[0] != '\0');
+ new_stroke->palcolor = BLI_ghash_lookup(data->new_colors, new_stroke->colorname);
+
+ BLI_assert(new_stroke->palcolor != NULL);
+ BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
+
/* Adjust all the stroke's points, so that the strokes
* get pasted relative to where the cursor is now
*/
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index fa9acc36a2b..fc6df49cf6c 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -38,8 +38,11 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -335,11 +338,27 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot)
/* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */
ListBase gp_strokes_copypastebuf = {NULL, NULL};
+/* Hash for hanging on to all the palette colors used by strokes in the buffer
+ *
+ * This is needed to prevent dangling and unsafe pointers when pasting across datablocks,
+ * or after a color used by a stroke in the buffer gets deleted (via user action or undo).
+ */
+GHash *gp_strokes_copypastebuf_colors = NULL;
+
/* Free copy/paste buffer data */
void ED_gpencil_strokes_copybuf_free(void)
{
bGPDstroke *gps, *gpsn;
+ /* Free the palettes buffer
+ * NOTE: This is done before the strokes so that the name ptrs (keys) are still safe
+ */
+ if (gp_strokes_copypastebuf_colors) {
+ BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN);
+ gp_strokes_copypastebuf_colors = NULL;
+ }
+
+ /* Free the stroke buffer */
for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) {
gpsn = gps->next;
@@ -352,6 +371,46 @@ void ED_gpencil_strokes_copybuf_free(void)
gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL;
}
+/* Ensure that destination datablock has all the colours the pasted strokes need
+ * Helper function for copy-pasting strokes
+ */
+GHash *gp_copybuf_validate_colormap(bGPdata *gpd)
+{
+ GHash *new_colors = BLI_ghash_str_new("GPencil Paste Dst Colors");
+ GHashIterator gh_iter;
+
+ /* If there's no active palette yet (i.e. new datablock), add one */
+ bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
+ if (palette == NULL) {
+ palette = BKE_gpencil_palette_addnew(gpd, "Pasted Palette", true);
+ }
+
+ /* For each color, figure out what to map to... */
+ GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) {
+ bGPDpalettecolor *palcolor;
+ char *name = BLI_ghashIterator_getKey(&gh_iter);
+
+ /* Look for existing color to map to */
+ /* XXX: What to do if same name but different color? Behaviour here should depend on a property? */
+ palcolor = BKE_gpencil_palettecolor_getbyname(palette, name);
+ if (palcolor == NULL) {
+ /* Doesn't Exist - Create new matching color for this palette */
+ /* XXX: This still doesn't fix the pasting across file boundaries problem... */
+ bGPDpalettecolor *src_color = BLI_ghashIterator_getValue(&gh_iter);
+
+ palcolor = MEM_dupallocN(src_color);
+ BLI_addtail(&palette->colors, palcolor);
+
+ BLI_uniquename(&palette->colors, palcolor, DATA_("GP Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info));
+ }
+
+ /* Store this mapping (for use later when pasting) */
+ BLI_ghash_insert(new_colors, name, palcolor);
+ }
+
+ return new_colors;
+}
+
/* --------------------- */
/* Copy selected strokes */
@@ -413,7 +472,26 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- /* done - no updates needed */
+ /* Build up hash of colors used in these strokes, making copies of these to protect against dangling pointers */
+ if (gp_strokes_copypastebuf.first) {
+ gp_strokes_copypastebuf_colors = BLI_ghash_str_new("GPencil CopyBuf Colors");
+
+ for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
+ if (ED_gpencil_stroke_can_use(C, gps)) {
+ if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, gps->colorname) == false) {
+ bGPDpalettecolor *color = MEM_dupallocN(gps->palcolor);
+
+ BLI_ghash_insert(gp_strokes_copypastebuf_colors, gps->colorname, color);
+ gps->palcolor = color;
+ }
+ }
+ }
+ }
+
+ /* updates (to ensure operator buttons are refreshed, when used via hotkeys) */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); // XXX?
+
+ /* done */
return OPERATOR_FINISHED;
}
@@ -458,6 +536,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
bGPDframe *gpf;
eGP_PasteMode type = RNA_enum_get(op->ptr, "type");
+ GHash *new_colors;
/* check for various error conditions */
if (gpd == NULL) {
@@ -515,6 +594,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ /* Ensure that all the necessary colors exist */
+ new_colors = gp_copybuf_validate_colormap(gpd);
+
+ /* Copy over the strokes from the buffer (and adjust the colors) */
for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
if (ED_gpencil_stroke_can_use(C, gps)) {
/* Need to verify if layer exists */
@@ -533,6 +616,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
*/
gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
if (gpf) {
+ /* Create new stroke */
bGPDstroke *new_stroke = MEM_dupallocN(gps);
new_stroke->tmp_layerinfo[0] = '\0';
@@ -543,10 +627,22 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
new_stroke->next = new_stroke->prev = NULL;
BLI_addtail(&gpf->strokes, new_stroke);
+
+ /* Fix color references */
+ BLI_assert(new_stroke->colorname[0] != '\0');
+ new_stroke->palcolor = BLI_ghash_lookup(new_colors, new_stroke->colorname);
+
+ BLI_assert(new_stroke->palcolor != NULL);
+ BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname));
+
+ /*new_stroke->flag |= GP_STROKE_RECALC_COLOR; */
}
}
}
+ /* free temp data */
+ BLI_ghash_free(new_colors, NULL, NULL);
+
/* updates */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -748,10 +844,10 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Blank Frame";
+ ot->name = "Insert Blank Frame";
ot->idname = "GPENCIL_OT_blank_frame_add";
- ot->description = "Add a new frame with nothing in it on the current frame. "
- "If there is already a frame, all existing frames are shifted one frame later";
+ ot->description = "Insert a blank frame on the current frame "
+ "(all subsequently existing frames, if any, are shifted right by one frame)";
/* callbacks */
ot->exec = gp_blank_frame_add_exec;
@@ -2126,10 +2222,10 @@ static int gp_count_subdivision_cuts(bGPDstroke *gps)
int totnewpoints = 0;
for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
- if (i + 1 < gps->totpoints){
+ if (i + 1 < gps->totpoints) {
if (gps->points[i + 1].flag & GP_SPOINT_SELECT) {
++totnewpoints;
- };
+ }
}
}
}
@@ -2184,7 +2280,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
/* if next point is selected add a half way point */
if (pt->flag & GP_SPOINT_SELECT) {
- if (i + 1 < oldtotpoints){
+ if (i + 1 < oldtotpoints) {
if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
pt_final = &gps->points[i2];
/* Interpolate all values */
@@ -2196,7 +2292,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->flag |= GP_SPOINT_SELECT;
++i2;
- };
+ }
}
}
}
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 5c7c9b84adb..a3734c56c59 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -40,6 +40,8 @@ struct bGPdata;
struct bGPDstroke;
struct bGPDspoint;
+struct GHash;
+
struct ARegion;
struct View2D;
struct wmOperatorType;
@@ -69,75 +71,23 @@ typedef struct GP_SpaceConversion {
float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */
} GP_SpaceConversion;
-
-/**
- * Check whether a given stroke segment is inside a circular brush
- *
- * \param mval The current screen-space coordinates (midpoint) of the brush
- * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
- * \param rad The radius of the brush
- *
- * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment
- * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment
- */
bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
int rad, int x0, int y0, int x1, int y1);
-
-/**
- * Init settings for stroke point space conversions
- *
- * \param[out] r_gsc The space conversion settings struct, populated with necessary params
- */
void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc);
-/**
- * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
- *
- * \param[out] r_x The screen-space x-coordinate of the point
- * \param[out] r_y The screen-space y-coordinate of the point
- */
void gp_point_to_xy(GP_SpaceConversion *settings, struct bGPDstroke *gps, struct bGPDspoint *pt,
int *r_x, int *r_y);
-/**
- * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
- *
- * Just like gp_point_to_xy(), except the resulting coordinates are floats not ints.
- * Use this version to solve "stair-step" artifacts which may arise when roundtripping the calculations.
- *
- * \param[out] r_x The screen-space x-coordinate of the point
- * \param[out] r_y The screen-space y-coordinate of the point
- */
void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
float *r_x, float *r_y);
-/**
- * Convert point to parent space
- *
- * \param pt Original point
- * \param diff_mat Matrix with the difference between original parent matrix
- * \param[out] r_pt Pointer to new point after apply matrix
- */
void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt);
-/**
- * Change points position relative to parent object
- */
+
void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps);
-/**
- * Change point position relative to parent object
- */
+
void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt);
-/**
- * Convert a screenspace point to a 3D Grease Pencil coordinate.
- *
- * For use with editing tools where it is easier to perform the operations in 2D,
- * and then later convert the transformed points back to 3D.
- *
- * \param screeN_co The screenspace 2D coordinates to convert to
- * \param[out] r_out The resulting 3D coordinates of the input point
- */
bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, struct Scene *scene, const float screen_co[2], float r_out[3]);
/* Poll Callbacks ------------------------------------ */
@@ -155,48 +105,18 @@ int gp_brush_crt_presets_poll(bContext *C);
extern ListBase gp_strokes_copypastebuf;
+/* Build a map for converting between old colornames and destination-color-refs */
+struct GHash *gp_copybuf_validate_colormap(bGPdata *gpd);
+
/* Stroke Editing ------------------------------------ */
void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke, int tag_flags);
-/**
- * Apply smooth to stroke point
- * \param gps Stroke to smooth
- * \param i Point index
- * \param inf Amount of smoothing to apply
- * \param affect_pressure Apply smoothing to pressure values too?
- */
bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure);
-
-/**
-* Apply smooth for strength to stroke point
-* \param gps Stroke to smooth
-* \param i Point index
-* \param inf Amount of smoothing to apply
-*/
bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf);
-
-/**
-* Apply smooth for thickness to stroke point (use pressure)
-* \param gps Stroke to smooth
-* \param i Point index
-* \param inf Amount of smoothing to apply
-*/
bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf);
-
-/**
- * Subdivide a stroke once, by adding points at the midpoint between each pair of points
- * \param gps Stroke data
- * \param new_totpoints Total number of points (after subdividing)
- */
void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints);
-
-/**
-* Add randomness to stroke
-* \param gps Stroke data
-* \param brush Brush data
-*/
void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush);
/* Layers Enums -------------------------------------- */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 297058168a0..59b5b41f114 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -77,7 +77,6 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_screen.h"
#include "ED_space_api.h"
#include "gpencil_intern.h"
@@ -86,13 +85,14 @@
/* Core/Shared Utilities */
/* Poll callback for interpolation operators */
-static int gpencil_interpolate_poll(bContext *C)
+static int gpencil_view3d_poll(bContext *C)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
/* only 3D view */
- if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype != SPACE_VIEW3D) {
return 0;
}
@@ -625,6 +625,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
break;
}
default:
+ {
if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
const float factor = tgpi->init_factor;
float value;
@@ -649,6 +650,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent
/* unhandled event - allow to pass through */
return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
}
+ }
}
/* still running... */
@@ -673,7 +675,7 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot)
ot->invoke = gpencil_interpolate_invoke;
ot->modal = gpencil_interpolate_modal;
ot->cancel = gpencil_interpolate_cancel;
- ot->poll = gpencil_interpolate_poll;
+ ot->poll = gpencil_view3d_poll;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
@@ -1017,7 +1019,7 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
/* api callbacks */
ot->exec = gpencil_interpolate_seq_exec;
- ot->poll = gpencil_interpolate_poll;
+ ot->poll = gpencil_view3d_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1025,24 +1027,14 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
/* ******************** Remove Breakdowns ************************ */
-/* Same as gpencil_interpolate_poll(),
- * except we ALSO need to have an active frame that is a breakdown
- */
static int gpencil_interpolate_reverse_poll(bContext *C)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
-
- /* only 3D view */
- if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
+ if (!gpencil_view3d_poll(C)) {
return 0;
}
-
- /* need data to interpolate */
- if (ELEM(NULL, gpd, gpl)) {
- return 0;
- }
-
+
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+
/* need to be on a breakdown frame */
if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) {
CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 5879306b06c..eb49060b629 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -162,6 +162,8 @@ typedef struct tGPsdata {
bGPDbrush *brush; /* current drawing brush */
short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */
int lock_axis; /* lock drawing to one axis */
+
+ short keymodifier; /* key used for invoking the operator */
} tGPsdata;
/* ------ */
@@ -484,7 +486,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
bGPdata *gpd = p->gpd;
bGPDbrush *brush = p->brush;
tGPspoint *pt;
-
+ ToolSettings *ts = p->scene->toolsettings;
+
/* check painting mode */
if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
/* straight lines only - i.e. only store start and end point in buffer */
@@ -636,7 +639,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
View3D *v3d = p->sa->spacedata.first;
view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
}
/* convert screen-coordinates to appropriate coordinates (and store them) */
@@ -756,7 +759,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
int i, totelem;
/* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
- int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0;
+ int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
/* get total number of points to allocate space for
* - drawing straight-lines only requires the endpoints
@@ -893,7 +896,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
copy_v2_v2_int(mval, &ptc->x);
if ((ED_view3d_autodist_depth(p->ar, mval, depth_margin, depth_arr + i) == 0) &&
- (i && (ED_view3d_autodist_depth_seg(p->ar, mval, mval_prev, depth_margin + 1, depth_arr + i) == 0)))
+ (i && (ED_view3d_autodist_depth_seg(p->ar, mval, mval_prev, depth_margin + 1, depth_arr + i) == 0)))
{
interp_depth = true;
}
@@ -910,7 +913,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
depth_arr[i] = 0.9999f;
}
else {
- if (p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) {
+ if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) {
/* remove all info between the valid endpoints */
int first_valid = 0;
int last_valid = 0;
@@ -1004,9 +1007,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname));
/* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head
- * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist
- * when drawing the background
- */
+ * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist
+ * when drawing the background
+ */
if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) && (p->paintmode != GP_PAINTMODE_DRAW_POLY)) {
BLI_addhead(&p->gpf->strokes, gps);
}
@@ -1794,6 +1797,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
static void gp_paint_strokeend(tGPsdata *p)
{
+ ToolSettings *ts = p->scene->toolsettings;
/* for surface sketching, need to set the right OpenGL context stuff so that
* the conversions will project the values correctly...
*/
@@ -1802,7 +1806,7 @@ static void gp_paint_strokeend(tGPsdata *p)
/* need to restore the original projection settings before packing up */
view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
}
/* check if doing eraser or not */
@@ -1938,7 +1942,7 @@ static void gpencil_draw_cancel(bContext *C, wmOperator *op)
/* ------------------------------- */
-static int gpencil_draw_init(bContext *C, wmOperator *op)
+static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p;
eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
@@ -1957,6 +1961,13 @@ static int gpencil_draw_init(bContext *C, wmOperator *op)
gpencil_draw_exit(C, op);
return 0;
}
+
+ if (event != NULL) {
+ p->keymodifier = event->keymodifier;
+ }
+ else {
+ p->keymodifier = -1;
+ }
/* everything is now setup ok */
return 1;
@@ -2198,7 +2209,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
/* printf("GPencil - Starting Re-Drawing\n"); */
/* try to initialize context data needed while drawing */
- if (!gpencil_draw_init(C, op)) {
+ if (!gpencil_draw_init(C, op, NULL)) {
if (op->customdata) MEM_freeN(op->customdata);
/* printf("\tGP - no valid data\n"); */
return OPERATOR_CANCELLED;
@@ -2273,7 +2284,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
printf("GPencil - Starting Drawing\n");
/* try to initialize context data needed while drawing */
- if (!gpencil_draw_init(C, op)) {
+ if (!gpencil_draw_init(C, op, event)) {
if (op->customdata)
MEM_freeN(op->customdata);
if (G.debug & G_DEBUG)
@@ -2436,7 +2447,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* is essential for ensuring that they can quickly return to that view
*/
}
- else if ((ELEM(event->type, DKEY)) && (event->val == KM_RELEASE)) {
+ else if ((ELEM(event->type, p->keymodifier)) && (event->val == KM_RELEASE)) {
/* enable continuous if release D key in mid drawing */
p->scene->toolsettings->gpencil_flags |= GP_TOOL_FLAG_PAINTSESSIONS_ON;
}
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 45dbde80284..2912a1ac4eb 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -1012,7 +1012,7 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
}
/* test if in lasso boundbox + within the lasso noose */
if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0) &&
- BLI_lasso_is_point_inside(mcords, mcords_tot, x0, y0, INT_MAX))
+ BLI_lasso_is_point_inside(mcords, mcords_tot, x0, y0, INT_MAX))
{
if (select) {
pt->flag |= GP_SPOINT_SELECT;
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 76e85f20c36..ed05b8be9ca 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -391,7 +391,16 @@ EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, PointerRNA
/* ******************************************************** */
/* Brush Tool Core */
-/* Check if part of stroke occurs within last segment drawn by eraser */
+/**
+ * Check whether a given stroke segment is inside a circular brush
+ *
+ * \param mval The current screen-space coordinates (midpoint) of the brush
+ * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
+ * \param rad The radius of the brush
+ *
+ * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment
+ * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment
+ */
bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]),
int rad, int x0, int y0, int x1, int y1)
{
@@ -502,7 +511,11 @@ bGPDpalettecolor *ED_gpencil_stroke_getcolor(bGPdata *gpd, bGPDstroke *gps)
/* ******************************************************** */
/* Space Conversion */
-/* Init handling for space-conversion function (from passed-in parameters) */
+/**
+ * Init settings for stroke point space conversions
+ *
+ * \param r_gsc: [out] The space conversion settings struct, populated with necessary params
+ */
void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
{
ScrArea *sa = CTX_wm_area(C);
@@ -538,7 +551,13 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
}
}
-/* convert point to parent space */
+/**
+ * Convert point to parent space
+ *
+ * \param pt Original point
+ * \param diff_mat Matrix with the difference between original parent matrix
+ * \param[out] r_pt Pointer to new point after apply matrix
+ */
void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt)
{
float fpt[3];
@@ -547,7 +566,9 @@ void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *
copy_v3_v3(&r_pt->x, fpt);
}
-/* Change position relative to parent object */
+/**
+ * Change points position relative to parent object
+ */
void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps)
{
bGPDspoint *pt;
@@ -568,7 +589,9 @@ void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps)
}
}
-/* Change point position relative to parent object */
+/**
+ * Change point position relative to parent object
+ */
void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt)
{
/* undo matrix */
@@ -583,8 +606,13 @@ void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt)
copy_v3_v3(&pt->x, fpt);
}
-/* Convert Grease Pencil points to screen-space values
- * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn
+/**
+ * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
+ *
+ * \param[out] r_x The screen-space x-coordinate of the point
+ * \param[out] r_y The screen-space y-coordinate of the point
+ *
+ * \warning This assumes that the caller has already checked whether the stroke in question can be drawn.
*/
void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
int *r_x, int *r_y)
@@ -628,8 +656,16 @@ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
}
}
-/* Convert Grease Pencil points to screen-space values (as floats)
- * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn
+/**
+ * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
+ *
+ * Just like gp_point_to_xy(), except the resulting coordinates are floats not ints.
+ * Use this version to solve "stair-step" artifacts which may arise when roundtripping the calculations.
+ *
+ * \param r_x: [out] The screen-space x-coordinate of the point
+ * \param r_y: [out] The screen-space y-coordinate of the point
+ *
+ * \warning This assumes that the caller has already checked whether the stroke in question can be drawn
*/
void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
float *r_x, float *r_y)
@@ -688,6 +724,12 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt,
/**
* Project screenspace coordinates to 3D-space
*
+ * For use with editing tools where it is easier to perform the operations in 2D,
+ * and then later convert the transformed points back to 3D.
+ *
+ * \param screen_co: The screenspace 2D coordinates to convert to
+ * \param r_out: The resulting 3D coordinates of the input point
+ *
* \note We include this as a utility function, since the standard method
* involves quite a few steps, which are invariably always the same
* for all GPencil operations. So, it's nicer to just centralize these.
@@ -722,7 +764,7 @@ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen
}
/**
- * Apply smooth to stroke point
+ * Apply smooth to stroke point
* \param gps Stroke to smooth
* \param i Point index
* \param inf Amount of smoothing to apply
@@ -830,8 +872,8 @@ bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf)
ptc = &gps->points[after];
/* the optimal value is the corresponding to the interpolation of the strength
- * at the distance of point b
- */
+ * at the distance of point b
+ */
const float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength;
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 5f8ebd87d19..91f8b39f7b9 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -63,7 +63,7 @@ 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);
-bool ED_space_clip_color_sample(struct Scene *scene, 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);
bool ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, bool fit);
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 283113f93d6..9de550a20ce 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -46,7 +46,7 @@ void ED_space_image_set(struct SpaceImage *sima, struct Scene *scene, s
struct Mask *ED_space_image_get_mask(struct SpaceImage *sima);
void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sima, struct Mask *mask);
-bool ED_space_image_color_sample(struct Scene *scene, struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]);
+bool ED_space_image_color_sample(struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]);
struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock);
void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock);
bool ED_space_image_has_buffer(struct SpaceImage *sima);
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index f7b9d6b4f9e..e3c382382a9 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -107,7 +107,7 @@ void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree,
void ED_operatormacros_node(void);
/* node_view.c */
-bool ED_space_node_color_sample(struct Scene *scene, struct SpaceNode *snode, struct ARegion *ar, int mval[2], float r_col[3]);
+bool ED_space_node_color_sample(struct SpaceNode *snode, struct ARegion *ar, int mval[2], float r_col[3]);
#endif /* __ED_NODE_H__ */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 9ce71258573..d5c301d98d6 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -356,6 +356,9 @@ void ED_view3d_draw_offscreen(
float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
struct GPUFX *fx, struct GPUFXSettings *fx_settings,
struct GPUOffScreen *ofs);
+void ED_view3d_draw_setup_view(
+ struct wmWindow *win, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
+ float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
struct ImBuf *ED_view3d_draw_offscreen_imbuf(
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey,
@@ -370,7 +373,9 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
-void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]);
+void ED_view3d_update_viewmat(
+ struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
+ float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
char ED_view3d_lock_view_from_index(int index);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 8420591aa3e..0c83038b7a3 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -313,9 +313,9 @@ DEF_ICON(OUTLINER_OB_ARMATURE)
DEF_ICON(OUTLINER_OB_FONT)
DEF_ICON(OUTLINER_OB_SURFACE)
DEF_ICON(OUTLINER_OB_SPEAKER)
+DEF_ICON(OUTLINER_OB_FORCE_FIELD)
+DEF_ICON(OUTLINER_OB_GROUP_INSTANCE)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK120)
- DEF_ICON(BLANK121)
DEF_ICON(BLANK122)
DEF_ICON(BLANK123)
DEF_ICON(BLANK124)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 9fbce7dd203..252c199d46c 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -217,7 +217,6 @@ enum {
/* scale fixed button widths by this to account for DPI */
#define UI_DPI_FAC ((U.pixelsize * (float)U.dpi) / 72.0f)
-#define UI_DPI_WINDOW_FAC (((float)U.dpi) / 72.0f)
/* 16 to copy ICON_DEFAULT_HEIGHT */
#define UI_DPI_ICON_SIZE ((float)16 * UI_DPI_FAC)
@@ -421,7 +420,7 @@ typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg);
void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
-void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg);
+void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, struct wmOperator *op);
/* void uiPupBlockOperator(struct bContext *C, uiBlockCreateFunc func, struct wmOperator *op, int opcontext); */ /* UNUSED */
void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *block);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 682db20af55..bcb1e3e648a 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1337,7 +1337,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
rctf rectf;
ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
- BLI_rcti_rctf_copy_floor(rect, &rectf);
+ BLI_rcti_rctf_copy_round(rect, &rectf);
BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
}
@@ -2288,7 +2288,7 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size)
#ifdef WITH_PYTHON
-static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value)
+static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *r_value)
{
char str_unit_convert[256];
const int unit_type = UI_but_unit_type_get(but);
@@ -2300,13 +2300,13 @@ static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char
bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), but->drawstr,
ui_get_but_scale_unit(but, 1.0), but->block->unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
- return BPY_execute_string_as_number(C, str_unit_convert, value, true);
+ return BPY_execute_string_as_number(C, str_unit_convert, true, r_value);
}
#endif /* WITH_PYTHON */
-bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *value)
+bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *r_value)
{
bool ok = false;
@@ -2315,13 +2315,13 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double
if (str[0] != '\0') {
bool is_unit_but = (ui_but_is_float(but) && ui_but_is_unit(but));
/* only enable verbose if we won't run again with units */
- if (BPY_execute_string_as_number(C, str, value, is_unit_but == false)) {
+ if (BPY_execute_string_as_number(C, str, is_unit_but == false, r_value)) {
/* if the value parsed ok without unit conversion this button may still need a unit multiplier */
if (is_unit_but) {
char str_new[128];
- BLI_snprintf(str_new, sizeof(str_new), "%f", *value);
- ok = ui_set_but_string_eval_num_unit(C, but, str_new, value);
+ BLI_snprintf(str_new, sizeof(str_new), "%f", *r_value);
+ ok = ui_set_but_string_eval_num_unit(C, but, str_new, r_value);
}
else {
ok = true; /* parse normal string via py (no unit conversion needed) */
@@ -2329,17 +2329,16 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double
}
else if (is_unit_but) {
/* parse failed, this is a unit but so run replacements and parse again */
- ok = ui_set_but_string_eval_num_unit(C, but, str, value);
+ ok = ui_set_but_string_eval_num_unit(C, but, str, r_value);
}
}
#else /* WITH_PYTHON */
- *value = atof(str);
+ *r_value = atof(str);
ok = true;
- (void)C;
- (void)but;
+ UNUSED_VARS(C, but);
#endif /* WITH_PYTHON */
@@ -3168,7 +3167,9 @@ static uiBut *ui_def_but(
}
if (block->flag & UI_BLOCK_RADIAL) {
- but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
+ but->drawflag |= UI_BUT_TEXT_LEFT;
+ if (but->str && but->str[0])
+ but->drawflag |= UI_BUT_ICON_LEFT;
}
else if ((block->flag & UI_BLOCK_LOOP) ||
ELEM(but->type,
@@ -3913,6 +3914,8 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int o
uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0);
+ if (str && str[0] == '\0')
+ return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip);
return uiDefIconTextButO_ptr(block, type, ot, opcontext, icon, str, x, y, width, height, tip);
}
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 5da294302e9..a04360b3395 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -39,6 +39,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_nla.h"
@@ -210,6 +211,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
/* updates */
driver->flag |= DRIVER_FLAG_RECOMPILE;
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
ok = true;
}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index f3859154dfb..eab609ebe84 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -225,7 +225,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
return false;
}
- if (RNA_property_subtype(eye->prop) == PROP_COLOR) {
+ if (RNA_property_subtype(eye->prop) != PROP_COLOR) {
const char *display_device;
float col[4];
@@ -235,7 +235,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
/* store inital color */
RNA_property_float_get_array(&eye->ptr, eye->prop, col);
if (eye->display) {
- IMB_colormanagement_scene_linear_to_display_v3(col, eye->display);
+ IMB_colormanagement_display_to_scene_linear_v3(col, eye->display);
}
copy_v3_v3(eye->init_col, col);
}
@@ -266,6 +266,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
/* we could use some clever */
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
+ const char *display_device = CTX_data_scene(C)->display_settings.display_device;
+ struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
if (sa) {
if (sa->spacetype == SPACE_IMAGE) {
@@ -275,7 +277,7 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
int mval[2] = {mx - ar->winrct.xmin,
my - ar->winrct.ymin};
- if (ED_space_image_color_sample(CTX_data_scene(C), sima, ar, mval, r_col)) {
+ if (ED_space_image_color_sample(sima, ar, mval, r_col)) {
return;
}
}
@@ -287,7 +289,7 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
int mval[2] = {mx - ar->winrct.xmin,
my - ar->winrct.ymin};
- if (ED_space_node_color_sample(CTX_data_scene(C), snode, ar, mval, r_col)) {
+ if (ED_space_node_color_sample(snode, ar, mval, r_col)) {
return;
}
}
@@ -299,7 +301,7 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
int mval[2] = {mx - ar->winrct.xmin,
my - ar->winrct.ymin};
- if (ED_space_clip_color_sample(CTX_data_scene(C), sc, ar, mval, r_col)) {
+ if (ED_space_clip_color_sample(sc, ar, mval, r_col)) {
return;
}
}
@@ -310,6 +312,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
glReadBuffer(GL_FRONT);
glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
glReadBuffer(GL_BACK);
+
+ IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
}
/* sets the sample color RGB, maintaining A */
@@ -320,10 +324,10 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3
/* to maintain alpha */
RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
- /* convert from display space to linear rgb space */
+ /* convert from linear rgb space to display space */
if (eye->display) {
copy_v3_v3(col_conv, col);
- IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display);
+ IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
}
else {
copy_v3_v3(col_conv, col);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 6e3c3c3674a..a3f0e29065d 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -87,6 +87,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "wm_event_system.h"
#ifdef WITH_INPUT_IME
# include "wm_window.h"
@@ -380,6 +381,7 @@ typedef struct uiAfterFunc {
void *butm_func_arg;
int a2;
+ wmOperator *popup_op;
wmOperatorType *optype;
int opcontext;
PointerRNA *opptr;
@@ -635,13 +637,24 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext,
return ptr;
}
+static void popup_check(bContext *C, wmOperator *op)
+{
+ if (op && op->type->check && op->type->check(C, op)) {
+ /* check for popup and re-layout buttons */
+ ARegion *ar_menu = CTX_wm_menu(C);
+ if (ar_menu)
+ ED_region_tag_refresh_ui(ar_menu);
+ }
+}
+
/**
* Check if a #uiAfterFunc is needed for this button.
*/
static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but)
{
return (but->func || but->funcN || but->rename_func || but->optype || but->rnaprop || block->handle_func ||
- (but->type == UI_BTYPE_BUT_MENU && block->butm_func));
+ (but->type == UI_BTYPE_BUT_MENU && block->butm_func) ||
+ (block->handle && block->handle->popup_op));
}
static void ui_apply_but_func(bContext *C, uiBut *but)
@@ -682,6 +695,9 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->butm_func_arg = block->butm_func_arg;
after->a2 = but->a2;
}
+
+ if (block->handle)
+ after->popup_op = block->handle->popup_op;
after->optype = but->optype;
after->opcontext = but->opcontext;
@@ -766,6 +782,9 @@ static void ui_apply_but_funcs_after(bContext *C)
if (after.context)
CTX_store_set(C, after.context);
+ if (after.popup_op)
+ popup_check(C, after.popup_op);
+
if (after.opptr) {
/* free in advance to avoid leak on exit */
opptr = *after.opptr;
@@ -3359,7 +3378,7 @@ static void ui_do_but_textedit(
if (event->type == WHEELDOWNMOUSE) {
break;
}
- /* fall-through */
+ ATTR_FALLTHROUGH;
case ENDKEY:
ui_textedit_move(but, data, STRCUR_DIR_NEXT,
event->shift != 0, STRCUR_JUMP_ALL);
@@ -3377,7 +3396,7 @@ static void ui_do_but_textedit(
if (event->type == WHEELUPMOUSE) {
break;
}
- /* fall-through */
+ ATTR_FALLTHROUGH;
case HOMEKEY:
ui_textedit_move(but, data, STRCUR_DIR_PREV,
event->shift != 0, STRCUR_JUMP_ALL);
@@ -6665,7 +6684,7 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but);
+ UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL);
}
/**
@@ -6738,6 +6757,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
{
uiPopupMenu *pup;
uiLayout *layout;
+ MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
bool is_array, is_array_component;
uiStringInfo label = {BUT_GET_LABEL, NULL};
@@ -6769,6 +6789,12 @@ static bool ui_but_menu(bContext *C, uiBut *but)
/*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);
+ /* set the prop and pointer data for python access to the hovered ui element; TODO, index could be supported as well*/
+ PointerRNA temp_ptr;
+ RNA_pointer_create(NULL, &RNA_Property, but->rnaprop, &temp_ptr);
+ uiLayoutSetContextPointer(layout,"button_prop", &temp_ptr);
+ uiLayoutSetContextPointer(layout,"button_pointer", ptr);
+
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop);
@@ -6984,7 +7010,11 @@ static bool ui_but_menu(bContext *C, uiBut *but)
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
}
-
+
+ /* Set the operator pointer for python access */
+ if (but->opptr)
+ uiLayoutSetContextPointer(layout,"button_operator", but->opptr);
+
uiItemS(layout);
}
@@ -7005,20 +7035,17 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
ICON_URL, "WM_OT_doc_view_manual_ui_context");
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
+ ptr_props = uiItemFullO(layout, "WM_OT_doc_view",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
+ ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
- ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
/* XXX inactive option, not for public! */
#if 0
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit");
+ ptr_props = uiItemFullO(layout, "WM_OT_doc_edit",
+ "Submit Description", ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr_props, "doc_id", buf);
RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop));
-
- uiItemFullO(layout, "WM_OT_doc_edit",
- "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
#endif
}
}
@@ -7034,6 +7061,14 @@ static bool ui_but_menu(bContext *C, uiBut *but)
}
uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
+ mt = WM_menutype_find("WM_MT_button_context", false);
+ if (mt) {
+ Menu menu = {NULL};
+ menu.layout = uiLayoutColumn(layout, false);
+ menu.type = mt;
+ mt->draw(C, &menu);
+ }
+
UI_popup_menu_end(C, pup);
return true;
@@ -8373,7 +8408,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
case MIDDLEMOUSE:
case MOUSEPAN:
UI_but_tooltip_timer_remove(C, but);
- /* fall-through */
+ ATTR_FALLTHROUGH;
default:
/* handle button type specific events */
retval = ui_do_button(C, block, but, event);
@@ -9167,23 +9202,23 @@ static int ui_handle_menu_event(
break;
case ONEKEY: case PAD1:
- act = 1;
+ act = 1; ATTR_FALLTHROUGH;
case TWOKEY: case PAD2:
- if (act == 0) act = 2;
+ if (act == 0) act = 2; ATTR_FALLTHROUGH;
case THREEKEY: case PAD3:
- if (act == 0) act = 3;
+ if (act == 0) act = 3; ATTR_FALLTHROUGH;
case FOURKEY: case PAD4:
- if (act == 0) act = 4;
+ if (act == 0) act = 4; ATTR_FALLTHROUGH;
case FIVEKEY: case PAD5:
- if (act == 0) act = 5;
+ if (act == 0) act = 5; ATTR_FALLTHROUGH;
case SIXKEY: case PAD6:
- if (act == 0) act = 6;
+ if (act == 0) act = 6; ATTR_FALLTHROUGH;
case SEVENKEY: case PAD7:
- if (act == 0) act = 7;
+ if (act == 0) act = 7; ATTR_FALLTHROUGH;
case EIGHTKEY: case PAD8:
- if (act == 0) act = 8;
+ if (act == 0) act = 8; ATTR_FALLTHROUGH;
case NINEKEY: case PAD9:
- if (act == 0) act = 9;
+ if (act == 0) act = 9; ATTR_FALLTHROUGH;
case ZEROKEY: case PAD0:
if (act == 0) act = 10;
@@ -9778,13 +9813,13 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
case (ZEROKEY + n): case (PAD0 + n): \
{ if (num_dir == UI_RADIAL_NONE) num_dir = d; } (void)0
- CASE_NUM_TO_DIR(1, UI_RADIAL_SW);
- CASE_NUM_TO_DIR(2, UI_RADIAL_S);
- CASE_NUM_TO_DIR(3, UI_RADIAL_SE);
- CASE_NUM_TO_DIR(4, UI_RADIAL_W);
- CASE_NUM_TO_DIR(6, UI_RADIAL_E);
- CASE_NUM_TO_DIR(7, UI_RADIAL_NW);
- CASE_NUM_TO_DIR(8, UI_RADIAL_N);
+ CASE_NUM_TO_DIR(1, UI_RADIAL_SW); ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(2, UI_RADIAL_S); ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(3, UI_RADIAL_SE); ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(4, UI_RADIAL_W); ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(6, UI_RADIAL_E); ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(7, UI_RADIAL_NW); ATTR_FALLTHROUGH;
+ CASE_NUM_TO_DIR(8, UI_RADIAL_N); ATTR_FALLTHROUGH;
CASE_NUM_TO_DIR(9, UI_RADIAL_NE);
{
but = ui_block_pie_dir_activate(block, event, num_dir);
@@ -10182,6 +10217,25 @@ void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *
void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup)
{
+ wmEventHandler *handler;
+
+ for (handler = handlers->first; handler; handler = handler->next) {
+ if (handler->ui_handle == ui_popup_handler &&
+ handler->ui_remove == ui_popup_handler_remove &&
+ handler->ui_userdata == popup)
+ {
+ /* tag refresh parent popup */
+ if (handler->next &&
+ handler->next->ui_handle == ui_popup_handler &&
+ handler->next->ui_remove == ui_popup_handler_remove)
+ {
+ uiPopupBlockHandle *parent_popup = handler->next->ui_userdata;
+ ED_region_tag_refresh_ui(parent_popup->region);
+ }
+ break;
+ }
+ }
+
WM_event_remove_ui_handler(handlers, ui_popup_handler, ui_popup_handler_remove, popup, false);
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index d8f9fdcbaae..067279777ba 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -556,6 +556,7 @@ struct uiPopupBlockHandle {
struct uiKeyNavLock keynav_state;
/* for operator popups */
+ struct wmOperator *popup_op;
struct wmOperatorType *optype;
ScrArea *ctx_area;
ARegion *ctx_region;
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index f6347388cc4..da43a58bc74 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1274,7 +1274,8 @@ static void ui_item_rna_size(
if (!w) {
if (type == PROP_ENUM && icon_only) {
w = ui_text_icon_width(layout, "", ICON_BLANK1, 0);
- w += 0.5f * UI_UNIT_X;
+ if (index != RNA_ENUM_VALUE)
+ w += 0.6f * UI_UNIT_X;
}
else {
w = ui_text_icon_width(layout, name, icon, 0);
@@ -2171,7 +2172,17 @@ static void ui_litem_layout_row(uiLayout *litem)
x += neww;
- if ((neww < minw || itemw == minw || item->flag & UI_ITEM_MIN) && w != 0) {
+ bool min_flag = item->flag & UI_ITEM_MIN;
+ /* ignore min flag for rows with right or center alignment */
+ if (item->type != ITEM_BUTTON &&
+ ELEM(((uiLayout *)item)->alignment, UI_LAYOUT_ALIGN_RIGHT, UI_LAYOUT_ALIGN_CENTER) &&
+ litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
+ ((uiItem *)litem)->flag & UI_ITEM_MIN)
+ {
+ min_flag = false;
+ }
+
+ if ((neww < minw || min_flag) && w != 0) {
/* fixed size */
item->flag |= UI_ITEM_FIXED;
if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) {
@@ -2253,10 +2264,11 @@ static void ui_litem_layout_row(uiLayout *litem)
}
/* single-column layout */
-static void ui_litem_estimate_column(uiLayout *litem)
+static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
{
uiItem *item;
int itemw, itemh;
+ bool min_size_flag = true;
litem->w = 0;
litem->h = 0;
@@ -2264,15 +2276,21 @@ static void ui_litem_estimate_column(uiLayout *litem)
for (item = litem->items.first; item; item = item->next) {
ui_item_size(item, &itemw, &itemh);
+ min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN);
+
litem->w = MAX2(litem->w, itemw);
litem->h += itemh;
- if (item->next)
+ if (item->next && (!is_box || item != litem->items.first))
litem->h += litem->space;
}
+
+ if (min_size_flag) {
+ litem->item.flag |= UI_ITEM_MIN;
+ }
}
-static void ui_litem_layout_column(uiLayout *litem)
+static void ui_litem_layout_column(uiLayout *litem, bool is_box)
{
uiItem *item;
int itemh, x, y;
@@ -2286,7 +2304,7 @@ static void ui_litem_layout_column(uiLayout *litem)
y -= itemh;
ui_item_position(item, x, y, litem->w, itemh);
- if (item->next)
+ if (item->next && (!is_box || item != litem->items.first))
y -= litem->space;
}
@@ -2378,8 +2396,10 @@ static void ui_litem_layout_radial(uiLayout *litem)
/* add a little bit more here to include number */
bitem->but->rect.xmax += 1.5f * UI_UNIT_X;
/* enable drawing as pie item if supported by widget */
- if (ui_item_is_radial_drawable(bitem))
+ if (ui_item_is_radial_drawable(bitem)) {
bitem->but->dt = UI_EMBOSS_RADIAL;
+ bitem->but->drawflag |= UI_BUT_ICON_LEFT;
+ }
}
ui_item_size(item, &itemw, &itemh);
@@ -2428,7 +2448,7 @@ static void ui_litem_layout_root(uiLayout *litem)
else if (litem->root->type == UI_LAYOUT_PIEMENU)
ui_litem_layout_root_radial(litem);
else
- ui_litem_layout_column(litem);
+ ui_litem_layout_column(litem, false);
}
/* box layout */
@@ -2436,9 +2456,10 @@ static void ui_litem_estimate_box(uiLayout *litem)
{
uiStyle *style = litem->root->style;
- ui_litem_estimate_column(litem);
+ ui_litem_estimate_column(litem, true);
+ litem->item.flag &= ~UI_ITEM_MIN;
litem->w += 2 * style->boxspace;
- litem->h += style->boxspace;
+ litem->h += 2 * style->boxspace;
}
static void ui_litem_layout_box(uiLayout *litem)
@@ -2452,17 +2473,18 @@ static void ui_litem_layout_box(uiLayout *litem)
h = litem->h;
litem->x += style->boxspace;
+ litem->y -= style->boxspace;
if (w != 0) litem->w -= 2 * style->boxspace;
if (h != 0) litem->h -= 2 * style->boxspace;
- ui_litem_layout_column(litem);
+ ui_litem_layout_column(litem, true);
litem->x -= style->boxspace;
litem->y -= style->boxspace;
if (w != 0) litem->w += 2 * style->boxspace;
- if (h != 0) litem->h += style->boxspace;
+ if (h != 0) litem->h += 2 * style->boxspace;
/* roundbox around the sublayout */
but = box->roundbox;
@@ -3115,7 +3137,7 @@ static void ui_item_estimate(uiItem *item)
switch (litem->item.type) {
case ITEM_LAYOUT_COLUMN:
- ui_litem_estimate_column(litem);
+ ui_litem_estimate_column(litem, false);
break;
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_estimate_column_flow(litem);
@@ -3170,7 +3192,9 @@ static void ui_item_align(uiLayout *litem, short nr)
}
else if (item->type == ITEM_LAYOUT_BOX) {
box = (uiLayoutItemBx *)item;
- box->roundbox->alignnr = nr;
+ if (!box->roundbox->alignnr) {
+ box->roundbox->alignnr = nr;
+ }
}
else if (((uiLayout *)item)->align) {
ui_item_align((uiLayout *)item, nr);
@@ -3212,7 +3236,7 @@ static void ui_item_layout(uiItem *item)
switch (litem->item.type) {
case ITEM_LAYOUT_COLUMN:
- ui_litem_layout_column(litem);
+ ui_litem_layout_column(litem, false);
break;
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_layout_column_flow(litem);
@@ -3556,14 +3580,13 @@ void uiLayoutOperatorButs(
row = uiLayoutRow(layout, true);
uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE);
- WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add");
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false);
+ op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMIN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&op_ptr, "operator", op->type->idname);
- uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
- WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add");
+ op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMOUT, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&op_ptr, "operator", op->type->idname);
RNA_boolean_set(&op_ptr, "remove_active", true);
- uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
}
if (op->type->ui) {
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 466978272bc..534bd4278ca 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -1692,6 +1692,28 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
UI_block_draw(C, block);
}
+/**
+ * Use to refresh centered popups on screen resizing (for splash).
+ */
+static void ui_block_region_popup_window_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+{
+ switch (wmn->category) {
+ case NC_WINDOW:
+ {
+ switch (wmn->action) {
+ case NA_EDITED:
+ {
+ /* window resize */
+ ED_region_tag_refresh_ui(ar);
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
+
static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
{
uiBut *bt;
@@ -2003,6 +2025,11 @@ uiPopupBlockHandle *ui_popup_block_create(
block = ui_popup_block_refresh(C, handle, butregion, but);
handle = block->handle;
+ /* keep centered on window resizing */
+ if ((block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) && handle->can_refresh) {
+ type.listener = ui_block_region_popup_window_listener;
+ }
+
return handle;
}
@@ -3285,7 +3312,7 @@ void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg)
UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
}
-void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg)
+void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, wmOperator *op)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
@@ -3294,6 +3321,7 @@ void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc po
handle->popup = true;
handle->retvalue = 1;
+ handle->popup_op = op;
handle->popup_arg = arg;
handle->popup_func = popup_func;
handle->cancel_func = cancel_func;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 62f12cd7967..131584dd405 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -430,7 +430,7 @@ static void template_ID(
uiLayoutRow(layout, true);
}
else if (flag & UI_ID_BROWSE) {
- but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.5, UI_UNIT_Y,
+ but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y,
TIP_(template_id_browse_tip(type)));
ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
/* default dragging of icon for id browse buttons */
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index df6f098ee81..636b7e4e9ce 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -127,12 +127,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
break;
case PROP_POINTER:
{
- PointerRNA pptr;
-
- pptr = RNA_property_pointer_get(ptr, prop);
- if (!pptr.type)
- pptr.type = RNA_property_pointer_type(ptr, prop);
- icon = RNA_struct_ui_icon(pptr.type);
+ if (icon == 0) {
+ PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
+ icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop));
+ }
if (icon == ICON_DOT)
icon = 0;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 4a2c13e395f..f7f2b422724 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -873,22 +873,19 @@ static void widget_draw_icon(
if (icon && icon != ICON_BLANK1) {
float ofs = 1.0f / aspect;
- if (but->drawflag & UI_BUT_ICON_LEFT || ui_block_is_pie_menu(but->block)) {
- if (but->block->flag & UI_BLOCK_LOOP) {
- if (but->type == UI_BTYPE_SEARCH_MENU)
- xs = rect->xmin + 4.0f * ofs;
- else
- xs = rect->xmin + 2.0f * ofs;
- }
- else {
+ if (but->drawflag & UI_BUT_ICON_LEFT) {
+ /* special case - icon_only pie buttons */
+ if (ui_block_is_pie_menu(but->block) && but->type != UI_BTYPE_MENU && but->str && but->str[0] == '\0')
xs = rect->xmin + 2.0f * ofs;
- }
- ys = (rect->ymin + rect->ymax - height) / 2.0f;
+ else if (but->dt == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL)
+ xs = rect->xmin + 2.0f * ofs;
+ else
+ xs = rect->xmin + 4.0f * ofs;
}
else {
xs = (rect->xmin + rect->xmax - height) / 2.0f;
- ys = (rect->ymin + rect->ymax - height) / 2.0f;
}
+ ys = (rect->ymin + rect->ymax - height) / 2.0f;
/* force positions to integers, for zoom levels near 1. draws icons crisp. */
if (aspect > 0.95f && aspect < 1.05f) {
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 3f9eb33e239..fb20d9f3caa 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -102,12 +102,12 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
char filename[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filename);
- const struct AlembicExportParams params = {
+ struct AlembicExportParams params = {
.frame_start = RNA_int_get(op->ptr, "start"),
.frame_end = RNA_int_get(op->ptr, "end"),
- .frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"),
- .frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"),
+ .frame_samples_xform = RNA_int_get(op->ptr, "xsamples"),
+ .frame_samples_shape = RNA_int_get(op->ptr, "gsamples"),
.shutter_open = RNA_float_get(op->ptr, "sh_open"),
.shutter_close = RNA_float_get(op->ptr, "sh_close"),
@@ -122,6 +122,8 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
.face_sets = RNA_boolean_get(op->ptr, "face_sets"),
.use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
+ .export_hair = RNA_boolean_get(op->ptr, "export_hair"),
+ .export_particles = RNA_boolean_get(op->ptr, "export_particles"),
.compression_type = RNA_enum_get(op->ptr, "compression_type"),
.packuv = RNA_boolean_get(op->ptr, "packuv"),
.triangulate = RNA_boolean_get(op->ptr, "triangulate"),
@@ -131,15 +133,26 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.global_scale = RNA_float_get(op->ptr, "global_scale"),
};
- ABC_export(CTX_data_scene(C), C, filename, &params);
+ /* Take some defaults from the scene, if not specified explicitly. */
+ Scene *scene = CTX_data_scene(C);
+ if (params.frame_start == INT_MIN) {
+ params.frame_start = SFRA;
+ }
+ if (params.frame_end == INT_MIN) {
+ params.frame_end = EFRA;
+ }
- return OPERATOR_FINISHED;
+ const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
+ bool ok = ABC_export(scene, C, filename, &params, as_background_job);
+
+ return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
{
uiLayout *box;
uiLayout *row;
+ uiLayout *col;
#ifdef WITH_ALEMBIC_HDF5
box = uiLayoutBox(layout);
@@ -231,6 +244,15 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiLayoutSetEnabled(row, triangulate);
uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE);
+
+ /* Object Data */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Particle Systems:"), ICON_PARTICLE_DATA);
+
+ col = uiLayoutColumn(box, true);
+ uiItemR(col, imfptr, "export_hair", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "export_particles", 0, NULL, ICON_NONE);
}
static void wm_alembic_export_draw(bContext *C, wmOperator *op)
@@ -282,11 +304,17 @@ void WM_OT_alembic_export(wmOperatorType *ot)
FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_int(ot->srna, "start", 1, INT_MIN, INT_MAX,
- "Start Frame", "Start Frame", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "start", INT_MIN, INT_MIN, INT_MAX,
+ "Start Frame",
+ "Start frame of the export, use the default value to "
+ "take the start frame of the current scene",
+ INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "end", 1, INT_MIN, INT_MAX,
- "End Frame", "End Frame", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "end", INT_MIN, INT_MIN, INT_MAX,
+ "End Frame",
+ "End frame of the export, use the default value to "
+ "take the end frame of the current scene",
+ INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "xsamples", 1, 1, 128,
"Transform Samples", "Number of times per frame transformations are sampled", 1, 128);
@@ -348,9 +376,15 @@ void WM_OT_alembic_export(wmOperatorType *ot)
RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_quad_method_items,
MOD_TRIANGULATE_NGON_BEAUTY, "Polygon Method", "Method for splitting the polygons into triangles");
+ RNA_def_boolean(ot->srna, "export_hair", 1, "Export Hair", "Exports hair particle systems as animated curves");
+ RNA_def_boolean(ot->srna, "export_particles", 1, "Export Particles", "Exports non-hair particle systems");
+
+ RNA_def_boolean(ot->srna, "as_background_job", true, "Run as Background Job",
+ "Enable this to run the import in the background, disable to block Blender while importing");
+
/* This dummy prop is used to check whether we need to init the start and
- * end frame values to that of the scene's, otherwise they are reset at
- * every change, draw update. */
+ * end frame values to that of the scene's, otherwise they are reset at
+ * every change, draw update. */
RNA_def_boolean(ot->srna, "init_scene_frame_range", false, "", "");
}
@@ -482,6 +516,7 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence");
const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
+ const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
int offset = 0;
int sequence_len = 1;
@@ -490,9 +525,11 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
sequence_len = get_sequence_len(filename, &offset);
}
- ABC_import(C, filename, scale, is_sequence, set_frame_range, sequence_len, offset, validate_meshes);
+ bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range,
+ sequence_len, offset, validate_meshes,
+ as_background_job);
- return OPERATOR_FINISHED;
+ return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void WM_OT_alembic_import(wmOperatorType *ot)
@@ -523,6 +560,9 @@ void WM_OT_alembic_import(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence",
"Set to true if the cache is split into separate files");
+
+ RNA_def_boolean(ot->srna, "as_background_job", true, "Run as Background Job",
+ "Enable this to run the export in the background, disable to block Blender while exporting");
}
#endif
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index ebe8898571d..af6f55d7a64 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -143,7 +143,7 @@ static int cachefile_reload_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
- BLI_listbase_clear(&cache_file->object_paths);
+ BLI_freelistN(&cache_file->object_paths);
BKE_cachefile_reload(bmain, cache_file);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index baae92f962e..cead08afd61 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -87,8 +87,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int include_shapekeys;
int deform_bones_only;
- int include_uv_textures;
- int include_material_textures;
+ int export_texture_type;
int use_texture_copies;
int active_uv_only;
@@ -97,7 +96,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int use_blender_profile;
int sort_by_name;
int export_transformation_type;
+
int open_sim;
+ int limit_precision;
+ int keep_bind_info;
int export_count;
@@ -136,8 +138,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
- include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures");
- include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures");
+ export_texture_type = RNA_enum_get(op->ptr, "export_texture_type_selection");
use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies");
active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only");
@@ -148,6 +149,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
open_sim = RNA_boolean_get(op->ptr, "open_sim");
+ limit_precision = RNA_boolean_get(op->ptr, "limit_precision");
+ keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
+
/* get editmode results */
ED_object_editmode_load(CTX_data_edit_object(C));
@@ -163,8 +167,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
deform_bones_only,
active_uv_only,
- include_uv_textures,
- include_material_textures,
+ export_texture_type,
use_texture_copies,
triangulate,
@@ -172,7 +175,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
use_blender_profile,
sort_by_name,
export_transformation_type,
- open_sim);
+
+ open_sim,
+ limit_precision,
+ keep_bind_info
+ );
if (export_count == 0) {
BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file");
@@ -231,10 +238,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_uv_textures", 0, NULL, ICON_NONE);
-
- row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "include_material_textures", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "export_texture_type_selection", 0, "", ICON_NONE);
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
@@ -256,11 +260,11 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "use_object_instantiation", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "use_blender_profile", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
@@ -270,6 +274,12 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE);
+
}
static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op)
@@ -296,6 +306,8 @@ static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op)
void WM_OT_collada_export(wmOperatorType *ot)
{
+ struct StructRNA *func = ot->srna;
+
static EnumPropertyItem prop_bc_export_mesh_type[] = {
{BC_MESH_TYPE_VIEW, "view", 0, "View", "Apply modifier's view settings"},
{BC_MESH_TYPE_RENDER, "render", 0, "Render", "Apply modifier's render settings"},
@@ -303,9 +315,15 @@ void WM_OT_collada_export(wmOperatorType *ot)
};
static EnumPropertyItem prop_bc_export_transformation_type[] = {
- {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"},
- {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"},
- {0, NULL, 0, NULL, NULL}
+ { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" },
+ { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ static EnumPropertyItem prop_bc_export_texture_type[] = {
+ { BC_TEXTURE_TYPE_MAT, "mat", 0, "Materials", "Export Materials" },
+ { BC_TEXTURE_TYPE_UV, "uv", 0, "UV Textures", "Export UV Textures (Face textures) as materials" },
+ { 0, NULL, 0, NULL, NULL }
};
ot->name = "Export COLLADA";
@@ -325,65 +343,74 @@ void WM_OT_collada_export(wmOperatorType *ot)
ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_boolean(ot->srna,
+ RNA_def_boolean(func,
"apply_modifiers", 0, "Apply Modifiers",
"Apply modifiers to exported mesh (non destructive))");
- RNA_def_int(ot->srna, "export_mesh_type", 0, INT_MIN, INT_MAX,
+ RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
"Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
- RNA_def_enum(ot->srna, "export_mesh_type_selection", prop_bc_export_mesh_type, 0,
+ RNA_def_enum(func, "export_mesh_type_selection", prop_bc_export_mesh_type, 0,
"Resolution", "Modifier resolution for export");
- RNA_def_boolean(ot->srna, "selected", 0, "Selection Only",
+ RNA_def_boolean(func, "selected", 0, "Selection Only",
"Export only selected elements");
- RNA_def_boolean(ot->srna, "include_children", 0, "Include Children",
+ RNA_def_boolean(func, "include_children", 0, "Include Children",
"Export all children of selected objects (even if not selected)");
- RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures",
+ RNA_def_boolean(func, "include_armatures", 0, "Include Armatures",
"Export related armatures (even if not selected)");
- RNA_def_boolean(ot->srna, "include_shapekeys", 1, "Include Shape Keys",
+ RNA_def_boolean(func, "include_shapekeys", 1, "Include Shape Keys",
"Export all Shape Keys from Mesh Objects");
- RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only",
+ RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
"Only export deforming bones with armatures");
-
- RNA_def_boolean(ot->srna, "active_uv_only", 0, "Only Selected UV Map",
+ RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
"Export only the selected UV Map");
- RNA_def_boolean(ot->srna, "include_uv_textures", 0, "Include UV Textures",
- "Export textures assigned to the object UV Maps");
-
- RNA_def_boolean(ot->srna, "include_material_textures", 0, "Include Material Textures",
- "Export textures assigned to the object Materials");
-
- RNA_def_boolean(ot->srna, "use_texture_copies", 1, "Copy",
+ RNA_def_boolean(func, "use_texture_copies", 1, "Copy",
"Copy textures to same folder where the .dae file is exported");
- RNA_def_boolean(ot->srna, "triangulate", 1, "Triangulate",
+ RNA_def_boolean(func, "triangulate", 1, "Triangulate",
"Export Polygons (Quads & NGons) as Triangles");
- RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instances",
+ RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances",
"Instantiate multiple Objects from same Data");
- RNA_def_boolean(ot->srna, "use_blender_profile", 1, "Use Blender Profile",
+ RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile",
"Export additional Blender specific information (for material, shaders, bones, etc.)");
- RNA_def_boolean(ot->srna, "sort_by_name", 0, "Sort by Object name",
+ RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name",
"Sort exported data by Object name");
- RNA_def_int(ot->srna, "export_transformation_type", 0, INT_MIN, INT_MAX,
- "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
- RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
- "Transform", "Transformation type for translation, scale and rotation");
+ RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
+ "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+
+ RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
+ "Transform", "Transformation type for translation, scale and rotation");
- RNA_def_boolean(ot->srna, "open_sim", 0, "Export to SL/OpenSim",
+
+ RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
+ "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
+
+ RNA_def_enum(func, "export_texture_type_selection", prop_bc_export_texture_type, 0,
+ "Texture Type", "Type for exported Textures (UV or MAT)");
+
+
+ RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim",
"Compatibility mode for SL, OpenSim and other compatible online worlds");
+
+ RNA_def_boolean(func, "limit_precision", 0,
+ "Limit Precision", "Reduce the precision of the exported data to 6 digits");
+
+ RNA_def_boolean(func, "keep_bind_info", 0,
+ "Keep Bind Info", "Store Bindpose information in custom bone properties for later use during Collada export");
+
}
@@ -395,7 +422,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
int find_chains;
int auto_connect;
int fix_orientation;
- int min_chain_length;
+ int min_chain_length;
+
+ int keep_bind_info;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -407,6 +436,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
find_chains = RNA_boolean_get(op->ptr, "find_chains");
auto_connect = RNA_boolean_get(op->ptr, "auto_connect");
fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation");
+
+ keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
+
min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
RNA_string_get(op->ptr, "filepath", filename);
@@ -416,7 +448,8 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
find_chains,
auto_connect,
fix_orientation,
- min_chain_length))
+ min_chain_length,
+ keep_bind_info) )
{
return OPERATOR_FINISHED;
}
@@ -453,6 +486,13 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
+
}
static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op)
@@ -508,5 +548,9 @@ void WM_OT_collada_import(wmOperatorType *ot)
0,
INT_MAX);
+ RNA_def_boolean(ot->srna,
+ "keep_bind_info", 0, "Keep Bind Info",
+ "Store Bindpose information in custom bone properties for later use during Collada export");
+
}
#endif
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index f01af22cec9..69335195b96 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -770,14 +770,17 @@ static int create_primitive_from_points(bContext *C, wmOperator *op, const float
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);
+ sizeof(MaskSplinePoint) * num_points);
mask_layer->act_spline = new_spline;
mask_layer->act_point = NULL;
+ const int spline_index = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
+
for (i = 0; i < num_points; i++) {
+ new_spline->tot_point = i + 1;
+
MaskSplinePoint *new_point = &new_spline->points[i];
BKE_mask_parent_init(&new_point->parent);
@@ -788,6 +791,12 @@ static int create_primitive_from_points(bContext *C, wmOperator *op, const float
new_point->bezt.h1 = handle_type;
new_point->bezt.h2 = handle_type;
BKE_mask_point_select_set(new_point, true);
+
+ if (mask_layer->splines_shapes.first) {
+ BKE_mask_layer_shape_changed_add(mask_layer,
+ spline_index + i,
+ true, true);
+ }
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 2b4f94a37ef..be7eb2bf9ed 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -834,13 +834,12 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
/* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
glPushMatrix();
-
+ glTranslatef(x + xofs, y + yofs, 0);
+ glScalef(zoomx, zoomy, 0);
if (stabmat) {
glMultMatrixf(stabmat);
}
-
- glTranslatef(x + xofs, y + yofs, 0);
- glScalef(maxdim * zoomx, maxdim * zoomy, 0);
+ glScalef(maxdim, maxdim, 0);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index eef03852007..35de390274c 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -889,7 +889,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
data->is_accurate = (event->val == KM_PRESS);
- /* fall-through */ /* update CV position */
+ ATTR_FALLTHROUGH; /* update CV position */
case MOUSEMOVE:
{
ScrArea *sa = CTX_wm_area(C);
@@ -1376,7 +1376,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
}
- /* fall-through */ /* update CV position */
+ ATTR_FALLTHROUGH; /* update CV position */
case MOUSEMOVE:
{
float B[2], mouse_coord[2], delta[2];
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index c4e87614732..a478526dee0 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -306,31 +306,30 @@ void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
{
- Mesh *me;
- MPoly *mp;
- MTexPoly *tf;
- MLoop *ml;
- MVert *mvert;
+ const Mesh *me;
+ const MPoly *mp;
+ const MLoop *ml;
+ const MVert *mvert;
int a, b;
bool ok = false;
float vec[3], bmat[3][3];
me = BKE_mesh_from_object(ob);
- if (!me || !me->mtpoly) return ok;
+ if (!me || !me->mloopuv) {
+ return ok;
+ }
copy_m3_m4(bmat, ob->obmat);
mvert = me->mvert;
mp = me->mpoly;
- tf = me->mtpoly;
- for (a = me->totpoly; a > 0; a--, mp++, tf++) {
+ for (a = me->totpoly; a > 0; a--, mp++) {
if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL))
continue;
ml = me->mloop + mp->totloop;
for (b = 0; b < mp->totloop; b++, ml++) {
- copy_v3_v3(vec, (mvert[ml->v].co));
- mul_m3_v3(bmat, vec);
+ mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
add_v3_v3v3(vec, vec, ob->obmat[3]);
minmax_v3v3_v3(r_min, r_max, vec);
}
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 3725590c188..07fedffaf80 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -384,7 +384,7 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
/* props */
RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500);
RNA_def_float_distance(ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00);
- RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.001, 100.00);
+ RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.0, 100.00);
RNA_def_float_distance(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index bf59693b856..5e44509e10a 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1472,7 +1472,7 @@ static void clip_to_ortho_planes(float v1[3], float v2[3], const float center[3]
/* could be v1 or v2 */
sub_v3_v3(v1, center);
- project_plane_v3_v3v3(closest, v1, dir);
+ project_plane_normalized_v3_v3v3(closest, v1, dir);
add_v3_v3(closest, center);
madd_v3_v3v3fl(v1, closest, dir, d);
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index e05ce727e22..1a2f9fdb62b 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -596,7 +596,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BMVert *v_new;
BLI_assert(l_sep->v == v);
- v_new = bmesh_urmv_loop_region(bm, l_sep);
+ v_new = BM_face_loop_separate_multi_isolated(bm, l_sep);
BLI_assert(BM_vert_find_first_loop(v));
BM_vert_select_set(bm, v, false);
@@ -665,7 +665,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_vert_select_set(bm, v, false);
- bmesh_vert_separate(bm, v, &vout, &vout_len, true);
+ bmesh_kernel_vert_separate(bm, v, &vout, &vout_len, true);
if (vout_len < 2) {
MEM_freeN(vout);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 65ee097e8e1..1f90b60a1f5 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -5235,8 +5235,10 @@ static int edbm_noise_exec(bContext *C, wmOperator *op)
else {
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- float tin, dum;
- externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL, false, false);
+ float tin = 0.0f, dum;
+ if (ma->mtex[ma->texact] != NULL) {
+ externtex(ma->mtex[ma->texact], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL, false, false);
+ }
eve->co[2] += fac * tin;
}
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 743efb246ab..3f06ba2ced4 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -57,6 +57,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_material.h"
+#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_editmesh.h"
#include "BKE_multires.h"
@@ -103,22 +104,26 @@ static void join_mesh_single(
/* vertex groups */
MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
+ MDeformVert *dvert_src = CustomData_get(&me->vdata, 0, CD_MDEFORMVERT);
- /* NB: vertex groups here are new version */
- if (dvert) {
- for (a = 0; a < me->totvert; a++) {
- for (b = 0; b < dvert[a].totweight; b++) {
- /* Find the old vertex group */
- bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr);
- int index;
- if (odg) {
- /* Search for a match in the new object, and set new index */
- for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) {
- if (STREQ(dg->name, odg->name)) {
- dvert[a].dw[b].def_nr = index;
- break;
- }
- }
+ /* Remap to correct new vgroup indices, if needed. */
+ if (dvert_src) {
+ BLI_assert(dvert != NULL);
+
+ /* Build src to merged mapping of vgroup indices. */
+ bDeformGroup *dg_src;
+ int *vgroup_index_map = alloca(sizeof(*vgroup_index_map) * BLI_listbase_count(&base_src->object->defbase));
+ bool is_vgroup_remap_needed = false;
+
+ for (dg_src = base_src->object->defbase.first, b = 0; dg_src; dg_src = dg_src->next, b++) {
+ vgroup_index_map[b] = defgroup_name_index(ob_dst, dg_src->name);
+ is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[b] != b);
+ }
+
+ if (is_vgroup_remap_needed) {
+ for (a = 0; a < me->totvert; a++) {
+ for (b = 0; b < dvert[a].totweight; b++) {
+ dvert[a].dw[b].def_nr = vgroup_index_map[dvert_src[a].dw[b].def_nr];
}
}
}
@@ -596,6 +601,9 @@ int join_mesh_exec(bContext *C, wmOperator *op)
BKE_key_sort(key);
}
+ /* Due to dependnecy cycle some other object might access old derived data. */
+ BKE_object_free_derived_caches(ob);
+
DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index ae458c722f9..a901560079a 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1154,7 +1154,21 @@ static int object_delete_exec(bContext *C, wmOperator *op)
base->object->id.name + 2, scene->id.name + 2);
continue;
}
+
+ /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this
+ * custom scene/object/base handling, and use generic lib remap/query for that.
+ * But this is for later (aka 2.8, once layers & co are settled and working).
+ */
+ if (use_global && base->object->id.lib == NULL) {
+ /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
+ BKE_libblock_delete(bmain, &base->object->id);
+ changed = true;
+ continue;
+ }
+
/* remove from Grease Pencil parent */
+ /* XXX This is likely not correct? Will also remove parent from grease pencil from other scenes,
+ * even when use_global is false... */
for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl->parent != NULL) {
@@ -1626,7 +1640,7 @@ static int convert_exec(bContext *C, wmOperator *op)
MetaBall *mb;
Mesh *me;
const short target = RNA_enum_get(op->ptr, "target");
- const bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
+ bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
int a, mballConverted = 0;
/* don't forget multiple users! */
@@ -1656,8 +1670,38 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
+
+ /* Ensure we get all meshes calculated with a sufficient data-mask,
+ * needed since re-evaluating single modifiers causes bugs if they depend
+ * on other objects data masks too, see: T50950. */
{
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Base *base = link->ptr.data;
+ ob = base->object;
+
+ /* The way object type conversion works currently (enforcing conversion of *all* objetcs using converted
+ * obdata, even some un-selected/hidden/inother scene ones, sounds totally bad to me.
+ * However, changing this is more design than bugfix, not to mention convoluted code below,
+ * so that will be for later.
+ * But at the very least, do not do that with linked IDs! */
+ if ((ID_IS_LINKED_DATABLOCK(ob) || ID_IS_LINKED_DATABLOCK(ob->data)) && !keep_original) {
+ keep_original = true;
+ BKE_reportf(op->reports, RPT_INFO,
+ "Converting some linked object/object data, enforcing 'Keep Original' option to True");
+ }
+
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ }
+
+ uint64_t customdata_mask_prev = scene->customdata_mask;
+ scene->customdata_mask |= CD_MASK_MESH;
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene);
+ scene->customdata_mask = customdata_mask_prev;
+ }
+
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Base *base = link->ptr.data;
ob = base->object;
if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
@@ -1700,7 +1744,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ED_rigidbody_object_remove(bmain, scene, newob);
}
}
- else if (ob->type == OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */
+ else if (ob->type == OB_MESH) {
ob->flag |= OB_DONE;
if (keep_original) {
@@ -1724,7 +1768,6 @@ static int convert_exec(bContext *C, wmOperator *op)
* cases this doesnt give correct results (when MDEF is used for eg)
*/
dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH);
- // dm = mesh_create_derived_no_deform(ob1, NULL); /* this was called original (instead of get_derived). man o man why! (ton) */
DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true);
@@ -1889,7 +1932,7 @@ static int convert_exec(bContext *C, wmOperator *op)
((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
}
}
- CTX_DATA_END;
+ BLI_freelistN(&selected_editable_bases);
if (!keep_original) {
if (mballConverted) {
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 968081818a2..ad43c48f0b9 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -51,6 +51,7 @@
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_modifier.h"
@@ -411,22 +412,18 @@ static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports)
}
}
else {
- if (ob->mat[i]) {
- BKE_reportf(reports, RPT_ERROR,
- "No active image found in material \"%s\" (%d) for object \"%s\"",
- ob->mat[i]->id.name + 2, i, ob->id.name + 2);
- }
- else if (((Mesh *) ob->data)->mat[i]) {
- BKE_reportf(reports, RPT_ERROR,
+ Material *mat = give_current_material(ob, i);
+ if (mat != NULL) {
+ BKE_reportf(reports, RPT_INFO,
"No active image found in material \"%s\" (%d) for object \"%s\"",
- ((Mesh *) ob->data)->mat[i]->id.name + 2, i, ob->id.name + 2);
+ mat->id.name + 2, i, ob->id.name + 2);
}
else {
- BKE_reportf(reports, RPT_ERROR,
- "No active image found in material (%d) for object \"%s\"",
+ BKE_reportf(reports, RPT_INFO,
+ "No active image found in material slot (%d) for object \"%s\"",
i, ob->id.name + 2);
}
- return false;
+ continue;
}
image->id.tag |= LIB_TAG_DOIT;
@@ -566,7 +563,11 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
Image *image;
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
- if ((image->id.tag & LIB_TAG_DOIT)) {
+ /* Some materials have no image, we just ignore those cases. */
+ if (image == NULL) {
+ bake_images->lookup[i] = -1;
+ }
+ else if (image->id.tag & LIB_TAG_DOIT) {
for (j = 0; j < i; j++) {
if (bake_images->data[j].image == image) {
bake_images->lookup[i] = j;
@@ -1172,6 +1173,9 @@ static int bake_exec(bContext *C, wmOperator *op)
BakeAPIRender bkr = {NULL};
Scene *scene = CTX_data_scene(C);
+ G.is_break = false;
+ G.is_rendering = true;
+
bake_set_props(op, scene);
bake_init_api_data(op, C, &bkr);
@@ -1223,6 +1227,7 @@ static int bake_exec(bContext *C, wmOperator *op)
finally:
+ G.is_rendering = false;
BLI_freelistN(&bkr.selected_objects);
return result;
}
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 0fe43c44d7d..568778c0a86 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -528,8 +528,7 @@ static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
if (!group)
return OPERATOR_CANCELLED;
- BKE_libblock_unlink(bmain, group, false, false);
- BKE_libblock_free(bmain, group);
+ BKE_libblock_delete(bmain, group);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index d601f5c3b14..1aa1407797b 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -793,7 +793,7 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
/* identifiers */
ot->name = "Add Modifier";
- ot->description = "Add a modifier to the active object";
+ ot->description = "Add a procedural operation/effect to the active object";
ot->idname = "OBJECT_OT_modifier_add";
/* api callbacks */
@@ -1484,7 +1484,6 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em->bm;
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
BMVert *bm_vert;
BMIter bm_iter;
GSet *visited;
@@ -1493,6 +1492,8 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mesh_ensure_skin_customdata(ob->data);
+ const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+
BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) &&
BLI_gset_add(visited, bm_vert))
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index b5fbe4ba586..3284af2df69 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -72,6 +72,7 @@
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_fcurve.h"
+#include "BKE_idprop.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
@@ -82,6 +83,7 @@
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_sca.h"
@@ -2101,30 +2103,52 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
single_tex_users_expand(bmain);
}
- BKE_main_id_clear_newpoins(bmain);
- DAG_relations_tag_update(bmain);
-}
+ /* Relink nodetrees' pointers that have been duplicated. */
+ FOREACH_NODETREE(bmain, ntree, id)
+ {
+ /* This is a bit convoluted, we want to root ntree of copied IDs and only those,
+ * so we first check that old ID has been copied and that ntree is root tree of old ID,
+ * then get root tree of new ID and remap its pointers to new ID... */
+ if (id->newid && (&ntree->id != id)) {
+ ntree = ntreeFromID(id->newid);
+ BKE_libblock_relink_to_newid(&ntree->id);
+ }
+ } FOREACH_NODETREE_END
-/******************************* Make Local ***********************************/
+ /* Relink datablock pointer properties */
+ {
+ IDP_RelinkProperty(scene->id.properties);
-/* helper for below, ma was checked to be not NULL */
-static void make_local_makelocalmaterial(Material *ma)
-{
- AnimData *adt;
- int b;
+ for (Base *base = scene->base.first; base; base = base->next) {
+ Object *ob = base->object;
+ if (!ID_IS_LINKED_DATABLOCK(ob)) {
+ IDP_RelinkProperty(ob->id.properties);
+ }
+ }
- id_make_local(G.main, &ma->id, false, false);
+ if (scene->nodetree) {
+ IDP_RelinkProperty(scene->nodetree->id.properties);
+ for (bNode *node = scene->nodetree->nodes.first; node; node = node->next) {
+ IDP_RelinkProperty(node->prop);
+ }
+ }
- for (b = 0; b < MAX_MTEX; b++)
- if (ma->mtex[b] && ma->mtex[b]->tex)
- id_make_local(G.main, &ma->mtex[b]->tex->id, false, false);
+ if (scene->gpd) {
+ IDP_RelinkProperty(scene->gpd->id.properties);
+ }
- adt = BKE_animdata_from_id(&ma->id);
- if (adt) BKE_animdata_make_local(adt);
+ IDP_RelinkProperty(scene->world->id.properties);
- /* nodetree? XXX */
+ if (scene->clip) {
+ IDP_RelinkProperty(scene->clip->id.properties);
+ }
+ }
+ BKE_main_id_clear_newpoins(bmain);
+ DAG_relations_tag_update(bmain);
}
+/******************************* Make Local ***********************************/
+
enum {
MAKE_LOCAL_SELECT_OB = 1,
MAKE_LOCAL_SELECT_OBDATA = 2,
@@ -2210,123 +2234,142 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
return changed;
}
-static int make_local_exec(bContext *C, wmOperator *op)
+static void make_local_animdata_tag_strips(ListBase *strips)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- AnimData *adt;
- ParticleSystem *psys;
- Material *ma, ***matarar;
- Lamp *la;
- ID *id;
- const int mode = RNA_enum_get(op->ptr, "type");
- int a, b;
-
- if (mode == MAKE_LOCAL_ALL) {
- /* de-select so the user can differentiate newly instanced from existing objects */
- BKE_scene_base_deselect_all(scene);
+ NlaStrip *strip;
- if (make_local_all__instance_indirect_unused(bmain, scene)) {
- BKE_report(op->reports, RPT_INFO,
- "Orphan library objects added to the current scene to avoid loss");
+ for (strip = strips->first; strip; strip = strip->next) {
+ if (strip->act) {
+ strip->act->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ if (strip->remap && strip->remap->target) {
+ strip->remap->target->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
- BKE_library_make_local(bmain, NULL, NULL, false, false); /* NULL is all libs */
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ make_local_animdata_tag_strips(&strip->strips);
}
+}
- tag_localizable_objects(C, mode);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
+/* Tag all actions used by given animdata to be made local. */
+static void make_local_animdata_tag(AnimData *adt)
+{
+ if (adt) {
+ /* Actions - Active and Temp */
+ if (adt->action) {
+ adt->action->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ if (adt->tmpact) {
+ adt->tmpact->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ /* Remaps */
+ if (adt->remap && adt->remap->target) {
+ adt->remap->target->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
- if (ob->id.lib)
- id_make_local(bmain, &ob->id, false, false);
- }
- CTX_DATA_END;
+ /* Drivers */
+ /* TODO: need to handle the ID-targets too? */
- /* maybe object pointers */
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if (ob->id.lib == NULL) {
- ID_NEW_REMAP(ob->parent);
+ /* NLA Data */
+ for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ make_local_animdata_tag_strips(&nlt->strips);
}
}
- CTX_DATA_END;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
- }
+}
- id = ob->data;
+static void make_local_material_tag(Material *ma)
+{
+ if (ma) {
+ ma->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ma->id));
- if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) {
- id_make_local(bmain, id, false, false);
- adt = BKE_animdata_from_id(id);
- if (adt) BKE_animdata_make_local(adt);
+ /* About nodetrees: root one is made local together with material, others we keep linked for now... */
- /* tag indirect data direct */
- matarar = give_matarar(ob);
- if (matarar) {
- for (a = 0; a < ob->totcol; a++) {
- ma = (*matarar)[a];
- if (ma)
- id_lib_extern(&ma->id);
- }
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (ma->mtex[a] && ma->mtex[a]->tex) {
+ ma->mtex[a]->tex->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
}
+ }
+}
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- id_make_local(bmain, &psys->part->id, false, false);
+static int make_local_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ParticleSystem *psys;
+ Material *ma, ***matarar;
+ Lamp *la;
+ const int mode = RNA_enum_get(op->ptr, "type");
+ int a;
+
+ /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
+ if (mode == MAKE_LOCAL_ALL) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
- adt = BKE_animdata_from_id(&ob->id);
- if (adt) BKE_animdata_make_local(adt);
+ /* de-select so the user can differentiate newly instanced from existing objects */
+ BKE_scene_base_deselect_all(scene);
+
+ if (make_local_all__instance_indirect_unused(bmain, scene)) {
+ BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
+ }
}
- CTX_DATA_END;
+ else {
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+ tag_localizable_objects(C, mode);
- if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
continue;
}
- if (ob->type == OB_LAMP) {
- la = ob->data;
-
- for (b = 0; b < MAX_MTEX; b++)
- if (la->mtex[b] && la->mtex[b]->tex)
- id_make_local(bmain, &la->mtex[b]->tex->id, false, false);
+ ob->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ob->id));
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ psys->part->id.tag &= ~LIB_TAG_PRE_EXISTING;
}
- else {
+
+ if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
for (a = 0; a < ob->totcol; a++) {
ma = ob->mat[a];
- if (ma)
- make_local_makelocalmaterial(ma);
+ if (ma) {
+ make_local_material_tag(ma);
+ }
}
matarar = (Material ***)give_matarar(ob);
if (matarar) {
for (a = 0; a < ob->totcol; a++) {
ma = (*matarar)[a];
- if (ma)
- make_local_makelocalmaterial(ma);
+ if (ma) {
+ make_local_material_tag(ma);
+ }
+ }
+ }
+
+ if (ob->type == OB_LAMP) {
+ BLI_assert(ob->data != NULL);
+ la = ob->data;
+ for (a = 0; a < MAX_MTEX; a++) {
+ if (la->mtex[a] && la->mtex[a]->tex) {
+ la->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
}
}
}
+
+ if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) && ob->data != NULL) {
+ ID *ob_data = ob->data;
+ ob_data->tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(ob_data));
+ }
}
CTX_DATA_END;
}
- BKE_main_id_clear_newpoins(bmain);
- WM_event_add_notifier(C, NC_WINDOW, NULL);
+ BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index 3d7a45843cc..edc3f6c784c 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -279,10 +279,10 @@ void DPAINT_OT_output_toggle(wmOperatorType *ot)
/***************************** Image Sequence Baking ******************************/
typedef struct DynamicPaintBakeJob {
- /* from wmJob */
- void *owner;
- short *stop, *do_update;
- float *progress;
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
struct Main *bmain;
Scene *scene;
@@ -297,13 +297,13 @@ typedef struct DynamicPaintBakeJob {
static void dpaint_bake_free(void *customdata)
{
- DynamicPaintBakeJob *job = customdata;
- MEM_freeN(job);
+ DynamicPaintBakeJob *job = customdata;
+ MEM_freeN(job);
}
static void dpaint_bake_endjob(void *customdata)
{
- DynamicPaintBakeJob *job = customdata;
+ DynamicPaintBakeJob *job = customdata;
DynamicPaintCanvasSettings *canvas = job->canvas;
canvas->flags &= ~MOD_DPAINT_BAKING;
@@ -311,7 +311,7 @@ static void dpaint_bake_endjob(void *customdata)
dynamicPaint_freeSurfaceData(job->surface);
G.is_rendering = false;
- BKE_spacedata_draw_locks(false);
+ BKE_spacedata_draw_locks(false);
WM_set_locked_interface(G.main->wm.first, false);
@@ -421,26 +421,26 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- DynamicPaintBakeJob *job = customdata;
+ DynamicPaintBakeJob *job = customdata;
- job->stop = stop;
- job->do_update = do_update;
- job->progress = progress;
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
job->start = PIL_check_seconds_timer();
job->success = 1;
- G.is_break = false; /* reset BKE_blender_test_break*/
+ G.is_break = false; /* reset BKE_blender_test_break*/
/* XXX annoying hack: needed to prevent data corruption when changing
* scene frame in separate threads
- */
- G.is_rendering = true;
- BKE_spacedata_draw_locks(true);
+ */
+ G.is_rendering = true;
+ BKE_spacedata_draw_locks(true);
dynamicPaint_bakeImageSequence(job);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
/*
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index e22a145b3a6..2541aaa4b11 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -4419,7 +4419,7 @@ void PE_undo_push(Scene *scene, const char *str)
undo= undo->prev;
}
if (undo) {
- while (edit->undo.first!=undo) {
+ while (edit->undo.first != undo) {
PTCacheUndo *first= edit->undo.first;
BLI_remlink(&edit->undo, first);
free_PTCacheUndo(first);
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index b5adf38527b..6460e83e2a0 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -631,71 +631,63 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom
#define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp")
#define FLUID_SUFFIX_SURFACE "fluidsurface"
-static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer)
+static bool fluid_init_filepaths(
+ ReportList *reports, FluidsimSettings *domainSettings, Object *fsDomain,
+ char *targetDir, char *targetFile)
{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
- FluidsimSettings *domainSettings= fluidmd->fss;
- FILE *fileCfg;
- int dirExist = 0;
- char newSurfdataPath[FILE_MAX]; /* modified output settings */
const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
- int outStringsChanged = 0;
/* prepare names... */
- const char *relbase= modifier_path_relbase(fsDomain);
+ const char *relbase = modifier_path_relbase(fsDomain);
+
+ /* We do not accept empty paths, they can end in random places silently, see T51176. */
+ if (domainSettings->surfdataPath[0] == '\0') {
+ modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
+ OB_FLUIDSIM_SURF_DIR_DEFAULT);
+ BKE_reportf(reports, RPT_WARNING, "Fluidsim: empty cache path, reset to default '%s'",
+ domainSettings->surfdataPath);
+ }
BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
- BLI_strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); /* if 0'd out below, this value is never used! */
- BLI_path_abs(targetDir, relbase); /* fixed #frame-no */
+ BLI_path_abs(targetDir, relbase);
/* .tmp: don't overwrite/delete original file */
BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
- // make sure all directories exist
- // as the bobjs use the same dir, this only needs to be checked
- // for the cfg output
- BLI_make_existing_file(targetFile);
-
- // check selected directory
- // simply try to open cfg file for writing to test validity of settings
- fileCfg = BLI_fopen(targetFile, "w");
- if (fileCfg) {
- dirExist = 1; fclose(fileCfg);
- // remove cfg dummy from directory test
- BLI_delete(targetFile, false, false);
- }
-
- if (targetDir[0] == '\0' || (!dirExist)) {
- char blendFile[FILE_MAX];
-
- // invalid dir, reset to current/previous
- BLI_split_file_part(G.main->name, blendFile, sizeof(blendFile));
- BLI_replace_extension(blendFile, FILE_MAX, ""); /* strip .blend */
- BLI_snprintf(newSurfdataPath, FILE_MAX, "//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
-
- BLI_snprintf(debugStrBuffer, 256, "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
- elbeemDebugOut(debugStrBuffer);
- outStringsChanged=1;
- }
-
- /* check if modified output dir is ok */
-#if 0
- if (outStringsChanged) {
- char dispmsg[FILE_MAX+256];
- int selection=0;
- BLI_strncpy(dispmsg, "Output settings set to: '", sizeof(dispmsg));
- strcat(dispmsg, newSurfdataPath);
- strcat(dispmsg, "'%t|Continue with changed settings %x1|Discard and abort %x0");
-
- /* ask user if thats what he/she wants... */
- selection = pupmenu(dispmsg);
- if (selection < 1) return 0; /* 0 from menu, or -1 aborted */
- BLI_strncpy(targetDir, newSurfdataPath, sizeof(targetDir));
- strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
- BLI_path_abs(targetDir, G.main->name); /* fixed #frame-no */
+ /* Ensure whole path exists and is wirtable. */
+ const bool dir_exists = BLI_dir_create_recursive(targetDir);
+ const bool is_writable = BLI_file_is_writable(targetFile);
+
+ /* We change path to some presumably valid default value, but do not allow bake process to continue,
+ * this gives user chance to set manually another path. */
+ if (!dir_exists || !is_writable) {
+ modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath),
+ OB_FLUIDSIM_SURF_DIR_DEFAULT);
+
+ if (!dir_exists) {
+ BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not create cache directory '%s', reset to default '%s'",
+ targetDir, domainSettings->surfdataPath);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "Fluidsim: cache directory '%s' is not writable, reset to default '%s'",
+ targetDir, domainSettings->surfdataPath);
+ }
+
+ BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
+ BLI_path_abs(targetDir, relbase);
+
+ /* .tmp: don't overwrite/delete original file */
+ BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
+
+ /* Ensure whole path exists and is wirtable. */
+ if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) {
+ BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not use default cache directory '%s', "
+ "please define a valid cache path manually", targetDir);
+ }
+ return false;
}
-#endif
- return outStringsChanged;
+
+ return true;
}
/* ******************************************************************************** */
@@ -857,7 +849,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
char targetDir[FILE_MAX]; // store & modify output settings
char targetFile[FILE_MAX]; // temp. store filename from targetDir for access
- int outStringsChanged = 0; // modified? copy back before baking
float domainMat[4][4];
float invDomMat[4][4];
@@ -943,7 +934,11 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
/* ******** prepare output file paths ******** */
- outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer);
+ if (!fluid_init_filepaths(reports, domainSettings, fsDomain, targetDir, targetFile)) {
+ fluidbake_free_data(channels, fobjects, fsset, fb);
+ return false;
+ }
+
channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra)
channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames;
@@ -968,11 +963,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
/* ******** start writing / exporting ******** */
// use .tmp, don't overwrite/delete original file
BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp);
-
- // make sure these directories exist as well
- if (outStringsChanged) {
- BLI_make_existing_file(targetFile);
- }
/* ******** export domain to elbeem ******** */
elbeemResetSettings(fsset);
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index e81aa584586..f36ebb3715e 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -99,45 +99,45 @@ static int ptcache_job_break(void *customdata)
static void ptcache_job_update(void *customdata, float progress, int *cancel)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
- if (ptcache_job_break(job)) {
- *cancel = 1;
- }
+ if (ptcache_job_break(job)) {
+ *cancel = 1;
+ }
- *(job->do_update) = true;
- *(job->progress) = progress;
+ *(job->do_update) = true;
+ *(job->progress) = progress;
}
static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
- job->stop = stop;
- job->do_update = do_update;
- job->progress = progress;
+ job->stop = stop;
+ job->do_update = do_update;
+ job->progress = progress;
- G.is_break = false;
+ G.is_break = false;
- /* XXX annoying hack: needed to prevent data corruption when changing
- * scene frame in separate threads
- */
- G.is_rendering = true;
- BKE_spacedata_draw_locks(true);
+ /* XXX annoying hack: needed to prevent data corruption when changing
+ * scene frame in separate threads
+ */
+ G.is_rendering = true;
+ BKE_spacedata_draw_locks(true);
BKE_ptcache_bake(job->baker);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
static void ptcache_job_endjob(void *customdata)
{
- PointCacheJob *job = customdata;
+ PointCacheJob *job = customdata;
Scene *scene = job->baker->scene;
- G.is_rendering = false;
- BKE_spacedata_draw_locks(false);
+ G.is_rendering = false;
+ BKE_spacedata_draw_locks(false);
WM_set_locked_interface(G.main->wm.first, false);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 8c5d25ad44d..43b1d033d23 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -116,6 +116,7 @@ typedef struct RenderJob {
ScrArea *sa;
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
+ bool supports_glsl_draw;
bool interface_locked;
} RenderJob;
@@ -210,7 +211,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
}
else {
if (rr->renlay == NULL) return;
- rectf = RE_RenderLayerGetPass(rr->renlay, SCE_PASS_COMBINED, viewname);
+ rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname);
}
}
if (rectf == NULL) return;
@@ -569,6 +570,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
* operate with.
*/
if (rr->do_exr_tile ||
+ !rj->supports_glsl_draw ||
ibuf->channels == 1 ||
U.image_draw_method != IMAGE_DRAW_METHOD_GLSL)
{
@@ -904,6 +906,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->orig_layer = 0;
rj->last_layer = 0;
rj->sa = sa;
+ rj->supports_glsl_draw = IMB_colormanagement_support_glsl_draw(&scene->view_settings);
BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings);
BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 1d0f433ba38..01050eda70b 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -38,7 +38,6 @@
#include "BLI_math_color_blend.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLI_jitter.h"
#include "BLI_threads.h"
#include "BLI_task.h"
@@ -257,10 +256,8 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
}
}
- BLI_lock_thread(LOCK_DRAW_IMAGE);
if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd)))
oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
/* will only work for non multiview correctly */
if (v3d) {
@@ -874,7 +871,7 @@ static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
typedef struct WriteTaskData {
RenderResult *rr;
- int cfra;
+ Scene tmp_scene;
} WriteTaskData;
static void write_result_func(TaskPool * __restrict pool,
@@ -883,10 +880,10 @@ static void write_result_func(TaskPool * __restrict pool,
{
OGLRender *oglrender = (OGLRender *) BLI_task_pool_userdata(pool);
WriteTaskData *task_data = (WriteTaskData *) task_data_v;
- Scene *scene = oglrender->scene;
+ Scene *scene = &task_data->tmp_scene;
RenderResult *rr = task_data->rr;
const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
- const int cfra = task_data->cfra;
+ const int cfra = scene->r.cfra;
bool ok;
/* Don't attempt to write if we've got an error. */
if (!oglrender->pool_ok) {
@@ -908,13 +905,11 @@ static void write_result_func(TaskPool * __restrict pool,
* This is because underlying calls do not use r.cfra but use scene
* for that.
*/
- Scene tmp_scene = *scene;
- tmp_scene.r.cfra = cfra;
if (is_movie) {
ok = RE_WriteRenderViewsMovie(&reports,
rr,
- &tmp_scene,
- &tmp_scene.r,
+ scene,
+ &scene->r,
oglrender->mh,
oglrender->movie_ctx_arr,
oglrender->totvideos,
@@ -934,8 +929,8 @@ static void write_result_func(TaskPool * __restrict pool,
true,
NULL);
- BKE_render_result_stamp_info(&tmp_scene, tmp_scene.camera, rr, false);
- ok = RE_WriteRenderViewsImage(NULL, rr, &tmp_scene, true, name);
+ BKE_render_result_stamp_info(scene, scene->camera, rr, false);
+ ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name);
if (!ok) {
BKE_reportf(&reports,
RPT_ERROR,
@@ -974,7 +969,7 @@ static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
Scene *scene = oglrender->scene;
WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data");
task_data->rr = rr;
- task_data->cfra = scene->r.cfra;
+ task_data->tmp_scene = *scene;
BLI_mutex_lock(&oglrender->task_mutex);
oglrender->num_scheduled_frames++;
if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) {
@@ -1088,7 +1083,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
/* render frame? */
if (oglrender->timer == event->customdata)
break;
- /* fall-through */
+ ATTR_FALLTHROUGH;
default:
/* nothing to do */
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 87c08dc6583..fa18b82507e 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -196,7 +196,7 @@ static Main *load_main_from_memory(const void *blend, int blend_size)
BlendFileData *bfd;
G.fileflags |= G_FILE_NO_UI;
- bfd = BLO_read_from_memory(blend, blend_size, NULL);
+ bfd = BLO_read_from_memory(blend, blend_size, NULL, BLO_READ_SKIP_NONE);
if (bfd) {
bmain = bfd->main;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 837573ad175..0878636d0fa 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -611,7 +611,7 @@ void WORLD_OT_new(wmOperatorType *ot)
/* identifiers */
ot->name = "New World";
ot->idname = "WORLD_OT_new";
- ot->description = "Add a new world";
+ ot->description = "Create a new world Data-Block";
/* api callbacks */
ot->exec = new_world_exec;
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index f11a8177bf8..4e02ff77a31 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -189,8 +189,12 @@ void ED_render_engine_changed(Main *bmain)
RE_FreePersistentData();
- for (scene = bmain->scene.first; scene; scene = scene->id.next)
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
ED_render_id_flush_update(bmain, &scene->id);
+ if (scene->nodetree) {
+ ntreeCompositUpdateRLayers(scene->nodetree);
+ }
+ }
}
/***************************** Updates ***********************************
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index 65f0fec50bc..c4a9af79ec2 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -44,6 +44,7 @@
#include "WM_types.h"
#include "ED_screen.h"
+#include "UI_interface.h"
#include "wm_window.h"
@@ -128,8 +129,8 @@ static ScrArea *find_area_image_empty(bContext *C)
/* new window uses x,y to set position */
ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
{
- wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
+ wmWindow *win = NULL;
ScrArea *sa = NULL;
SpaceImage *sima;
bool area_was_image = false;
@@ -138,25 +139,15 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
return NULL;
if (scene->r.displaymode == R_OUTPUT_WINDOW) {
- rcti rect;
- int sizex, sizey;
-
- sizex = 10 + (scene->r.xsch * scene->r.size) / 100;
- sizey = 40 + (scene->r.ysch * scene->r.size) / 100;
+ int sizex = 30 * UI_DPI_FAC + (scene->r.xsch * scene->r.size) / 100;
+ int sizey = 60 * UI_DPI_FAC + (scene->r.ysch * scene->r.size) / 100;
/* arbitrary... miniature image window views don't make much sense */
if (sizex < 320) sizex = 320;
if (sizey < 256) sizey = 256;
- /* some magic to calculate postition */
- /* pixelsize: mouse coords are in U.pixelsize units :/ */
- rect.xmin = (mx / U.pixelsize) + win->posx - sizex / 2;
- rect.ymin = (my / U.pixelsize) + win->posy - sizey / 2;
- rect.xmax = rect.xmin + sizex;
- rect.ymax = rect.ymin + sizey;
-
/* changes context! */
- if (WM_window_open_temp(C, &rect, WM_WINDOW_RENDER) == NULL) {
+ if (WM_window_open_temp(C, mx, my, sizex, sizey, WM_WINDOW_RENDER) == NULL) {
BKE_report(reports, RPT_ERROR, "Failed to open window!");
return NULL;
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index e6bb604d387..9cfaf3b4c1d 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1749,7 +1749,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr);
- uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.5 * U.widget_unit, U.widget_unit,
+ uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.6 * U.widget_unit, U.widget_unit,
&areaptr, "type", 0, 0.0f, 0.0f, 0.0f, 0.0f, "");
return xco + 1.7 * U.widget_unit;
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 93bac3f6660..216cbe9d7f4 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -566,7 +566,7 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
float rast_x = x + off_x * xzoom;
float rast_y = y + off_y * yzoom;
- GLfloat scissor[4];
+ GLfloat viewport[4];
int draw_w, draw_h;
/* Determine the smallest number of pixels we need to draw
@@ -581,9 +581,9 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
* fails if we zoom in on one really huge pixel so that it
* covers the entire screen).
*/
- glGetFloatv(GL_SCISSOR_BOX, scissor);
- draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom));
- draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom));
+ glGetFloatv(GL_VIEWPORT, viewport);
+ draw_w = min_ii(img_w - off_x, ceil((viewport[2] - rast_x) / xzoom));
+ draw_h = min_ii(img_h - off_y, ceil((viewport[3] - rast_y) / yzoom));
if (draw_w > 0 && draw_h > 0) {
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 5cd0d33c365..18f02aff482 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -766,7 +766,9 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
/* lower edge */
const int yval = sa->v2->vec.y - headery_init;
se = screen_findedge(sc, sa->v4, sa->v1);
- select_connected_scredge(sc, se);
+ if (se != NULL) {
+ select_connected_scredge(sc, se);
+ }
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v2 && sv != sa->v3) {
if (sv->flag) {
@@ -779,7 +781,9 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
/* upper edge */
const int yval = sa->v1->vec.y + headery_init;
se = screen_findedge(sc, sa->v2, sa->v3);
- select_connected_scredge(sc, se);
+ if (se != NULL) {
+ select_connected_scredge(sc, se);
+ }
for (sv = sc->vertbase.first; sv; sv = sv->next) {
if (sv != sa->v1 && sv != sa->v4) {
if (sv->flag) {
@@ -1758,7 +1762,7 @@ bool ED_screen_delete_scene(bContext *C, Scene *scene)
BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
- BKE_libblock_free(bmain, scene);
+ BKE_libblock_free_us(bmain, scene);
return true;
}
@@ -1922,7 +1926,6 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
ED_screen_set(C, sc);
- BKE_screen_free(oldscreen);
BKE_libblock_free(CTX_data_main(C), oldscreen);
/* After we've restored back to SCREENNORMAL, we have to wait with
@@ -2166,10 +2169,11 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
/* update animated texture nodes */
{
Tex *tex;
- for (tex = bmain->tex.first; tex; tex = tex->id.next)
+ for (tex = bmain->tex.first; tex; tex = tex->id.next) {
if (tex->use_nodes && tex->nodetree) {
ntreeTexTagAnimated(tex->nodetree);
}
+ }
}
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index a7a0a240259..c99d9add432 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -2808,7 +2808,7 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
bScreen *sc = CTX_wm_screen(C);
uiPopupMenu *pup;
uiLayout *layout;
- PointerRNA ptr1, ptr2;
+ PointerRNA ptr;
ScrEdge *actedge;
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
@@ -2820,22 +2820,17 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- WM_operator_properties_create(&ptr1, "SCREEN_OT_area_join");
-
- /* mouse cursor on edge, '4' can fail on wide edges... */
- RNA_int_set(&ptr1, "min_x", event->x + 4);
- RNA_int_set(&ptr1, "min_y", event->y + 4);
- RNA_int_set(&ptr1, "max_x", event->x - 4);
- RNA_int_set(&ptr1, "max_y", event->y - 4);
-
- WM_operator_properties_create(&ptr2, "SCREEN_OT_area_split");
-
+ ptr = uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
/* store initial mouse cursor position */
- RNA_int_set(&ptr2, "mouse_x", event->x);
- RNA_int_set(&ptr2, "mouse_y", event->y);
-
- uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, ptr2.data, WM_OP_INVOKE_DEFAULT, 0);
- uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, ptr1.data, WM_OP_INVOKE_DEFAULT, 0);
+ RNA_int_set(&ptr, "mouse_x", event->x);
+ RNA_int_set(&ptr, "mouse_y", event->y);
+
+ ptr = uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ /* mouse cursor on edge, '4' can fail on wide edges... */
+ RNA_int_set(&ptr, "min_x", event->x + 4);
+ RNA_int_set(&ptr, "min_y", event->y + 4);
+ RNA_int_set(&ptr, "max_x", event->x - 4);
+ RNA_int_set(&ptr, "max_y", event->y - 4);
UI_popup_menu_end(C, pup);
@@ -2903,10 +2898,23 @@ static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot)
static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op))
{
- wmOperator *lastop = CTX_wm_manager(C)->operators.last;
-
- if (lastop)
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmOperator *lastop = wm->operators.last;
+
+ /* Seek last registered operator */
+ while (lastop) {
+ if (lastop->type->flag & OPTYPE_REGISTER) {
+ break;
+ }
+ else {
+ lastop = lastop->prev;
+ }
+ }
+
+ if (lastop) {
+ WM_operator_free_all_after(wm, lastop);
WM_operator_repeat(C, lastop);
+ }
return OPERATOR_CANCELLED;
}
@@ -2941,8 +2949,9 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
layout = UI_popup_menu_layout(pup);
for (i = items - 1, lastop = wm->operators.last; lastop; lastop = lastop->prev, i--)
- if (WM_operator_repeat_check(C, lastop))
+ if ((lastop->type->flag & OPTYPE_REGISTER) && WM_operator_repeat_check(C, lastop)) {
uiItemIntO(layout, RNA_struct_ui_name(lastop->type->srna), ICON_NONE, op->type->idname, "index", i);
+ }
UI_popup_menu_end(C, pup);
@@ -3747,7 +3756,7 @@ static int screen_animation_cancel_exec(bContext *C, wmOperator *op)
bScreen *screen = ED_screen_animation_playing(CTX_wm_manager(C));
if (screen) {
- if (RNA_boolean_get(op->ptr, "restore_frame")) {
+ if (RNA_boolean_get(op->ptr, "restore_frame") && screen->animtimer) {
ScreenAnimData *sad = screen->animtimer->customdata;
Scene *scene = CTX_data_scene(C);
@@ -3874,22 +3883,11 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
- rcti rect;
- int sizex, sizey;
-
- sizex = 800 * UI_DPI_WINDOW_FAC;
- sizey = 480 * UI_DPI_WINDOW_FAC;
-
- /* some magic to calculate postition */
- /* pixelsize: mouse coords are in U.pixelsize units :/ */
- rect.xmin = (event->x / U.pixelsize) + win->posx - sizex / 2;
- rect.ymin = (event->y / U.pixelsize) + win->posy - sizey / 2;
- rect.xmax = rect.xmin + sizex;
- rect.ymax = rect.ymin + sizey;
+ int sizex = 800 * UI_DPI_FAC;
+ int sizey = 480 * UI_DPI_FAC;
/* changes context! */
- if (WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS) != NULL) {
+ if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_USERPREFS) != NULL) {
return OPERATOR_FINISHED;
}
else {
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index c2c52f58181..e273d3a40f0 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -670,7 +670,7 @@ static void SOUND_OT_mixdown(wmOperatorType *ot)
/* identifiers */
ot->name = "Mixdown";
- ot->description = "Mixes the scene's audio to a sound file";
+ ot->description = "Mix the scene's audio to a sound file";
ot->idname = "SOUND_OT_mixdown";
/* api callbacks */
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 14d0f909d23..59dd755173f 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -259,11 +259,9 @@ ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale
return NULL;
}
-/* Returns color in the display space, matching ED_space_image_color_sample(). */
-bool ED_space_clip_color_sample(Scene *scene, SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
+/* Returns color in linear space, matching ED_space_image_color_sample(). */
+bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3])
{
- const char *display_device = scene->display_settings.display_device;
- struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
ImBuf *ibuf;
float fx, fy, co[2];
bool ret = false;
@@ -299,11 +297,7 @@ bool ED_space_clip_color_sample(Scene *scene, SpaceClip *sc, ARegion *ar, int mv
ret = true;
}
}
-
- if (ret) {
- IMB_colormanagement_scene_linear_to_display_v3(r_col, display);
- }
-
+
IMB_freeImBuf(ibuf);
return ret;
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 547c2fba66f..e901b9f8026 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -72,7 +72,7 @@ void clip_graph_tracking_values_iterate_track(
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
for (coord = 0; coord < 2; coord++) {
- int i, prevfra = 0;
+ int i, prevfra = track->markers[0].framenr;
bool open = false;
float prevval = 0.0f;
@@ -179,6 +179,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
bool has_bundle = false;
char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2];
+ const bool used_for_stabilization = (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT));
if (track == act_track)
tracking->act_track = NULL;
@@ -200,7 +201,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
- if (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)) {
+ if (used_for_stabilization) {
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
}
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 05e69968e35..237082f948b 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -337,7 +337,7 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
switch (wmn->data) {
case ND_FRAME:
clip_scopes_tag_refresh(sa);
- /* fall-through */
+ ATTR_FALLTHROUGH;
case ND_FRAME_RANGE:
ED_area_tag_redraw(sa);
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 169eb76399b..56c240c3d20 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -875,8 +875,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
data->accurate = event->val == KM_PRESS;
}
-
- /* fall-through */
+ ATTR_FALLTHROUGH;
case MOUSEMOVE:
mdelta[0] = event->mval[0] - data->mval[0];
mdelta[1] = event->mval[1] - data->mval[1];
diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c
index 4332f3ea765..aa8518befaa 100644
--- a/source/blender/editors/space_clip/tracking_ops_plane.c
+++ b/source/blender/editors/space_clip/tracking_ops_plane.c
@@ -301,8 +301,7 @@ static int slide_plane_marker_modal(bContext *C,
if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
data->accurate = event->val == KM_PRESS;
}
-
- /* fall-through */
+ ATTR_FALLTHROUGH;
case MOUSEMOVE:
mdelta[0] = event->mval[0] - data->previous_mval[0];
mdelta[1] = event->mval[1] - data->previous_mval[1];
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 83469a48165..6c33091ff01 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1964,7 +1964,7 @@ int ED_path_extension_type(const char *path)
else if (BLI_testextensie(path, ".py")) {
return FILE_TYPE_PYSCRIPT;
}
- else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", NULL)) {
+ else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) {
return FILE_TYPE_TEXT;
}
else if (BLI_testextensie_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 631ff06a77a..ee0ec3fda39 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -48,9 +48,6 @@
#ifdef WIN32
# include <windows.h> /* need to include windows.h so _WIN32_IE is defined */
-# ifndef _WIN32_IE
-# define _WIN32_IE 0x0400 /* minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already */
-# endif
# include <shlobj.h> /* for SHGetSpecialFolderPath, has to be done before BLI_winstuff
* because 'near' is disabled through BLI_windstuff */
# include "BLI_winstuff.h"
@@ -169,12 +166,15 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path)
static void fsmenu_entry_generate_name(struct FSMenuEntry *fsentry, char *name, size_t name_size)
{
- char temp[FILE_MAX];
+ int offset = 0;
+ int len = name_size;
- BLI_strncpy(temp, fsentry->path, FILE_MAX);
- BLI_add_slash(temp);
- BLI_getlastdir(temp, name, name_size);
- BLI_del_slash(name);
+ if (BLI_path_name_at_index(fsentry->path, -1, &offset, &len)) {
+ /* use as size */
+ len += 1;
+ }
+
+ BLI_strncpy(name, &fsentry->path[offset], MIN2(len, name_size));
if (!name[0]) {
name[0] = '/';
name[1] = '\0';
@@ -537,28 +537,22 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* Finally get user favorite places */
if (read_bookmarks) {
UInt32 seed;
- OSErr err = noErr;
- CFArrayRef pathesArray;
- LSSharedFileListRef list;
- LSSharedFileListItemRef itemRef;
- CFIndex i, pathesCount;
- CFURLRef cfURL = NULL;
- CFStringRef pathString = NULL;
- list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
- pathesArray = LSSharedFileListCopySnapshot(list, &seed);
- pathesCount = CFArrayGetCount(pathesArray);
+ LSSharedFileListRef list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
+ CFArrayRef pathesArray = LSSharedFileListCopySnapshot(list, &seed);
+ CFIndex pathesCount = CFArrayGetCount(pathesArray);
- for (i = 0; i < pathesCount; i++) {
- itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i);
+ for (CFIndex i = 0; i < pathesCount; i++) {
+ LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i);
- err = LSSharedFileListItemResolve(itemRef,
- kLSSharedFileListNoUserInteraction |
- kLSSharedFileListDoNotMountVolumes,
- &cfURL, NULL);
- if (err != noErr)
+ CFURLRef cfURL = NULL;
+ OSErr err = LSSharedFileListItemResolve(itemRef,
+ kLSSharedFileListNoUserInteraction |
+ kLSSharedFileListDoNotMountVolumes,
+ &cfURL, NULL);
+ if (err != noErr || !cfURL)
continue;
- pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
+ CFStringRef pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8))
continue;
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index b9d98dfe794..8037c2deb5b 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -428,7 +428,6 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
RenderPass *rpass;
const char *fake_name;
int nr;
- int passflag = 0;
/* may have been freed since drawing */
rr = BKE_image_acquire_renderresult(scene, image);
@@ -450,30 +449,31 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
fake_name = ui_imageuser_pass_fake_name(rl);
if (fake_name) {
- BLI_strncpy(rpass_fake.internal_name, fake_name, sizeof(rpass_fake.internal_name));
+ BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name));
nr += 1;
}
+ ListBase added_passes;
+ BLI_listbase_clear(&added_passes);
+
/* rendered results don't have a Combined pass */
/* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
-
/* just show one pass of each kind */
- if (passflag & rpass->passtype)
+ if (BLI_findstring_ptr(&added_passes, rpass->name, offsetof(LinkData, data))) {
continue;
+ }
+ BLI_addtail(&added_passes, BLI_genericNodeN(rpass->name));
- passflag |= rpass->passtype;
-
-final:
- uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0,
UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
}
+ BLI_freelistN(&added_passes);
+
if (fake_name) {
- fake_name = NULL;
- rpass = &rpass_fake;
- nr = 0;
- goto final;
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass_fake.name), 0, 0,
+ UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, 0.0f, 0.0, 0, -1, "");
}
BKE_image_release_renderresult(scene, image);
@@ -633,7 +633,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt
int rp_index = iuser->pass + 1;
for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
- if (rp->passtype != rpass->passtype) {
+ if (!STREQ(rp->name, rpass->name)) {
iuser->pass = rp_index;
changed = true;
break;
@@ -650,7 +650,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt
}
for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
- if (rp->passtype == rpass->passtype) {
+ if (STREQ(rp->name, rpass->name)) {
iuser->pass = rp_index - 1;
changed = true;
break;
@@ -712,6 +712,10 @@ static void uiblock_layer_pass_buttons(
const char *display_name = "";
const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO) != 0;
+ if (iuser->scene == NULL) {
+ return;
+ }
+
uiLayoutRow(layout, true);
/* layer menu is 1/3 larger than pass */
@@ -769,7 +773,7 @@ static void uiblock_layer_pass_buttons(
fake_name = ui_imageuser_pass_fake_name(rl);
rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL);
- display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : "");
+ display_name = rpass ? rpass->name : (fake_name ? fake_name : "");
rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
but = uiDefMenuBut(
block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name),
@@ -1204,7 +1208,7 @@ void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr)
case S3D_DISPLAY_SIDEBYSIDE:
{
uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
- /* fall-through */
+ ATTR_FALLTHROUGH;
}
case S3D_DISPLAY_TOPBOTTOM:
{
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 324a3cb13b7..501a5a35899 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1067,6 +1067,7 @@ typedef struct ImageOpenData {
typedef struct ImageFrameRange {
struct ImageFrameRange *next, *prev;
ListBase frames;
+ /** The full path of the first file in the list of image files */
char filepath[FILE_MAX];
} ImageFrameRange;
@@ -1092,8 +1093,7 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
/**
* \brief Get a list of frames from the list of image files matching the first file name sequence pattern
* \param ptr [in] the RNA pointer containing the "directory" entry and "files" collection
- * \param frames [out] the list of frame numbers found in the files matching the first one by name
- * \param path [out] the full path of the first file in the list of image files
+ * \param frames_all [out] the list of frame numbers found in the files matching the first one by name
*/
static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all)
{
@@ -1890,7 +1890,6 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
}
else {
colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf);
- IMB_metadata_copy(colormanaged_ibuf, ibuf);
ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy);
save_imbuf_post(ibuf, colormanaged_ibuf);
}
@@ -2900,11 +2899,9 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
}
}
-/* Returns color in the display space, matching ED_space_node_color_sample(). */
-bool ED_space_image_color_sample(Scene *scene, SpaceImage *sima, ARegion *ar, int mval[2], float r_col[3])
+/* Returns color in linear space, matching ED_space_node_color_sample(). */
+bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], float r_col[3])
{
- const char *display_device = scene->display_settings.display_device;
- struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
void *lock;
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
float fx, fy;
@@ -2938,10 +2935,6 @@ bool ED_space_image_color_sample(Scene *scene, SpaceImage *sima, ARegion *ar, in
}
}
- if (ret) {
- IMB_colormanagement_scene_linear_to_display_v3(r_col, display);
- }
-
ED_space_image_release_buffer(sima, ibuf, lock);
return ret;
}
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 5355b8012db..c774b99629c 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -552,7 +552,7 @@ void nla_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
- strcpy(pt->category, "Modifiers");
+ strcpy(pt->category, "Modifiers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_modifiers;
pt->poll = nla_strip_eval_panel_poll;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 93dcdbb5c02..255fc0d6f8f 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -362,7 +362,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
glVertex2f(strip->start, yminc);
glEnd();
}
- /* fall-through */
+ ATTR_FALLTHROUGH;
/* this only draws after the strip */
case NLASTRIP_EXTEND_HOLD_FORWARD:
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index d31a475e45e..f58b4050834 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -1234,6 +1234,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_REFRACTION:
+ case SH_NODE_BSDF_PRINCIPLED:
ntype->draw_buttons = node_shader_buts_glossy;
break;
case SH_NODE_BSDF_ANISOTROPIC:
@@ -1320,9 +1321,6 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point
PropertyRNA *prop;
const char *layer_name;
char scene_name[MAX_ID_NAME - 2];
- wmOperatorType *ot = WM_operatortype_find("RENDER_OT_render", 1);
-
- BLI_assert(ot != 0);
uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL);
@@ -1339,11 +1337,9 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point
scn_ptr = RNA_pointer_get(ptr, "scene");
RNA_string_get(&scn_ptr, "name", scene_name);
- WM_operator_properties_create_ptr(&op_ptr, ot);
+ op_ptr = uiItemFullO(row, "RENDER_OT_render", "", ICON_RENDER_STILL, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&op_ptr, "layer", layer_name);
RNA_string_set(&op_ptr, "scene", scene_name);
- uiItemFullO_ptr(row, ot, "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
-
}
@@ -1792,6 +1788,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
Scene *scene = CTX_data_scene(C);
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
PointerRNA active_input_ptr, op_ptr;
+ wmOperatorType *ot;
uiLayout *row, *col;
int active_index;
const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
@@ -1830,11 +1827,10 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
active_input_ptr.id.data = ptr->id.data;
col = uiLayoutColumn(row, true);
- op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
- ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false);
+ op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&op_ptr, "direction", 1);
- op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
- ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&op_ptr, "direction", 2);
if (active_input_ptr.data) {
@@ -2166,14 +2162,7 @@ static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi
static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
{
- PointerRNA op_ptr;
- wmOperatorType *ot = WM_operatortype_find("NODE_OT_switch_view_update", 1);
-
- BLI_assert(ot != 0);
-
- WM_operator_properties_create_ptr(&op_ptr, ot);
-
- uiItemFullO_ptr(layout, ot, "Update Views", ICON_FILE_REFRESH, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
+ uiItemFullO(layout, "NODE_OT_switch_view_update", "Update Views", ICON_FILE_REFRESH, NULL, WM_OP_INVOKE_DEFAULT, 0);
}
static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2489,6 +2478,11 @@ static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), P
uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
}
+static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE);
+}
+
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
@@ -2716,6 +2710,8 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_SUNBEAMS:
ntype->draw_buttons = node_composit_buts_sunbeams;
break;
+ case CMP_NODE_BRIGHTCONTRAST:
+ ntype->draw_buttons = node_composit_buts_brightcontrast;
}
}
@@ -3087,7 +3083,7 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
node_file_output_socket_draw(C, layout, ptr, node_ptr);
return;
}
-
+
if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) {
node_socket_button_label(C, layout, ptr, node_ptr, text);
return;
@@ -3436,7 +3432,6 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
/* store current linewidth */
float linew;
float arrow[2], arrow1[2], arrow2[2];
- const float px_fac = UI_DPI_WINDOW_FAC;
glGetFloatv(GL_LINE_WIDTH, &linew);
/* we can reuse the dist variable here to increment the GL curve eval amount*/
@@ -3463,7 +3458,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
}
if (do_triple) {
UI_ThemeColorShadeAlpha(th_col3, -80, -120);
- glLineWidth(4.0f * px_fac);
+ glLineWidth(4.0f);
glBegin(GL_LINE_STRIP);
for (i = 0; i <= LINK_RESOL; i++) {
@@ -3483,7 +3478,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
* for Intel hardware, this breaks with GL_LINE_STRIP and
* changing color in begin/end blocks.
*/
- glLineWidth(1.5f * px_fac);
+ glLineWidth(1.5f);
if (do_shaded) {
glBegin(GL_LINES);
for (i = 0; i < LINK_RESOL; i++) {
@@ -3618,7 +3613,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
return;
if (link->fromsock->flag & SOCK_UNAVAIL)
return;
-
+
if (link->flag & NODE_LINK_VALID) {
/* special indicated link, on drop-node */
if (link->flag & NODE_LINKFLAG_HILITE) {
@@ -3638,7 +3633,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
th_col1 = TH_REDALERT;
}
}
-
+
node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
// node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
}
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index d49df2afbd4..dc6b06790e0 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -44,6 +44,8 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_texture.h"
#include "ED_node.h" /* own include */
#include "ED_screen.h"
@@ -105,13 +107,15 @@ static bool add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int
if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
- for (i = 0; i < tot - 1; i++)
- for (b = 0; b < NODE_LINK_RESOL; b++)
+ for (i = 0; i < tot - 1; i++) {
+ for (b = 0; b < NODE_LINK_RESOL; b++) {
if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) {
result[0] = (mcoords[i][0] + mcoords[i + 1][0]) / 2.0f;
result[1] = (mcoords[i][1] + mcoords[i + 1][1]) / 2.0f;
return 1;
}
+ }
+ }
}
return 0;
}
@@ -312,7 +316,10 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
switch (snode->nodetree->type) {
case NTREE_SHADER:
- type = SH_NODE_TEX_IMAGE;
+ if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C)))
+ type = SH_NODE_TEX_IMAGE;
+ else
+ type = SH_NODE_TEXTURE;
break;
case NTREE_TEXTURE:
type = TEX_NODE_IMAGE;
@@ -333,7 +340,14 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- node->id = (ID *)ima;
+ if (type == SH_NODE_TEXTURE) {
+ Tex *tex = BKE_texture_add(CTX_data_main(C), DATA_(ima->id.name));
+ tex->ima = ima;
+ node->id = (ID *)tex;
+ WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, node->id);
+ }
+ else
+ node->id = (ID *)ima;
/* When adding new image file via drag-drop we need to load imbuf in order
* to get proper image source.
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index f0567924edd..925298451ce 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -133,6 +133,7 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
int in_out;
uiLayout *layout = pa->layout, *row, *split, *col;
PointerRNA ptr, sockptr, opptr;
+ wmOperatorType *ot;
if (!ntree)
return;
@@ -146,23 +147,25 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
split = uiLayoutRow(row, true);
col = uiLayoutColumn(split, true);
+ ot = WM_operatortype_find("NODE_OT_tree_socket_add", false);
uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input",
NULL, 0, 0, 0, 0);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_IN);
col = uiLayoutColumn(split, true);
uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output",
NULL, 0, 0, 0, 0);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_OUT);
+ ot = WM_operatortype_find("NODE_OT_tree_socket_move", false);
col = uiLayoutColumn(row, true);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "direction", 1);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "direction", 2);
if (sock) {
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index ab40c55b59d..6e25c87d274 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -820,14 +820,6 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f);
-#ifdef WITH_COMPOSITOR
- if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) {
- if (COM_isHighlightedbNode(node)) {
- UI_ThemeColorBlend(color_id, TH_ACTIVE, 0.5f);
- }
- }
-#endif
-
glLineWidth(1.0f);
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
@@ -989,16 +981,6 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
if (node->flag & NODE_MUTED)
UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f);
-#ifdef WITH_COMPOSITOR
- if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) {
- if (COM_isHighlightedbNode(node)) {
- UI_ThemeColorBlend(color_id, TH_ACTIVE, 0.5f);
- }
- }
-#else
- (void)ntree;
-#endif
-
UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
/* outline active and selected emphasis */
@@ -1253,15 +1235,9 @@ static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, const float center[2]
static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
SpaceNode *snode = CTX_wm_space_node(C);
-
+
node_uiblocks_init(C, ntree);
-
-#ifdef WITH_COMPOSITOR
- if (ntree->type == NTREE_COMPOSIT) {
- COM_startReadHighlights();
- }
-#endif
-
+
node_update_nodetree(C, ntree);
node_draw_nodetree(C, ar, snode, ntree, parent_key);
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index fdfe316f5ed..5f8f839025f 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -505,8 +505,6 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce)
nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
ntreeUpdateTree(CTX_data_main(C), sce->nodetree);
-
- // XXX ntreeCompositForceHidden(sce->nodetree);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
@@ -582,17 +580,11 @@ void snode_set_context(const bContext *C)
}
}
- if (snode->nodetree != ntree || snode->id != id || snode->from != from || snode->treepath.last == NULL) {
+ if (snode->nodetree != ntree || snode->id != id || snode->from != from ||
+ (snode->treepath.last == NULL && ntree))
+ {
ED_node_tree_start(snode, ntree, id, from);
}
-
- /* XXX Legacy hack to update render layer node outputs.
- * This should be handled by the depsgraph eventually ...
- */
- if (ED_node_is_compositor(snode) && snode->nodetree) {
- /* update output sockets based on available layers */
- ntreeCompositForceHidden(snode->nodetree);
- }
}
void snode_update(SpaceNode *snode, bNode *node)
@@ -2094,7 +2086,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
/* make sure all clipboard nodes would be valid in the target tree */
all_nodes_valid = true;
for (node = clipboard_nodes_lb->first; node; node = node->next) {
- if (!node->typeinfo->poll_instance(node, ntree)) {
+ if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) {
all_nodes_valid = false;
BKE_reportf(op->reports, RPT_ERROR, "Cannot add node %s into node tree %s", node->name, ntree->id.name + 2);
}
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 26eeaa91dd0..914f8ffbe10 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -92,9 +92,9 @@ static int node_group_operator_editable(bContext *C)
* Disabled otherwise to allow pynodes define their own operators
* with same keymap.
*/
- if (STREQ(snode->tree_idname, "ShaderNodeTree") ||
- STREQ(snode->tree_idname, "CompositorNodeTree") ||
- STREQ(snode->tree_idname, "TextureNodeTree"))
+ if (ED_node_is_shader(snode) ||
+ ED_node_is_compositor(snode) ||
+ ED_node_is_texture(snode))
{
return true;
}
@@ -112,11 +112,11 @@ static const char *group_node_idname(bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
- if (STREQ(snode->tree_idname, "ShaderNodeTree"))
+ if (ED_node_is_shader(snode))
return "ShaderNodeGroup";
- else if (STREQ(snode->tree_idname, "CompositorNodeTree"))
+ else if (ED_node_is_compositor(snode))
return "CompositorNodeGroup";
- else if (STREQ(snode->tree_idname, "TextureNodeTree"))
+ else if (ED_node_is_texture(snode))
return "TextureNodeGroup";
return "";
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index 8c5d2d82468..f497a06cb12 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -345,7 +345,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
- if (ibuf == NULL) {
+ if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) {
BKE_image_release_ibuf(ima, ibuf, lock);
return OPERATOR_CANCELLED;
}
@@ -417,20 +417,18 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
}
}
-/* Returns color in the display space, matching ED_space_image_color_sample().
+/* Returns color in linear space, matching ED_space_image_color_sample().
* And here we've got recursion in the comments tips...
*/
-bool ED_space_node_color_sample(Scene *scene, SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3])
+bool ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3])
{
- const char *display_device = scene->display_settings.display_device;
- struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
void *lock;
Image *ima;
ImBuf *ibuf;
float fx, fy, bufx, bufy;
bool ret = false;
- if (STREQ(snode->tree_idname, ntreeType_Composite->idname) || (snode->flag & SNODE_BACKDRAW) == 0) {
+ if (!ED_node_is_compositor(snode) || (snode->flag & SNODE_BACKDRAW) == 0) {
/* use viewer image for color sampling only if we're in compositor tree
* with backdrop enabled
*/
@@ -471,10 +469,6 @@ bool ED_space_node_color_sample(Scene *scene, SpaceNode *snode, ARegion *ar, int
}
}
- if (ret) {
- IMB_colormanagement_scene_linear_to_display_v3(r_col, display);
- }
-
BKE_image_release_ibuf(ima, ibuf, lock);
return ret;
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index bbdf6feef01..2267316d257 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -753,6 +753,10 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi
break;
}
break;
+ case NC_WM:
+ if (wmn->data == ND_JOB)
+ ED_region_tag_redraw(ar);
+ break;
case NC_SCENE:
case NC_MATERIAL:
case NC_TEXTURE:
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 684a1f9fd67..121fe812016 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1040,9 +1040,6 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
struct DrawIconArg arg;
float aspect;
- /* icons tiny bit away from text */
- x -= 0.15f * UI_UNIT_Y;
-
/* make function calls a bit compacter */
arg.block = block;
arg.id = tselem->id;
@@ -1053,8 +1050,10 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
/* placement of icons, copied from interface_widgets.c */
aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
- arg.x = x = x + 4.0f * aspect;
- arg.y = y = y + 0.1f * UI_UNIT_Y;
+ x += 2.0f * aspect;
+ y += 2.0f * aspect;
+ arg.x = x;
+ arg.y = y;
if (tselem->type) {
switch (tselem->type) {
@@ -1389,9 +1388,9 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
UI_draw_roundbox_corner_set(UI_CNR_ALL);
glColor4ub(255, 255, 255, 100);
UI_draw_roundbox(
- (float) *offsx - 1.0f * ufac,
+ (float) *offsx + 1.0f * ufac,
(float)ys + 1.0f * ufac,
- (float)*offsx + UI_UNIT_X - 2.0f * ufac,
+ (float)*offsx + UI_UNIT_X - 1.0f * ufac,
(float)ys + UI_UNIT_Y - ufac,
(float)UI_UNIT_Y / 2.0f - ufac);
glEnable(GL_BLEND); /* roundbox disables */
@@ -1536,9 +1535,9 @@ static void outliner_draw_tree_element(
if (active != OL_DRAWSEL_NONE) {
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox(
- (float)startx + UI_UNIT_X,
+ (float)startx + UI_UNIT_X + 1.0f * ufac,
(float)*starty + 1.0f * ufac,
- (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac,
+ (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac,
(float)*starty + UI_UNIT_Y - 1.0f * ufac,
UI_UNIT_Y / 2.0f - 1.0f * ufac);
glEnable(GL_BLEND); /* roundbox disables it */
@@ -1549,16 +1548,13 @@ static void outliner_draw_tree_element(
/* open/close icon, only when sublevels, except for scene */
if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
int icon_x;
- if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE))
- icon_x = startx;
- else
- icon_x = startx + 5 * ufac;
+ icon_x = startx;
// icons a bit higher
if (TSELEM_OPEN(tselem, soops))
- UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_DOWN);
+ UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN);
else
- UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_RIGHT);
+ UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT);
}
offsx += UI_UNIT_X;
@@ -1568,7 +1564,7 @@ static void outliner_draw_tree_element(
tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, 1.0f);
- offsx += UI_UNIT_X;
+ offsx += UI_UNIT_X + 2 * ufac;
}
else
offsx += 2 * ufac;
@@ -1576,16 +1572,16 @@ static void outliner_draw_tree_element(
if (tselem->type == 0 && ID_IS_LINKED_DATABLOCK(tselem->id)) {
glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
if (tselem->id->tag & LIB_TAG_MISSING) {
- UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN);
+ UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN);
}
else if (tselem->id->tag & LIB_TAG_INDIRECT) {
- UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT);
+ UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT);
}
else {
- UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT);
+ UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT);
}
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
- offsx += UI_UNIT_X;
+ offsx += UI_UNIT_X + 2 * ufac;
}
glDisable(GL_BLEND);
@@ -1757,7 +1753,7 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio
// gray hierarchy lines
UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f);
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
- startx = 6;
+ startx = UI_UNIT_X / 2 - 1.0f;
outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
// items themselves
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 345ac353c11..265a19b9e7e 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -309,9 +309,12 @@ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeSto
ID *id = tselem->id;
BLI_assert(te->idcode != 0 && id != NULL);
- BLI_assert(te->idcode != ID_LI || ((Library *)id)->parent == NULL);
UNUSED_VARS_NDEBUG(te);
+ if (te->idcode == ID_LI && ((Library *)id)->parent != NULL) {
+ BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked library '%s'", id->name);
+ return;
+ }
if (id->tag & LIB_TAG_INDIRECT) {
BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name);
return;
@@ -516,7 +519,8 @@ void OUTLINER_OT_id_remap(wmOperatorType *ot)
ot->flag = 0;
- RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
+ prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace");
RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, outliner_id_itemf);
@@ -1940,7 +1944,7 @@ static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEv
{
/* present a prompt to informing users that this change is irreversible */
return WM_operator_confirm_message(C, op,
- "Purging unused data-blocks cannot be undone. "
+ "Purging unused data-blocks cannot be undone and saves to current .blend file. "
"Click here to proceed...");
}
@@ -1962,7 +1966,8 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
/* identifiers */
ot->idname = "OUTLINER_OT_orphans_purge";
ot->name = "Purge All";
- ot->description = "Clear all orphaned data-blocks without any users from the file (cannot be undone)";
+ ot->description = "Clear all orphaned data-blocks without any users from the file "
+ "(cannot be undone, saves to current .blend file)";
/* callbacks */
ot->invoke = outliner_orphans_purge_invoke;
@@ -2068,74 +2073,62 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false);
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
-
PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
+ /* Cannot use uiItemEnumO()... have multiple properties to set. */
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_OBJECT);
- /* Cannot use uiItemEnumO()... have multiple properties to set. */
- uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
+
/* par becomes parent, make the associated menus */
if (par->type == OB_ARMATURE) {
- WM_operator_properties_create_ptr(&ptr, ot);
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE);
- uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME);
- uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE);
- uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO);
- uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_BONE);
- uiItemFullO_ptr(layout, ot, IFACE_("Bone"),
- 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
}
else if (par->type == OB_CURVE) {
- WM_operator_properties_create_ptr(&ptr, ot);
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_CURVE);
- uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_FOLLOW);
- uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_PATH_CONST);
- uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
}
else if (par->type == OB_LATTICE) {
- WM_operator_properties_create_ptr(&ptr, ot);
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_LATTICE);
- uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
}
UI_popup_menu_end(C, pup);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 89df471990a..7e05c76b35b 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -470,10 +470,11 @@ static eOLDrawState tree_element_active_defgroup(
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
}
else {
- if (ob == OBACT)
+ if (ob == OBACT) {
if (ob->actdef == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
+ }
}
return OL_DRAWSEL_NONE;
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 4eda7977622..29dcf73109c 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -235,8 +235,7 @@ static void unlink_group_cb(
}
else {
Main *bmain = CTX_data_main(C);
- BKE_libblock_unlink(bmain, group, false, false);
- BKE_libblock_free(bmain, group);
+ BKE_libblock_delete(bmain, group);
}
}
@@ -399,7 +398,7 @@ static void object_deselect_cb(
static void object_delete_cb(
bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+ TreeStoreElem *tsep, TreeStoreElem *tselem, void *user_data)
{
Base *base = (Base *)te->directdata;
@@ -431,6 +430,13 @@ static void object_delete_cb(
tselem->id = NULL;
#endif
}
+ else {
+ /* No base, means object is no more instantiated in any scene.
+ * Should not happen ideally, but does happens, see T51625.
+ * Rather than twisting in all kind of ways to address all possible cases leading to that situation, simpler
+ * to allow deleting such object as a mere generic data-block. */
+ id_delete_cb(C, reports, scene, te, tsep, tselem, user_data);
+ }
}
static void id_local_cb(
@@ -1051,7 +1057,7 @@ static EnumPropertyItem prop_group_op_types[] = {
{OL_GROUPOP_UNLINK, "UNLINK", 0, "Unlink Group", ""},
{OL_GROUPOP_LOCAL, "LOCAL", 0, "Make Local Group", ""},
{OL_GROUPOP_LINK, "LINK", 0, "Link Group Objects to Scene", ""},
- {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", "WARNING: no undo"},
+ {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", ""},
{OL_GROUPOP_REMAP, "REMAP", 0, "Remap Users",
"Make all users of selected data-blocks to use instead current (clicked) one"},
{OL_GROUPOP_INSTANCE, "INSTANCE", 0, "Instance Groups in Scene", ""},
@@ -1090,7 +1096,7 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op)
DAG_relations_tag_update(CTX_data_main(C));
break;
case OL_GROUPOP_DELETE:
- WM_operator_name_call(C, "OUTLINER_OT_id_delete", WM_OP_INVOKE_REGION_WIN, NULL);
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
break;
case OL_GROUPOP_REMAP:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
@@ -1254,6 +1260,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
if (idlevel > 0) {
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
+ ED_undo_push(C, "Delete");
}
break;
}
@@ -1261,6 +1268,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
if (idlevel > 0) {
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
+ ED_undo_push(C, "Remap");
}
break;
}
@@ -1369,18 +1377,20 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- ED_undo_push(C, "Rename");
+ ED_undo_push(C, "Rename Library");
break;
}
case OL_LIB_DELETE:
{
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
+ ED_undo_push(C, "Delete Library");
break;
}
case OL_LIB_RELOCATE:
{
/* rename */
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, lib_relocate_cb, NULL);
+ ED_undo_push(C, "Relocate Library");
break;
}
case OL_LIB_RELOAD:
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index ede6b7ce469..46f212e3679 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -38,6 +38,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
@@ -445,6 +447,7 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 8ae89941bdb..3ae4a233353 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -562,7 +562,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen
}
if (seq1 == NULL) seq1 = seq2;
if (seq3 == NULL) seq3 = seq2;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case 2:
if (seq1 == NULL || seq2 == NULL) {
*error_str = N_("2 selected sequence strips are needed");
@@ -3352,6 +3352,9 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
if (seq_act->sound) BKE_sound_add_scene_sound_defaults(scene, seq_act);
if (seq_other->sound) BKE_sound_add_scene_sound_defaults(scene, seq_other);
+ BKE_sequence_invalidate_cache(scene, seq_act);
+ BKE_sequence_invalidate_cache(scene, seq_other);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 48c49f36471..d88ed36e392 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -683,7 +683,7 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
if (!select_more_less_seq__internal(scene, false, false))
return OPERATOR_CANCELLED;
-
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index de85ddc40ab..39b48f5b52c 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -43,6 +43,8 @@ set(SRC
text_format.c
text_format_lua.c
text_format_osl.c
+ text_format_pov.c
+ text_format_pov_ini.c
text_format_py.c
text_header.c
text_ops.c
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 686a10fc785..fcb46ced750 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -158,7 +158,7 @@ static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
}
ED_area_tag_redraw(sa);
- /* fall-through */ /* fall down to tag redraw */
+ ATTR_FALLTHROUGH; /* fall down to tag redraw */
case NA_ADDED:
case NA_REMOVED:
ED_area_tag_redraw(sa);
@@ -636,5 +636,7 @@ void ED_spacetype_text(void)
ED_text_format_register_py();
ED_text_format_register_osl();
ED_text_format_register_lua();
+ ED_text_format_register_pov();
+ ED_text_format_register_pov_ini();
}
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index c38c57b9528..da5fa9da046 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -328,7 +328,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
if (tools & TOOL_SUGG_LIST) {
texttool_suggest_clear();
}
- if (tools & TOOL_DOCUMENT) {
+ if (tools & TOOL_DOCUMENT) {
texttool_docs_clear();
doc_scroll = 0;
}
@@ -455,7 +455,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
break;
case PAGEDOWNKEY:
scroll = SUGG_LIST_SIZE - 1;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case WHEELDOWNMOUSE:
case DOWNARROWKEY:
if (event->val == KM_PRESS) {
@@ -489,7 +489,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
break;
case PAGEUPKEY:
scroll = SUGG_LIST_SIZE - 1;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case WHEELUPMOUSE:
case UPARROWKEY:
if (event->val == KM_PRESS) {
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
index b901ec83a9c..d7cf31d0b41 100644
--- a/source/blender/editors/space_text/text_format.h
+++ b/source/blender/editors/space_text/text_format.h
@@ -102,6 +102,8 @@ void ED_text_format_register(TextFormatType *tft);
void ED_text_format_register_py(void);
void ED_text_format_register_osl(void);
void ED_text_format_register_lua(void);
+void ED_text_format_register_pov(void);
+void ED_text_format_register_pov_ini(void);
#define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \
(strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0)
diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c
new file mode 100644
index 00000000000..0d19c503798
--- /dev/null
+++ b/source/blender/editors/space_text/text_format_pov.c
@@ -0,0 +1,809 @@
+/*
+ * ***** 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_text/text_format_pov.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_text.h"
+
+#include "text_format.h"
+
+/* *** POV Keywords (for format_line) *** */
+
+/* Checks the specified source string for a POV keyword (minus boolean & 'nil').
+ * This name must start at the beginning of the source string and must be
+ * followed by a non-identifier (see text_check_identifier(char)) or null char.
+ *
+ * If a keyword is found, the length of the matching word is returned.
+ * Otherwise, -1 is returned.
+ *
+ * See:
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+
+static int txtfmt_pov_find_keyword(const char *string)
+{
+ int i, len;
+ /* Language Directives */
+ if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+static int txtfmt_pov_find_reserved_keywords(const char *string)
+{
+ int i, len;
+ /* POV-Ray Built-in Variables
+ * list is from...
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+ /* Language Keywords */
+ if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aa_threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "absorption", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "adc_bailout", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "albedo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "translucency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "all", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "alpha", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "altitude", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "always_sample", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ambient_light", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ambient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "arc_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "area_light", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "array", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "assumed_gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "autostop", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "black_hole", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brightness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brilliance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "caustics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "charset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "collect", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "component", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "composite", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "contained_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "coords", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "crand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cube", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "diffuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "direction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dispersion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dist_exp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "eccentricity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "emission", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error_bound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "evaluate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exponent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exterior", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "extinction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "face_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "falloff_angle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "falloff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "file_gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "flatness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "flip", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_alt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_offset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "form", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fresnel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gather", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "global_settings", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gray_threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hf_gray_16", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hierarchy", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hypercomplex", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "importance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside_vector", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "internal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intervals", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ior", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "irid_wavelength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "irid", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "load_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "location", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "looks_like", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "low_error_factor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "major_radius", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_gradient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_iteration", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_sample", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_trace_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max_trace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "maximum_reuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "metallic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "metric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "minimum_reuse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "nearest_count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "now", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "number_of_waves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "open", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orientation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pass_through", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phong_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phong", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "point_at", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pot", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "precompute", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pretrace_end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pretrace_start", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "prod", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pwr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quaternion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radiosity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radius", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ratio", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "reciprocal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "recursion_limit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "reflection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "refraction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "right", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "roughness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "samples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "save_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scattering", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sky", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "slice", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smooth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "solid", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spacing", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "specular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "split_union", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spotlight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strength", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sturm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sum", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "target", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture_list", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "thickness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tightness", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tolerance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "toroidal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ttf", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "turb_depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "u_steps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "up", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_alpha", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_indices", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "v_steps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "water_level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "width", len)) i = len;
+
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+
+static int txtfmt_pov_find_reserved_builtins(const char *string)
+{
+ int i, len;
+
+ /* POV-Ray Built-in Variables
+ * list is from...
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+ if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
+ /* Color Identifiers */
+ else if (STR_LITERAL_STARTSWITH(string, "blue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "filter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gray", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "green", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "red", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbf", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgbt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rgb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sRGB", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SRGB", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbf", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "srgbt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "transmit", len)) i = len;
+ /* Patterns */
+ else if (STR_LITERAL_STARTSWITH(string, "agate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "aoi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "average", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "boxed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bozo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brick", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bumps", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cells", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "checker", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "crackle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cylindrical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density_file", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dents", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "facets", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gradient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "granite", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hexagon", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "julia", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "leopard", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "magnet", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mandel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "marble", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "onion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pavement", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pigment_pattern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "planar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quilted", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radial", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ripples", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "slope", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spherical", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spiral1", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spiral2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spotted", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "square", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tile2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tiling", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tiles", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "waves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "wood", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "wrinkles", len)) i = len;
+ /* Objects */
+ else if (STR_LITERAL_STARTSWITH(string, "background", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bicubic_patch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "blob", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "box", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "camera", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cone", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cylinder", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "difference", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "disc", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fog", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "height_field", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "intersection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "isosurface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "julia_fractal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lathe", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "light_group", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "light_source", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "merge", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "object", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ovus", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lemon", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parametric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "plane", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "poly", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polygon", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "polynomial", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "prism", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quadric", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quartic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rainbow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sky_sphere", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "smooth_triangle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sphere_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sphere", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "superellipsoid", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "text", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "torus", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
+ /* Filetypes */
+ else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
+ /* Spline Identifiers */
+ else if (STR_LITERAL_STARTSWITH(string, "b_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bezier_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "conic_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "linear_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "linear_sweep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "natural_spline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quadratic_spline", len)) i = len;
+ /* Encodings */
+ else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
+ /* Camera Types */
+ else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len;
+ /* Built-in Vectors */
+ else if (STR_LITERAL_STARTSWITH(string, "t", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "u", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "v", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "x", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "y", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "z", len)) i = len;
+
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+
+/* Checks the specified source string for a POV modifiers. This
+ * name must start at the beginning of the source string and must be followed
+ * by a non-identifier (see text_check_identifier(char)) or null character.
+ *
+ * If a special name is found, the length of the matching name is returned.
+ * Otherwise, -1 is returned.
+ *
+ * See:
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+
+static int txtfmt_pov_find_specialvar(const char *string)
+{
+ int i, len;
+ /* Modifiers */
+ if (STR_LITERAL_STARTSWITH(string, "interior_texture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media_interaction", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media_attenuation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "noise_generator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "agate_turb", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bounded_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "brick_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bump_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bump_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "circular", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clipped_by", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "colour_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "control0", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "control1", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cubic_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "density", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_distance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frequency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "global_lights", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hollow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "adaptive", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interior", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "interpolate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inverse", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jitter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "map_type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "material_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "material", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "media", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mm_per_unit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mortar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_bump_scale", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_image", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_radiosity", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_reflection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no_shadow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "octaves", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "omega", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "once", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "orient", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "parallel", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "phase", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "photons", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pigment_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pigment", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "finish", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "poly_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quick_color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "quick_colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ramp_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scale", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "scallop_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "shadowless", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sine_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "slope_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "subsurface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture_map", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "texture", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "transform", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "translate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "triangle_wave", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "turbulence", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_colour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "use_index", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uv_mapping", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warp", len)) i = len;
+
+ /* Vector Functions */
+ else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "min_extent", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "trace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vaxis_rotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vcross", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vnormalize", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vrotate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vturbulence", len)) i = len;
+ /* String Functions */
+ else if (STR_LITERAL_STARTSWITH(string, "chr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "concat", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "datetime", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "str", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strlwr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strupr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "substr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vstr", len)) i = len;
+ /* Float Functions */
+ else if (STR_LITERAL_STARTSWITH(string, "abs", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "acosh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "acos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asc", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asinh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "asin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atan2", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atanh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "atan", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "bitwise_xor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ceil", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cosh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "cos", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "defined", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "degrees", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dimensions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "div", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "file_exists", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "floor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inside", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ln", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "log", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "max", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "min", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "mod", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pow", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "radians", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rand", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "seed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sinh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sin", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sqrt", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sqr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strcmp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "strlen", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tanh", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tan", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "val", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vdot", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vlength", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+static int txtfmt_pov_find_bool(const char *string)
+{
+ int i, len;
+ /*Built-in Constants*/
+ if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+static char txtfmt_pov_format_identifier(const char *str)
+{
+ char fmt;
+ if ((txtfmt_pov_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_pov_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else fmt = FMT_TYPE_DEFAULT;
+ return fmt;
+}
+
+static void txtfmt_pov_format_line(SpaceText *st, TextLine *line, const bool do_next)
+{
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev; fmt++; str++;
+ if (*str == '\0') break;
+ *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* C-Style comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == '*' && *(str + 1) == '/') {
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find) cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* C-Style (multi-line) comments */
+ if (*str == '/' && *(str + 1) == '*') {
+ cont = FMT_CONT_COMMENT_C;
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Single line comment */
+ else if (*str == '/' && *(str + 1) == '/') {
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1))))
+ {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_pov_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if (text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_pov_format_identifier()' */
+ if ((i = txtfmt_pov_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_pov_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_pov_find_reserved_keywords(str)) != -1) prev = FMT_TYPE_RESERVED;
+ else if ((i = txtfmt_pov_find_reserved_builtins(str)) != -1) prev = FMT_TYPE_RESERVED;
+
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt; fmt++; str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0'; fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_pov_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
+}
+
+void ED_text_format_register_pov(void)
+{
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"pov", "inc", "mcr", "mac", NULL};
+
+ tft.format_identifier = txtfmt_pov_format_identifier;
+ tft.format_line = txtfmt_pov_format_line;
+ tft.ext = ext;
+
+ ED_text_format_register(&tft);
+}
diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c
new file mode 100644
index 00000000000..719f4e3c036
--- /dev/null
+++ b/source/blender/editors/space_text/text_format_pov_ini.c
@@ -0,0 +1,488 @@
+/*
+ * ***** 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_text/text_format_pov_ini.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_text.h"
+
+#include "text_format.h"
+
+/* *** POV INI Keywords (for format_line) *** */
+
+/* Checks the specified source string for a POV INI keyword (minus boolean & 'nil').
+ * This name must start at the beginning of the source string and must be
+ * followed by a non-identifier (see text_check_identifier(char)) or null char.
+ *
+ * If a keyword is found, the length of the matching word is returned.
+ * Otherwise, -1 is returned.
+ *
+ * See:
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+
+static int txtfmt_ini_find_keyword(const char *string)
+{
+ int i, len;
+ /* Language Directives */
+ if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len;
+
+ else if (STR_LITERAL_STARTSWITH(string, "I", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "S", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "A", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Q", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "U", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "F", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "C", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "N", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "P", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "T", len)) i = len;
+
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+static int txtfmt_ini_find_reserved(const char *string)
+{
+ int i, len;
+ /* POV-Ray Built-in INI Variables
+ * list is from...
+ * http://www.povray.org/documentation/view/3.7.0/212/
+ */
+ if (STR_LITERAL_STARTSWITH(string, "Antialias_Threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bounding_Method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Subset_Start_Frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Subset_End_Frame", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Frame_Step", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Cyclic_Animation", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Field_Render", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Odd_Field", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Height", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Start_Column", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Start_Row", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "End_Column", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "End_Row", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Test_Abort_Count", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Test_Abort", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Continue_Trace", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Create_Ini", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Display_Gamma", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Display", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Version", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pause_When_Done", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Verbose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Preview_Start_Size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Preview_End_Size", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_to_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Input_File_Name", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_File_Name", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_File_Type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Output_Alpha", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bits_Per_Color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Compression", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Dither_Method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Dither", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Command", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Include_Header", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Library_Path", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Debug_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Render_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Statistic_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning_Level", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "All_Console", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Debug_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Fatal_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Render_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Statistic_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "All_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Quality", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bounding_Threshold", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Bounding", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Light_Buffer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Vista_Buffer", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Remove_Bounds", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Split_Unions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Sampling_Method", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Jitter_Amount", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Jitter", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "CheckNewVersion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RunCount", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "CommandLine", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "TextColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "WarningColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ErrorColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "BackgroundColour", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "DropToEditor", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastRenderName", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastRenderPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastQueuePath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SecondaryINISection", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "BetaVersionNo64", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastBitmapName", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastBitmapPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastINIPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SecondaryINIFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "BackgroundFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SaveSettingsOnExit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "TileBackground", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "HideNewUserHelp", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SendSystemInfo", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ItsAboutTime", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "LastPath", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band0Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band1Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band2Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band3Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Band4Width", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ShowCmd", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionLeft", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionTop", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionRight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionBottom", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseToolbar", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseTooltips", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionX", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NormalPositionY", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Flags", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Transparency", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Use8BitMode", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "MakeActive", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "KeepAboveMain", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "HideWhenMainMinimized", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AutoClose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "PreserveBitmap", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "FontSize", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "FontWeight", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Font", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "KeepMessages", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AlertSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Completion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Priority", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "DutyCycle", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AlertOnCompletion", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "AutoRender", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "PreventSleep", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NoShelloutWait", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SystemNoActive", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSound", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "UseExtensions", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ReadWriteSourceDir", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "NoShellOuts", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "VideoSource", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SceneFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "OutputFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "IniOutputFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "CurrentDirectory", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "SourceFile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Rendering", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "RenderwinClose", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Append_File", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "Warning Level", len)) i = len;
+ /* Filetypes */
+ else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len;
+ /* Encodings */
+ else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len;
+
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+
+
+
+static int txtfmt_ini_find_bool(const char *string)
+{
+ int i, len;
+ /* Built-in Constants */
+ if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%o", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%n", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%k", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%h", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "%w", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ return (i == 0 || text_check_identifier(string[i])) ? -1 : i;
+}
+
+static char txtfmt_pov_ini_format_identifier(const char *str)
+{
+ char fmt;
+ if ((txtfmt_ini_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_ini_find_reserved(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else fmt = FMT_TYPE_DEFAULT;
+ return fmt;
+}
+
+static void txtfmt_pov_ini_format_line(SpaceText *st, TextLine *line, const bool do_next)
+{
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev; fmt++; str++;
+ if (*str == '\0') break;
+ *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* Multi-line comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == ']' && *(str + 1) == ']') {
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find) cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Multi-line comments not supported */
+ /* Single line comment */
+ if (*str == ';') {
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1))))
+ {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_ini_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if ((*str != '#') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_ini_format_identifier()' */
+ if ((i = txtfmt_ini_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_ini_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED;
+
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt; fmt++; str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0'; fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_pov_ini_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
+}
+
+void ED_text_format_register_pov_ini(void)
+{
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"ini", NULL};
+
+ tft.format_identifier = txtfmt_pov_ini_format_identifier;
+ tft.format_line = txtfmt_pov_ini_format_line;
+ tft.ext = ext;
+
+ ED_text_format_register(&tft);
+}
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 149144d969a..314b7bf3335 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1265,7 +1265,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
else {
/* wire */
if (armflag & ARM_POSEMODE) {
- if (constflag) {
+ if (constflag && ((G.f & G_PICKSEL) == 0)) {
/* set constraint colors */
if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
glEnable(GL_BLEND);
@@ -1406,7 +1406,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
set_ebone_glColor(boneflag);
}
else if (armflag & ARM_POSEMODE) {
- if (constflag) {
+ if (constflag && ((G.f & G_PICKSEL) == 0)) {
/* draw constraint colors */
if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
glEnable(GL_BLEND);
@@ -2360,7 +2360,6 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* Draw name */
if (arm->flag & ARM_DRAWNAMES) {
mid_v3_v3v3(vec, eBone->head, eBone->tail);
- glRasterPos3fv(vec);
view3d_cached_text_draw_add(vec, eBone->name, strlen(eBone->name), 10, 0, col);
}
/* Draw additional axes */
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index be2e4ab05e0..884bc6b83ba 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -867,7 +867,7 @@ void view3d_cached_text_draw_add(const float co[3],
memcpy(vos->str, str, alloc_len);
}
-void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4])
+void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write)
{
RegionView3D *rv3d = ar->regiondata;
ViewCachedString *vos;
@@ -877,9 +877,6 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
/* project first and test */
for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
- if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE))
- mul_m4_v3(mat, vos->vec);
-
if (ED_view3d_project_short_ex(ar,
(vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
(vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
@@ -1824,16 +1821,16 @@ static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], con
glBegin(mode);
glVertex3fv(near_plane[2]);
- glVertex3fv(near_plane[1]);
- glVertex3fv(far_plane[1]);
glVertex3fv(far_plane[2]);
+ glVertex3fv(far_plane[3]);
+ glVertex3fv(near_plane[3]);
glEnd();
glBegin(mode);
- glVertex3fv(far_plane[0]);
- glVertex3fv(near_plane[0]);
- glVertex3fv(near_plane[3]);
glVertex3fv(far_plane[3]);
+ glVertex3fv(near_plane[3]);
+ glVertex3fv(near_plane[0]);
+ glVertex3fv(far_plane[0]);
glEnd();
}
@@ -4212,7 +4209,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (is_obact && BKE_paint_select_vert_test(ob)) {
const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0;
- glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
if (!use_depth) glDisable(GL_DEPTH_TEST);
@@ -5124,7 +5120,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
copy_m4_m4(imat, rv3d->viewinv);
normalize_v3(imat[0]);
normalize_v3(imat[1]);
- /* fall-through */
+ ATTR_FALLTHROUGH;
case PART_DRAW_CROSS:
case PART_DRAW_AXIS:
/* lets calculate the scale: */
@@ -6420,19 +6416,16 @@ static void draw_editnurb(
vec_a[0] = fac;
vec_a[1] = 0.0f;
vec_a[2] = 0.0f;
-
- vec_b[0] = -fac;
- vec_b[1] = 0.0f;
- vec_b[2] = 0.0f;
mul_qt_v3(bevp->quat, vec_a);
- mul_qt_v3(bevp->quat, vec_b);
+ madd_v3_v3fl(vec_a, bevp->dir, -fac);
+
+ reflect_v3_v3v3(vec_b, vec_a, bevp->dir);
+ negate_v3(vec_b);
+
add_v3_v3(vec_a, bevp->vec);
add_v3_v3(vec_b, bevp->vec);
- madd_v3_v3fl(vec_a, bevp->dir, -fac);
- madd_v3_v3fl(vec_b, bevp->dir, -fac);
-
glBegin(GL_LINE_STRIP);
glVertex3fv(vec_a);
glVertex3fv(bevp->vec);
@@ -6476,7 +6469,6 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
Curve *cu = ob->data;
EditFont *ef = cu->editfont;
float vec1[3], vec2[3];
- int selstart, selend;
draw_editfont_textcurs(rv3d, ef->textcurs);
@@ -6529,17 +6521,16 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
setlinestyle(0);
- if (BKE_vfont_select_get(ob, &selstart, &selend) && ef->selboxes) {
- const int seltot = selend - selstart;
+ if (ef->selboxes && ef->selboxes_len) {
float selboxw;
cpack(0xffffff);
set_inverted_drawing(1);
- for (int i = 0; i <= seltot; i++) {
+ for (int i = 0; i < ef->selboxes_len; i++) {
EditFontSelBox *sb = &ef->selboxes[i];
float tvec[3];
- if (i != seltot) {
+ if (i + 1 != ef->selboxes_len) {
if (ef->selboxes[i + 1].y == sb->y)
selboxw = ef->selboxes[i + 1].x - sb->x;
else
@@ -7832,7 +7823,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag);
}
invert_m4_m4(ob->imat, ob->obmat);
- view3d_cached_text_draw_end(v3d, ar, 0, NULL);
+ view3d_cached_text_draw_end(v3d, ar, 0);
glMultMatrixf(ob->obmat);
@@ -8007,7 +7998,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* return warning, this is cached text draw */
invert_m4_m4(ob->imat, ob->obmat);
- view3d_cached_text_draw_end(v3d, ar, 1, NULL);
+ view3d_cached_text_draw_end(v3d, ar, 1);
/* return warning, clear temp flag */
v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP;
@@ -8446,8 +8437,8 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
bbs_mesh_wire(em, dm, bm_solidoffs);
bm_wireoffs = bm_solidoffs + em->bm->totedge;
- /* we draw verts if vert select mode or if in transform (for snap). */
- if ((ts->selectmode & SCE_SELECT_VERTEX) || (G.moving & G_TRANSFORM_EDIT)) {
+ /* we draw verts if vert select mode. */
+ if (ts->selectmode & SCE_SELECT_VERTEX) {
bbs_mesh_verts(em, dm, bm_wireoffs);
bm_vertoffs = bm_wireoffs + em->bm->totvert;
}
diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c
index 9414d39467d..3f23d4aa09a 100644
--- a/source/blender/editors/space_view3d/drawsimdebug.c
+++ b/source/blender/editors/space_view3d/drawsimdebug.c
@@ -171,7 +171,7 @@ void draw_sim_debug_data(Scene *UNUSED(scene), View3D *v3d, ARegion *ar)
view3d_cached_text_draw_begin();
draw_sim_debug_elements(_sim_debug_data, imat);
- view3d_cached_text_draw_end(v3d, ar, false, NULL);
+ view3d_cached_text_draw_end(v3d, ar, false);
glPopMatrix();
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 351c7ccec15..34e01405e7e 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -814,10 +814,6 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
if (dv && dv->totweight) {
ToolSettings *ts = scene->toolsettings;
- wmOperatorType *ot_weight_set_active = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
- wmOperatorType *ot_weight_paste = WM_operatortype_find("OBJECT_OT_vertex_weight_paste", true);
- wmOperatorType *ot_weight_delete = WM_operatortype_find("OBJECT_OT_vertex_weight_delete", true);
-
wmOperatorType *ot;
PointerRNA op_ptr, tools_ptr;
PointerRNA *but_ptr;
@@ -856,7 +852,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
/* The Weight Group Name */
- ot = ot_weight_set_active;
+ ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, dg->name,
xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, "");
but_ptr = UI_but_operator_ptr_get(but);
@@ -882,23 +878,16 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
xco += x;
/* The weight group paste function */
-
- ot = ot_weight_paste;
- WM_operator_properties_create_ptr(&op_ptr, ot);
- RNA_int_set(&op_ptr, "weight_group", i);
icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN;
- uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
+ op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_paste", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_int_set(&op_ptr, "weight_group", i);
/* The weight entry delete function */
-
- ot = ot_weight_delete;
- WM_operator_properties_create_ptr(&op_ptr, ot);
- RNA_int_set(&op_ptr, "weight_group", i);
icon = (locked) ? ICON_LOCKED : ICON_X;
- uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
+ op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_delete", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_int_set(&op_ptr, "weight_group", i);
yco -= UI_UNIT_Y;
-
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 3fb2761d40e..250e6559b8f 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -105,7 +105,8 @@
#include "view3d_intern.h" /* own include */
/* prototypes */
-static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar);
+static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d);
+static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect);
static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
float winmat[4][4], const char *viewname);
@@ -2371,17 +2372,11 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
short zbuf = v3d->zbuf;
RegionView3D *rv3d = ar->regiondata;
- view3d_winmatrix_set(ar, v3d, NULL);
- view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(rv3d->persinv, rv3d->persmat);
- invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+ /* Setup view matrix. */
+ ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL);
glClear(GL_DEPTH_BUFFER_BIT);
- glLoadMatrixf(rv3d->viewmat);
-
v3d->zbuf = true;
glEnable(GL_DEPTH_TEST);
@@ -2390,46 +2385,15 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
}
v3d->zbuf = zbuf;
-
}
-void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
+static void view3d_draw_depth_loop(Scene *scene, ARegion *ar, View3D *v3d)
{
- RegionView3D *rv3d = ar->regiondata;
Base *base;
- short zbuf = v3d->zbuf;
- short flag = v3d->flag;
- float glalphaclip = U.glalphaclip;
- int obcenter_dia = U.obcenter_dia;
+
/* no need for color when drawing depth buffer */
const short dflag_depth = DRAW_CONSTCOLOR;
- /* temp set drawtype to solid */
-
- /* Setting these temporarily is not nice */
- v3d->flag &= ~V3D_SELECT_OUTLINE;
- U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
- U.obcenter_dia = 0;
-
- view3d_winmatrix_set(ar, v3d, NULL);
- view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(rv3d->persinv, rv3d->persmat);
- invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
-
- glClear(GL_DEPTH_BUFFER_BIT);
-
- glLoadMatrixf(rv3d->viewmat);
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
- }
- /* get surface depth without bias */
- rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
- v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
-
/* draw set first */
if (scene->set) {
Scene *sce_iter;
@@ -2503,8 +2467,39 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
glDepthMask(mask_orig);
}
+}
+
+void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ short zbuf = v3d->zbuf;
+ short flag = v3d->flag;
+ float glalphaclip = U.glalphaclip;
+ int obcenter_dia = U.obcenter_dia;
+ /* temp set drawtype to solid */
+
+ /* Setting these temporarily is not nice */
+ v3d->flag &= ~V3D_SELECT_OUTLINE;
+ U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
+ U.obcenter_dia = 0;
+
+ /* Setup view matrix. */
+ ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(rv3d);
+ }
+ /* get surface depth without bias */
+ rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
+
+ v3d->zbuf = true;
+ glEnable(GL_DEPTH_TEST);
+
+ view3d_draw_depth_loop(scene, ar, v3d);
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
}
rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
@@ -2737,7 +2732,8 @@ CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
/**
* \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
*/
-void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
+void ED_view3d_update_viewmat(
+ Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
@@ -2745,7 +2741,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
if (winmat)
copy_m4_m4(rv3d->winmat, winmat);
else
- view3d_winmatrix_set(ar, v3d, NULL);
+ view3d_winmatrix_set(ar, v3d, rect);
/* setup view matrix */
if (viewmat)
@@ -3008,11 +3004,12 @@ static void view3d_draw_objects(
}
}
-static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
+static void view3d_main_region_setup_view(
+ Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
- ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
+ ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat, rect);
/* set for opengl */
glMatrixMode(GL_PROJECTION);
@@ -3195,7 +3192,7 @@ void ED_view3d_draw_offscreen(
if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
else
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
/* framebuffer fx needed, we need to draw offscreen first */
if (v3d->fx_settings.fx_flag && fx) {
@@ -3258,6 +3255,23 @@ void ED_view3d_draw_offscreen(
}
/**
+ * Set the correct matrices
+ */
+void ED_view3d_draw_setup_view(
+ wmWindow *win, Scene *scene, ARegion *ar, View3D *v3d, float viewmat[4][4], float winmat[4][4], const rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* Setup the view matrix. */
+ if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
+ view3d_stereo3d_setup(scene, v3d, ar, rect);
+ }
+ else {
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, rect);
+ }
+}
+
+/**
* Utility func for ED_view3d_draw_offscreen
*
* \param ofs: Optional off-screen buffer, can be NULL.
@@ -3624,7 +3638,7 @@ static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
}
/* setup view matrices */
- view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
+ view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL, NULL);
/* background draw */
ED_region_pixelspace(ar);
@@ -3691,26 +3705,37 @@ static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d,
ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
}
-static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
+static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
- wmWindow *win = CTX_wm_window(C);
-
- if ((scene->r.scemode & R_MULTIVIEW) == 0)
- return false;
-
- if (WM_stereo3d_enabled(win, true) == false)
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
return false;
+ }
- if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB)
+ if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) {
return false;
+ }
- if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) {
- if (v3d->stereo3d_camera == STEREO_MONO_ID)
+ switch (v3d->stereo3d_camera) {
+ case STEREO_MONO_ID:
return false;
-
- return BKE_scene_multiview_is_stereo3d(&scene->r);
+ break;
+ case STEREO_3D_ID:
+ /* win will be NULL when calling this from the selection or draw loop. */
+ if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) {
+ return false;
+ }
+ if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) &&
+ !BKE_scene_multiview_is_stereo3d(&scene->r))
+ {
+ return false;
+ }
+ break;
+ /* We always need the stereo calculation for left and right cameras. */
+ case STEREO_LEFT_ID:
+ case STEREO_RIGHT_ID:
+ default:
+ break;
}
-
return true;
}
@@ -3722,7 +3747,7 @@ static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d,
* we do a small hack to replace it temporarily so we don't need to change the
* view3d)main_region_setup_view() code to account for that.
*/
-static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
+static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect)
{
bool is_left;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
@@ -3748,7 +3773,7 @@ static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect);
data->shiftx = shiftx;
BLI_unlock_thread(LOCK_VIEW3D);
@@ -3762,7 +3787,7 @@ static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
v3d->camera = camera;
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect);
v3d->camera = view_ob;
BLI_unlock_thread(LOCK_VIEW3D);
@@ -3778,14 +3803,14 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *
const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
}
else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
float viewmat[4][4];
Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
}
}
@@ -3823,11 +3848,8 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie
GPU_default_lights();
}
- /* setup the view matrix */
- if (view3d_stereo3d_active(C, scene, v3d, rv3d))
- view3d_stereo3d_setup(scene, v3d, ar);
- else
- view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
+ /* Setup the view matrix. */
+ ED_view3d_draw_setup_view(CTX_wm_window(C), scene, ar, v3d, NULL, NULL, NULL);
rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
#ifdef WITH_GAMEENGINE
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index f07727f8118..4e3f279e12e 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -85,6 +85,8 @@
#include "view3d_intern.h" /* own include */
+static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar);
+
bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
{
return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
@@ -697,16 +699,68 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
return is_set;
}
+enum eViewOpsOrbit {
+ VIEWOPS_ORBIT_SELECT = (1 << 0),
+ VIEWOPS_ORBIT_DEPTH = (1 << 1),
+};
+
+static enum eViewOpsOrbit viewops_orbit_mode_ex(bool use_select, bool use_depth)
+{
+ enum eViewOpsOrbit flag = 0;
+ if (use_select) {
+ flag |= VIEWOPS_ORBIT_SELECT;
+ }
+ if (use_depth) {
+ flag |= VIEWOPS_ORBIT_DEPTH;
+ }
+
+ return flag;
+}
+
+static enum eViewOpsOrbit viewops_orbit_mode(void)
+{
+ return viewops_orbit_mode_ex(
+ (U.uiflag & USER_ORBIT_SELECTION) != 0,
+ (U.uiflag & USER_ZBUF_ORBIT) != 0);
+}
+
/**
* Calculate the values for #ViewOpsData
*/
-static void viewops_data_create_ex(bContext *C, wmOperator *op, const wmEvent *event,
- const bool use_orbit_select,
- const bool use_orbit_zbuf)
+static void viewops_data_create_ex(
+ bContext *C, wmOperator *op, const wmEvent *event,
+ bool switch_from_camera, enum eViewOpsOrbit orbit_mode)
{
ViewOpsData *vod = op->customdata;
RegionView3D *rv3d = vod->rv3d;
+ /* we need the depth info before changing any viewport options */
+ if (orbit_mode & VIEWOPS_ORBIT_DEPTH) {
+ float fallback_depth_pt[3];
+
+ view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
+
+ negate_v3_v3(fallback_depth_pt, rv3d->ofs);
+
+ vod->use_dyn_ofs = ED_view3d_autodist(
+ vod->scene, vod->ar, vod->v3d,
+ event->mval, vod->dyn_ofs, true, fallback_depth_pt);
+ }
+ else {
+ vod->use_dyn_ofs = false;
+ }
+
+ if (switch_from_camera) {
+ /* switch from camera view when: */
+ if (view3d_ensure_persp(vod->v3d, vod->ar)) {
+ /* If we're switching from camera view to the perspective one,
+ * need to tag viewport update, so camera vuew and borders
+ * are properly updated.
+ */
+ ED_region_tag_redraw(vod->ar);
+ }
+ }
+
/* set the view from the camera, if view locking is enabled.
* we may want to make this optional but for now its needed always */
ED_view3d_camera_lock_init(vod->v3d, vod->rv3d);
@@ -718,28 +772,19 @@ static void viewops_data_create_ex(bContext *C, wmOperator *op, const wmEvent *e
vod->origx = vod->oldx = event->x;
vod->origy = vod->oldy = event->y;
vod->origkey = event->type; /* the key that triggered the operator. */
- vod->use_dyn_ofs = false;
copy_v3_v3(vod->ofs, rv3d->ofs);
- if (use_orbit_select) {
-
- vod->use_dyn_ofs = true;
-
- view3d_orbit_calc_center(C, vod->dyn_ofs);
-
- negate_v3(vod->dyn_ofs);
+ if (orbit_mode & VIEWOPS_ORBIT_SELECT) {
+ float ofs[3];
+ if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
+ vod->use_dyn_ofs = true;
+ negate_v3_v3(vod->dyn_ofs, ofs);
+ orbit_mode &= ~VIEWOPS_ORBIT_DEPTH;
+ }
}
- else if (use_orbit_zbuf) {
- Scene *scene = CTX_data_scene(C);
- float fallback_depth_pt[3];
-
- view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
-
- 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 (orbit_mode & VIEWOPS_ORBIT_DEPTH) {
+ if (vod->use_dyn_ofs) {
if (rv3d->is_persp) {
float my_origin[3]; /* original G.vd->ofs */
float my_pivot[3]; /* view */
@@ -808,12 +853,10 @@ static void viewops_data_create_ex(bContext *C, wmOperator *op, const wmEvent *e
rv3d->rflag |= RV3D_NAVIGATING;
}
-static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event)
+static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event, bool switch_from_camera)
{
- viewops_data_create_ex(
- C, op, event,
- (U.uiflag & USER_ORBIT_SELECTION) != 0,
- (U.uiflag & USER_ZBUF_ORBIT) != 0);
+ enum eViewOpsOrbit orbit_mode = viewops_orbit_mode();
+ viewops_data_create_ex(C, op, event, switch_from_camera, orbit_mode);
}
static void viewops_data_free(bContext *C, wmOperator *op)
@@ -1219,16 +1262,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
- /* switch from camera view when: */
- if (view3d_ensure_persp(vod->v3d, vod->ar)) {
- /* If we're switching from camera view to the perspective one,
- * need to tag viewport update, so camera vuew and borders
- * are properly updated.
- */
- ED_region_tag_redraw(vod->ar);
- }
-
- viewops_data_create(C, op, event);
+ viewops_data_create(C, op, event, true);
if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
/* Rotate direction we keep always same */
@@ -1637,8 +1671,9 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
- viewops_data_create_ex(C, op, event,
- (U.uiflag & USER_ORBIT_SELECTION) != 0, false);
+ viewops_data_create_ex(
+ C, op, event,
+ viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false), false);
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -1705,8 +1740,9 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
- viewops_data_create_ex(C, op, event,
- (U.uiflag & USER_ORBIT_SELECTION) != 0, false);
+ viewops_data_create_ex(
+ C, op, event,
+ viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false), false);
vod = op->customdata;
@@ -2020,7 +2056,7 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event);
+ viewops_data_create(C, op, event, false);
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -2501,7 +2537,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event);
+ viewops_data_create(C, op, event, false);
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -2774,7 +2810,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->ar);
}
- viewops_data_create(C, op, event);
+ viewops_data_create(C, op, event, false);
/* if one or the other zoom position aren't set, set from event */
@@ -4298,7 +4334,7 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else {
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event);
+ viewops_data_create(C, op, event, false);
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -4375,7 +4411,7 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else if (pandir == V3D_VIEW_PANDOWN) { y = 25; }
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event);
+ viewops_data_create(C, op, event, false);
ViewOpsData *vod = op->customdata;
viewmove_apply(vod, vod->oldx + x, vod->oldy + y);
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index c2b8d1f8bda..7a106a27833 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -154,7 +154,7 @@ void view3d_cached_text_draw_begin(void);
void view3d_cached_text_draw_add(const float co[3],
const char *str, const size_t str_len,
short xoffs, short flag, const unsigned char col[4]);
-void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4]);
+void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write);
bool check_object_draw_texture(struct Scene *scene, struct View3D *v3d, const char drawtype);
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index ce4b7f7deeb..ef7b01f7a21 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -119,7 +119,7 @@ void meshobject_foreachScreenVert(
data.clip_flag = clip_flag;
if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
- ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat);
}
dm->foreachMappedVert(dm, meshobject_foreachScreenVert__mapFunc, &data, DM_FOREACH_NOP);
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 8230a0de6b9..5c13fd37dda 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -449,7 +449,7 @@ void ED_view3d_smooth_view_force_finish(
/* force update of view matrix so tools that run immediately after
* can use them without redrawing first */
Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL);
+ ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL, NULL);
}
}
@@ -1172,9 +1172,10 @@ int view3d_opengl_select(
G.f |= G_PICKSEL;
- view3d_winmatrix_set(ar, v3d, &rect);
- mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
-
+ /* Important we use the 'viewmat' and don't re-calculate since
+ * the object & bone view locking takes 'rect' into account, see: T51629. */
+ ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
+
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = true;
glEnable(GL_DEPTH_TEST);
@@ -1190,7 +1191,7 @@ int view3d_opengl_select(
hits = GPU_select_end();
/* second pass, to get the closest object to camera */
- if (do_passes) {
+ if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);
@@ -1199,8 +1200,7 @@ int view3d_opengl_select(
}
G.f &= ~G_PICKSEL;
- view3d_winmatrix_set(ar, v3d, NULL);
- mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
+ ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = 0;
@@ -1405,6 +1405,8 @@ static bool view3d_localview_init(
}
}
+ DAG_on_visible_update(bmain, false);
+
return ok;
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 7d9063c3285..4686ff0523e 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1605,7 +1605,7 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size)
offset = -offset;
length = -length;
size = -size;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case RIGHT:
glBegin(GL_LINES);
glVertex2s(offset, 0);
@@ -1621,7 +1621,7 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size)
offset = -offset;
length = -length;
size = -size;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case UP:
glBegin(GL_LINES);
glVertex2s(0, offset);
@@ -1640,7 +1640,7 @@ static void drawArrowHead(ArrowDirection d, short size)
switch (d) {
case LEFT:
size = -size;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case RIGHT:
glBegin(GL_LINES);
glVertex2s(0, 0);
@@ -1652,7 +1652,7 @@ static void drawArrowHead(ArrowDirection d, short size)
case DOWN:
size = -size;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case UP:
glBegin(GL_LINES);
glVertex2s(0, 0);
@@ -3051,19 +3051,13 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
/** \name Transform Shear
* \{ */
-static void postInputShear(TransInfo *UNUSED(t), float values[3])
-{
- mul_v3_fl(values, 0.05f);
-}
-
static void initShear(TransInfo *t)
{
t->mode = TFM_SHEAR;
t->transform = applyShear;
t->handleEvent = handleEventShear;
-
- setInputPostFct(&t->mouse, postInputShear);
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
t->idx_max = 0;
t->num.idx_max = 0;
@@ -3085,24 +3079,24 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event)
if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
/* Use custom.mode.data pointer to signal Shear direction */
if (t->custom.mode.data == NULL) {
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO);
t->custom.mode.data = (void *)1;
}
else {
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
t->custom.mode.data = NULL;
}
status = TREDRAW_HARD;
}
else if (event->type == XKEY && event->val == KM_PRESS) {
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
t->custom.mode.data = NULL;
status = TREDRAW_HARD;
}
else if (event->type == YKEY && event->val == KM_PRESS) {
- initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO);
t->custom.mode.data = (void *)1;
status = TREDRAW_HARD;
@@ -4278,7 +4272,7 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system,
B_UNIT_LENGTH, do_split, false);
}
- else if (dist > 1e10f || dist < -1e10f) {
+ else if (dist > 1e10f || dist < -1e10f) {
/* prevent string buffer overflow */
BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist);
}
@@ -4948,7 +4942,7 @@ static void initPushPull(TransInfo *t)
static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
{
- float vec[3], axis[3];
+ float vec[3], axis_global[3];
float distance;
int i;
char str[UI_MAX_DRAW_STR];
@@ -4976,7 +4970,7 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
}
if (t->con.applyRot && t->con.mode & CON_APPLY) {
- t->con.applyRot(t, NULL, axis, NULL);
+ t->con.applyRot(t, NULL, axis_global, NULL);
}
for (i = 0; i < t->total; i++, td++) {
@@ -4988,7 +4982,11 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
sub_v3_v3v3(vec, t->center, td->center);
if (t->con.applyRot && t->con.mode & CON_APPLY) {
+ float axis[3];
+ copy_v3_v3(axis, axis_global);
t->con.applyRot(t, td, axis, NULL);
+
+ mul_m3_v3(td->smtx, axis);
if (isLockConstraint(t)) {
float dvec[3];
project_v3_v3v3(dvec, vec, axis);
@@ -5561,7 +5559,7 @@ static void slide_origdata_interp_data_vert(
float v_proj[3][3];
if (do_loop_weight || do_loop_mdisps) {
- project_plane_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis);
}
// BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
@@ -5595,19 +5593,19 @@ static void slide_origdata_interp_data_vert(
/* In the unlikely case that we're next to a zero length edge - walk around the to the next.
* Since we only need to check if the vertex is in this corner,
* its not important _which_ loop - as long as its not overlapping 'sv->co_orig_3d', see: T45096. */
- project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) &&
((l_prev = l_prev->prev) != l->next)))
{
co_prev = slide_origdata_orig_vert_co(sod, l_prev->v);
- project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis);
}
- project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) &&
((l_next = l_next->next) != l->prev)))
{
co_next = slide_origdata_orig_vert_co(sod, l_next->v);
- project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis);
+ project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis);
}
if (co_prev_ok && co_next_ok) {
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 5e67f304755..ba474e93b70 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -828,7 +828,9 @@ static void pose_grab_with_ik_clear(Object *ob)
bKinematicConstraint *data;
bPoseChannel *pchan;
bConstraint *con, *next;
+#ifdef WITH_LEGACY_DEPSGRAPH
bool need_dependency_update = false;
+#endif
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
/* clear all temporary lock flags */
@@ -843,7 +845,9 @@ static void pose_grab_with_ik_clear(Object *ob)
data = con->data;
if (data->flag & CONSTRAINT_IK_TEMP) {
/* iTaSC needs clear for removed constraints */
+#ifdef WITH_LEGACY_DEPSGRAPH
need_dependency_update = true;
+#endif
BIK_clear_data(ob->pose);
BLI_remlink(&pchan->constraints, con);
@@ -2004,9 +2008,9 @@ static bool bmesh_test_dist_add(
}
/**
- * \parm mtx: Measure disatnce in this space.
- * \parm dists: Store the closest connected distance to selected vertices.
- * \parm index: Optionally store the original index we're measuring the distance to (can be NULL).
+ * \param mtx: Measure disatnce in this space.
+ * \param dists: Store the closest connected distance to selected vertices.
+ * \param index: Optionally store the original index we're measuring the distance to (can be NULL).
*/
static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index)
{
@@ -2276,7 +2280,7 @@ static struct TransIslandData *editmesh_islands_info_calc(
}
if (group_tot_single != 0) {
- trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single);
+ trans_islands = MEM_reallocN(trans_islands, sizeof(*trans_islands) * (group_tot + group_tot_single));
BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
@@ -2398,7 +2402,8 @@ static void createTransEditVerts(TransInfo *t)
int island_info_tot;
int *island_vert_map = NULL;
- const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION);
+ /* Even for translation this is needed because of island-orientation, see: T51651. */
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
/* Original index of our connected vertex when connected distances are calculated.
* Optional, allocate if needed. */
int *dists_index = NULL;
@@ -2464,11 +2469,6 @@ static void createTransEditVerts(TransInfo *t)
editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
}
- /* Only in case of rotation and resize, we want the elements of the edited
- * object to behave as groups whose pivot are the individual origins
- *
- * TODO: use island_info to detect the closest point when the "Snap Target"
- * in Blender UI is "Closest" */
if (is_island_center) {
/* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
const bool calc_single_islands = (
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index f78a23be7b8..c23da19f830 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -971,7 +971,7 @@ static void recalcData_sequencer(TransInfo *t)
/* force recalculation of triangles during transformation */
static void recalcData_gpencil_strokes(TransInfo *t)
- {
+{
TransData *td = t->data;
for (int i = 0; i < t->total; i++, td++) {
bGPDstroke *gps = td->extra;
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 42cc918ec8c..5f2e5a99090 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -86,12 +86,11 @@ static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mv
output[1] *= mi->factor;
}
-static void InputHorizontalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
+static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
const int winx = t->ar ? t->ar->winx : 1;
- const double pad = winx / 10;
- output[0] = (mval[0] - pad) / (winx - 2 * pad);
+ output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f;
}
static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
@@ -104,12 +103,11 @@ static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double m
output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f;
}
-static void InputVerticalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3])
+static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
{
const int winy = t->ar ? t->ar->winy : 1;
- const double pad = winy / 10;
- output[0] = (mval[1] - pad) / (winy - 2 * pad);
+ output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f;
}
static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3])
@@ -187,7 +185,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2
/* use doubles here, to make sure a "1.0" (no rotation) doesn't become 9.999999e-01, which gives 0.02 for acos */
double deler = (((dx1 * dx1 + dy1 * dy1) +
(dx2 * dx2 + dy2 * dy2) -
- (dx3 * dx3 + dy3 * dy3)) / (2.0 * ((A * B) ? (A * B) : 1.0)));
+ (dx3 * dx3 + dy3 * dy3)) / (2.0 * (((A * B) != 0.0) ? (A * B) : 1.0)));
/* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */
float dphi;
@@ -314,7 +312,6 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
t->helpline = HLP_TRACKBALL;
break;
case INPUT_HORIZONTAL_RATIO:
- mi->factor = (float)(mi->center[0] - mi->imval[0]);
mi->apply = InputHorizontalRatio;
t->helpline = HLP_HARROW;
break;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 0a984d90ae3..ec066ba91a4 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -143,21 +143,17 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags)
}
/* for pose mode */
-static void stats_pose(Scene *scene, RegionView3D *rv3d, bPoseChannel *pchan)
+static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, const bPoseChannel *pchan)
{
- Bone *bone = pchan->bone;
-
- if (bone) {
- calc_tw_center(scene, pchan->pose_head);
- protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
- }
+ protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
}
/* for editmode*/
-static void stats_editbone(RegionView3D *rv3d, EditBone *ebo)
+static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *ebo)
{
- if (ebo->flag & BONE_EDITMODE_LOCKED)
+ if (ebo->flag & BONE_EDITMODE_LOCKED) {
protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE, &rv3d->twdrawflag);
+ }
}
/* could move into BLI_math however this is only useful for display/editing purposes */
@@ -192,73 +188,71 @@ static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], con
}
-static int test_rotmode_euler(short rotmode)
+static bool test_rotmode_euler(short rotmode)
{
return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0 : 1;
}
bool gimbal_axis(Object *ob, float gmat[3][3])
{
- if (ob) {
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
-
- if (pchan) {
- float mat[3][3], tmat[3][3], obmat[3][3];
- if (test_rotmode_euler(pchan->rotmode)) {
- eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
- }
- else { /* quat */
- return 0;
- }
-
-
- /* apply bone transformation */
- mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
-
- if (pchan->parent) {
- float parent_mat[3][3];
+ if (ob->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
- copy_m3_m4(parent_mat, pchan->parent->pose_mat);
- mul_m3_m3m3(mat, parent_mat, tmat);
-
- /* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
- mul_m3_m3m3(gmat, obmat, mat);
- }
- else {
- /* needed if object transformation isn't identity */
- copy_m3_m4(obmat, ob->obmat);
- mul_m3_m3m3(gmat, obmat, tmat);
- }
-
- normalize_m3(gmat);
- return 1;
- }
- }
- else {
- if (test_rotmode_euler(ob->rotmode)) {
- eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
+ if (pchan) {
+ float mat[3][3], tmat[3][3], obmat[3][3];
+ if (test_rotmode_euler(pchan->rotmode)) {
+ eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode);
}
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle);
}
else { /* quat */
return 0;
}
- if (ob->parent) {
+
+ /* apply bone transformation */
+ mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat);
+
+ if (pchan->parent) {
float parent_mat[3][3];
- copy_m3_m4(parent_mat, ob->parent->obmat);
- normalize_m3(parent_mat);
- mul_m3_m3m3(gmat, parent_mat, gmat);
+
+ copy_m3_m4(parent_mat, pchan->parent->pose_mat);
+ mul_m3_m3m3(mat, parent_mat, tmat);
+
+ /* needed if object transformation isn't identity */
+ copy_m3_m4(obmat, ob->obmat);
+ mul_m3_m3m3(gmat, obmat, mat);
}
+ else {
+ /* needed if object transformation isn't identity */
+ copy_m3_m4(obmat, ob->obmat);
+ mul_m3_m3m3(gmat, obmat, tmat);
+ }
+
+ normalize_m3(gmat);
return 1;
}
}
+ else {
+ if (test_rotmode_euler(ob->rotmode)) {
+ eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle);
+ }
+ else { /* quat */
+ return 0;
+ }
+
+ if (ob->parent) {
+ float parent_mat[3][3];
+ copy_m3_m4(parent_mat, ob->parent->obmat);
+ normalize_m3(parent_mat);
+ mul_m3_m3m3(gmat, parent_mat, gmat);
+ }
+ return 1;
+ }
return 0;
}
@@ -385,7 +379,7 @@ static int calc_manipulator_stats(const bContext *C)
calc_tw_center(scene, ebo->head);
totsel++;
}
- stats_editbone(rv3d, ebo);
+ protectflag_to_drawflags_ebone(rv3d, ebo);
}
else {
for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
@@ -405,7 +399,7 @@ static int calc_manipulator_stats(const bContext *C)
totsel++;
}
if (ebo->flag & BONE_SELECTED) {
- stats_editbone(rv3d, ebo);
+ protectflag_to_drawflags_ebone(rv3d, ebo);
}
}
}
@@ -530,7 +524,8 @@ static int calc_manipulator_stats(const bContext *C)
/* doesn't check selection or visibility intentionally */
Bone *bone = pchan->bone;
if (bone) {
- stats_pose(scene, rv3d, pchan);
+ calc_tw_center(scene, pchan->pose_head);
+ protectflag_to_drawflags_pchan(rv3d, pchan);
totsel = 1;
ok = true;
}
@@ -543,7 +538,8 @@ static int calc_manipulator_stats(const bContext *C)
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
Bone *bone = pchan->bone;
if (bone && (bone->flag & BONE_TRANSFORM)) {
- stats_pose(scene, rv3d, pchan);
+ calc_tw_center(scene, pchan->pose_head);
+ protectflag_to_drawflags_pchan(rv3d, pchan);
}
}
ok = true;
@@ -623,7 +619,7 @@ static int calc_manipulator_stats(const bContext *C)
break;
}
/* if not gimbal, fall through to normal */
- /* fall-through */
+ ATTR_FALLTHROUGH;
}
case V3D_MANIP_NORMAL:
{
@@ -634,7 +630,7 @@ static int calc_manipulator_stats(const bContext *C)
break;
}
/* no break we define 'normal' as 'local' in Object mode */
- /* fall-through */
+ ATTR_FALLTHROUGH;
}
case V3D_MANIP_LOCAL:
{
@@ -1720,7 +1716,7 @@ void BIF_draw_manipulator(const bContext *C)
}
}
-static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], float hotspot)
+static int manipulator_selectbuf(Scene *scene, ScrArea *sa, ARegion *ar, const int mval[2], float hotspot)
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
@@ -1730,9 +1726,6 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
const bool is_picksel = true;
const bool do_passes = GPU_select_query_check_active();
- /* XXX check a bit later on this... (ton) */
- extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rcti *rect);
-
/* when looking through a selected camera, the manipulator can be at the
* exact same position as the view, skip so we don't break selection */
if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f)
@@ -1743,8 +1736,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
rect.ymin = mval[1] - hotspot;
rect.ymax = mval[1] + hotspot;
- view3d_winmatrix_set(ar, v3d, &rect);
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+ ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, &rect);
if (do_passes)
GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
@@ -1763,7 +1755,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
hits = GPU_select_end();
- if (do_passes) {
+ if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
/* do the drawing */
@@ -1779,8 +1771,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
GPU_select_end();
}
- view3d_winmatrix_set(ar, v3d, NULL);
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+ ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, NULL);
if (hits == 1) return buffer[3];
else if (hits > 1) {
@@ -1845,6 +1836,7 @@ static const char *manipulator_get_operator_name(int man_val)
/* return 0; nothing happened */
int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
{
+ Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
ARegion *ar = CTX_wm_region(C);
@@ -1859,7 +1851,7 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode);
// find the hotspots first test narrow hotspot
- val = manipulator_selectbuf(sa, ar, event->mval, 0.5f * (float)U.tw_hotspot);
+ val = manipulator_selectbuf(scene, sa, ar, event->mval, 0.5f * (float)U.tw_hotspot);
if (val) {
wmOperatorType *ot;
PointerRNA props_ptr;
@@ -1867,7 +1859,7 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
const char *opname;
// drawflags still global, for drawing call above
- drawflags = manipulator_selectbuf(sa, ar, event->mval, 0.2f * (float)U.tw_hotspot);
+ drawflags = manipulator_selectbuf(scene, sa, ar, event->mval, 0.2f * (float)U.tw_hotspot);
if (drawflags == 0) drawflags = val;
/* Planar constraint doesn't make sense for rotation, give other keymaps a chance */
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 058af768885..23158495b44 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -451,18 +451,18 @@ void initTransformOrientation(bContext *C, TransInfo *t)
case V3D_MANIP_GIMBAL:
unit_m3(t->spacemtx);
- if (gimbal_axis(ob, t->spacemtx)) {
+ if (ob && gimbal_axis(ob, t->spacemtx)) {
BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename));
break;
}
- /* fall-through */ /* no gimbal fallthrough to normal */
+ ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */
case V3D_MANIP_NORMAL:
if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
break;
}
- /* fall-through */ /* we define 'normal' as 'local' in Object mode */
+ ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */
case V3D_MANIP_LOCAL:
BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename));
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 3c9becc60dc..aecd24d4e40 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -234,7 +234,7 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
/* -------------------------------------------------------------------- */
-/** \Common utilities
+/** Common utilities
* \{ */
/**
@@ -620,7 +620,7 @@ static float dist_aabb_to_plane(
/* -------------------------------------------------------------------- */
-/** \Walk DFS
+/** Walk DFS
* \{ */
typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data);
@@ -1122,15 +1122,14 @@ static bool snapDerivedMesh(
float dist_px_sq = dist_squared_to_projected_aabb_simple(
lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
- if (dist_px_sq > SQUARE(*dist_px))
- {
+ if (dist_px_sq > SQUARE(*dist_px)) {
return retval;
}
}
else {
/* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
{
return retval;
}
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index e07831358d6..61142fdc887 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -296,7 +296,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
}
/* Else, common behavior with DELKEY, only difference is remove char(s) before/after the cursor. */
dir = STRCUR_DIR_PREV;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case DELKEY:
if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) {
int t_cur = cur = n->str_cur;
@@ -322,7 +322,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
break;
case LEFTARROWKEY:
dir = STRCUR_DIR_PREV;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case RIGHTARROWKEY:
cur = n->str_cur;
if (event->ctrl) {
@@ -497,7 +497,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
n->unit_sys, n->unit_type[idx]);
/* Note: with angles, we always get values as radians here... */
- if (BPY_execute_string_as_number(C, str_unit_convert, &val, false)) {
+ if (BPY_execute_string_as_number(C, str_unit_convert, false, &val)) {
n->val[idx] = (float)val;
n->val_flag[idx] &= ~NUM_INVALID;
}
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index fab5b7e821f..4e021d4833e 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -419,6 +419,9 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
if (G.debug & G_DEBUG)
printf("redo_cb: operator redo %s\n", op->type->name);
+
+ WM_operator_free_all_after(wm, op);
+
ED_undo_pop_op(C, op);
if (op->type->check) {
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 59119529934..d4ceaa39d3c 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -510,7 +510,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
ma = give_current_material(ob, ob->actcol);
- if (me->mtpoly) {
+ if (me->mloopuv) {
MPoly *mpoly = me->mpoly;
MLoopUV *mloopuv, *mloopuv_base;
int a, b;
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 6b37a81db8c..212c4c5ab7a 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -3139,7 +3139,7 @@ static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PV
PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe;
float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f;
float len1, len2;
-
+
/* find longest series of verts split in the chart itself, these are
* marked during construction */
be = outer;
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 50aec737c8e..d5233f0ed28 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -2116,6 +2116,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
break;
}
+ ATTR_FALLTHROUGH;
case PADENTER:
case RETKEY:
if (event->val == KM_PRESS) {
diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp
index c331d1de9c9..9b1b02c8ee2 100644
--- a/source/blender/freestyle/intern/application/AppView.cpp
+++ b/source/blender/freestyle/intern/application/AppView.cpp
@@ -22,12 +22,6 @@
* \ingroup freestyle
*/
-/* This header file needs to be included first, in order to avoid a
- compilation with MinGW (see the commit log of revision 28253) */
-extern "C" {
-#include "BLI_jitter.h"
-}
-
#include <iostream>
#include "Controller.h"
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index f63cf771120..1dbac1848b7 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -524,7 +524,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
// We'll generate both with tips and without tips
// coordinates, on two different UV layers.
- if (ma->mtex[a]->texflag & MTEX_TIPS) {
+ if (ma->mtex[a]->texflag & MTEX_TIPS) {
BLI_strncpy(ma->mtex[a]->uvname, uvNames[1], sizeof(ma->mtex[a]->uvname));
}
else {
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index 223bc607e21..ea22633c50e 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -448,15 +448,13 @@ static void prepare(Render *re, SceneRenderLayer *srl)
RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name);
bool diffuse = false, z = false;
for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
- switch (rpass->passtype) {
- case SCE_PASS_DIFFUSE:
+ if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty);
diffuse = true;
- break;
- case SCE_PASS_Z:
+ }
+ if (STREQ(rpass->name, RE_PASSNAME_Z)) {
controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty);
z = true;
- break;
}
}
if (G.debug & G_DEBUG_FREESTYLE) {
@@ -492,7 +490,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
return;
}
- src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, freestyle_render->viewname);
+ src = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, freestyle_render->viewname);
if (!src) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "No source result image to composite" << endl;
@@ -512,7 +510,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
}
return;
}
- dest = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
+ dest = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname);
if (!dest) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "No destination result image to composite to" << endl;
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h
index d65b0ea803b..444fd7c4785 100644
--- a/source/blender/freestyle/intern/geometry/matrix_util.h
+++ b/source/blender/freestyle/intern/geometry/matrix_util.h
@@ -50,15 +50,15 @@ namespace MatrixUtil {
/**
* computes the eigen values and eigen vectors of a semi definite symmetric matrix
*
- * @param matrix is stored in column symmetric storage, i.e.
+ * \param mat: The matrix stored in column symmetric storage, i.e.
* matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
* size = n(n+1)/2
*
- * @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
+ * \param eigen_vec: (return) = { v1, v2, v3, ..., vn }
* where vk = vk0, vk1, ..., vkn
* size = n^2, must be allocated by caller
*
- * @param eigen_values (return) are in decreasing order
+ * \param eigen_val: (return) are in decreasing order
* size = n, must be allocated by caller
*/
void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val);
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index b693d473bd8..e4a837d0a5f 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -222,50 +222,53 @@ void GPU_interleaved_attrib_unbind(void);
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
/* build */
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
const int (*face_vert_indices)[3],
const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopTri *looptri,
const struct MVert *verts,
const int *face_indices,
const int face_indices_len);
-GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(
+GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
int *grid_indices, int totgrid, unsigned int **grid_hidden, int gridsize, const struct CCGKey *key,
struct GridCommonGPUBuffer **grid_common_gpu_buffer);
-GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading);
+GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading);
/* update */
-void GPU_update_mesh_pbvh_buffers(
+void GPU_pbvh_mesh_buffers_update(
GPU_PBVH_Buffers *buffers, const struct MVert *mvert,
const int *vert_indices, int totvert, const float *vmask,
const int (*face_vert_indices)[3], bool show_diffuse_color);
-void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
- struct BMesh *bm,
- struct GSet *bm_faces,
- struct GSet *bm_unique_verts,
- struct GSet *bm_other_verts,
- bool show_diffuse_color);
+void GPU_pbvh_bmesh_buffers_update(
+ GPU_PBVH_Buffers *buffers,
+ struct BMesh *bm,
+ struct GSet *bm_faces,
+ struct GSet *bm_unique_verts,
+ struct GSet *bm_other_verts,
+ bool show_diffuse_color);
-void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **grids,
- const struct DMFlagMat *grid_flag_mats,
- int *grid_indices, int totgrid, const struct CCGKey *key,
- bool show_diffuse_color);
+void GPU_pbvh_grid_buffers_update(
+ GPU_PBVH_Buffers *buffers, struct CCGElem **grids,
+ const struct DMFlagMat *grid_flag_mats,
+ int *grid_indices, int totgrid, const struct CCGKey *key,
+ bool show_diffuse_color);
/* draw */
-void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe, bool fast);
+void GPU_pbvh_buffers_draw(
+ GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
+ bool wireframe, bool fast);
/* debug PBVH draw*/
-void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf);
-void GPU_end_draw_pbvh_BB(void);
-void GPU_init_draw_pbvh_BB(void);
+void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf);
+void GPU_pbvh_BB_draw_init(void);
+void GPU_pbvh_BB_draw_end(void);
bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color);
-void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers);
-void GPU_free_pbvh_buffer_multires(struct GridCommonGPUBuffer **grid_common_gpu_buffer);
+void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers);
+void GPU_pbvh_multires_buffers_free(struct GridCommonGPUBuffer **grid_common_gpu_buffer);
#endif
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 0d92d22a173..6db23686832 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -98,6 +98,7 @@ typedef enum GPUBuiltin {
GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
+ GPU_OBJECT_INFO = (1 << 15)
} GPUBuiltin;
typedef enum GPUOpenGLBuiltin {
@@ -213,6 +214,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link);
void GPU_material_enable_alpha(GPUMaterial *material);
+GPUBuiltin GPU_get_material_builtins(GPUMaterial *material);
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
/* High level functions to create and use GPU materials */
@@ -230,7 +232,7 @@ void GPU_material_bind(
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
void GPU_material_bind_uniforms(
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
- float autobumpscale, GPUParticleInfo *pi);
+ float autobumpscale, GPUParticleInfo *pi, float object_info[3]);
void GPU_material_unbind(GPUMaterial *material);
bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
@@ -345,6 +347,7 @@ struct GPUParticleInfo
float location[3];
float velocity[3];
float angular_velocity[3];
+ int random_id;
};
#ifdef WITH_OPENSUBDIV
diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index a2b89239344..8505bd847a0 100644
--- a/source/blender/gpu/intern/gpu_basic_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -407,7 +407,7 @@ static GPUShader *gpu_basic_shader(int options)
return shader;
}
-static void GPU_basic_shader_uniform_autoset(GPUShader *shader, int options)
+static void gpu_basic_shader_uniform_autoset(GPUShader *shader, int options)
{
if (options & GPU_SHADER_LINE) {
glGetIntegerv(GL_VIEWPORT, &GPU_MATERIAL_STATE.viewport[0]);
@@ -443,7 +443,7 @@ void GPU_basic_shader_bind(int options)
if (shader) {
GPU_shader_bind(shader);
- GPU_basic_shader_uniform_autoset(shader, options);
+ gpu_basic_shader_uniform_autoset(shader, options);
}
}
else {
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 370841327aa..9f1fe3a5a67 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -743,7 +743,7 @@ void GPU_triangle_setup(struct DerivedMesh *dm)
GLStates |= GPU_BUFFER_ELEMENT_STATE;
}
-static int GPU_typesize(int type)
+static int gpu_typesize(int type)
{
switch (type) {
case GL_FLOAT:
@@ -766,7 +766,7 @@ int GPU_attrib_element_size(GPUAttrib data[], int numdata)
int i, elementsize = 0;
for (i = 0; i < numdata; i++) {
- int typesize = GPU_typesize(data[i].type);
+ int typesize = gpu_typesize(data[i].type);
if (typesize != 0)
elementsize += typesize * data[i].size;
}
@@ -803,7 +803,7 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
glVertexAttribPointer(data[i].index, data[i].size, data[i].type,
GL_TRUE, elementsize, BUFFER_OFFSET(offset));
- offset += data[i].size * GPU_typesize(data[i].type);
+ offset += data[i].size * gpu_typesize(data[i].type);
attribData[i].index = data[i].index;
attribData[i].size = data[i].size;
@@ -1030,13 +1030,13 @@ static void gpu_color_from_mask_quad_copy(const CCGKey *key,
out[2] = diffuse_color[2] * mask_color;
}
-void GPU_update_mesh_pbvh_buffers(
+void GPU_pbvh_mesh_buffers_update(
GPU_PBVH_Buffers *buffers, const MVert *mvert,
const int *vert_indices, int totvert, const float *vmask,
const int (*face_vert_indices)[3], bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
- int i, j;
+ int i;
buffers->vmask = vmask;
buffers->show_diffuse_color = show_diffuse_color;
@@ -1057,6 +1057,9 @@ void GPU_update_mesh_pbvh_buffers(
copy_v4_v4(buffers->diffuse_color, diffuse_color);
+ uchar diffuse_color_ub[4];
+ rgba_float_to_uchar(diffuse_color_ub, diffuse_color);
+
/* Build VBO */
if (buffers->vert_buf)
GPU_buffer_free(buffers->vert_buf);
@@ -1076,28 +1079,20 @@ void GPU_update_mesh_pbvh_buffers(
memcpy(out->no, v->no, sizeof(short) * 3);
}
-#define UPDATE_VERTEX(face, vertex, index, diffuse_color) \
- { \
- VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \
- if (vmask) \
- gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \
- else \
- rgb_float_to_uchar(out->color, diffuse_color); \
- } (void)0
-
for (i = 0; i < buffers->face_indices_len; i++) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
- const unsigned int vtri[3] = {
- buffers->mloop[lt->tri[0]].v,
- buffers->mloop[lt->tri[1]].v,
- buffers->mloop[lt->tri[2]].v,
- };
+ for (uint j = 0; j < 3; j++) {
+ VertexBufferFormat *out = vert_data + face_vert_indices[i][j];
- UPDATE_VERTEX(i, vtri[0], 0, diffuse_color);
- UPDATE_VERTEX(i, vtri[1], 1, diffuse_color);
- UPDATE_VERTEX(i, vtri[2], 2, diffuse_color);
+ if (vmask) {
+ uint v_index = buffers->mloop[lt->tri[j]].v;
+ gpu_color_from_mask_copy(vmask[v_index], diffuse_color, out->color);
+ }
+ else {
+ copy_v3_v3_uchar(out->color, diffuse_color_ub);
+ }
+ }
}
-#undef UPDATE_VERTEX
}
else {
/* calculate normal for each polygon only once */
@@ -1112,8 +1107,6 @@ void GPU_update_mesh_pbvh_buffers(
buffers->mloop[lt->tri[2]].v,
};
- float fmask;
-
if (paint_is_face_hidden(lt, mvert, buffers->mloop))
continue;
@@ -1126,23 +1119,22 @@ void GPU_update_mesh_pbvh_buffers(
mpoly_prev = lt->poly;
}
+ uchar color_ub[3];
if (vmask) {
- fmask = (vmask[vtri[0]] +
- vmask[vtri[1]] +
- vmask[vtri[2]]) / 3.0f;
+ float fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f;
+ gpu_color_from_mask_copy(fmask, diffuse_color, color_ub);
+ }
+ else {
+ copy_v3_v3_uchar(color_ub, diffuse_color_ub);
}
- for (j = 0; j < 3; j++) {
+ for (uint j = 0; j < 3; j++) {
const MVert *v = &mvert[vtri[j]];
VertexBufferFormat *out = vert_data;
copy_v3_v3(out->co, v->co);
copy_v3_v3_short(out->no, no);
-
- if (vmask)
- gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
- else
- rgb_float_to_uchar(out->color, diffuse_color);
+ copy_v3_v3_uchar(out->color, color_ub);
vert_data++;
}
@@ -1160,7 +1152,7 @@ void GPU_update_mesh_pbvh_buffers(
buffers->mvert = mvert;
}
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
const int (*face_vert_indices)[3],
const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri,
const MVert *mvert,
@@ -1244,9 +1236,10 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
return buffers;
}
-void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
- const DMFlagMat *grid_flag_mats, int *grid_indices,
- int totgrid, const CCGKey *key, bool show_diffuse_color)
+void GPU_pbvh_grid_buffers_update(
+ GPU_PBVH_Buffers *buffers, CCGElem **grids,
+ const DMFlagMat *grid_flag_mats, int *grid_indices,
+ int totgrid, const CCGKey *key, bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
int i, j, k, x, y;
@@ -1466,7 +1459,7 @@ static GPUBuffer *gpu_get_grid_buffer(
} \
} (void)0
-GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(
+GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key,
GridCommonGPUBuffer **grid_common_gpu_buffer)
{
@@ -1612,12 +1605,13 @@ static int gpu_bmesh_face_visible_count(GSet *bm_faces)
/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
* shading, an element index buffer. */
-void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
- BMesh *bm,
- GSet *bm_faces,
- GSet *bm_unique_verts,
- GSet *bm_other_verts,
- bool show_diffuse_color)
+void GPU_pbvh_bmesh_buffers_update(
+ GPU_PBVH_Buffers *buffers,
+ BMesh *bm,
+ GSet *bm_faces,
+ GSet *bm_unique_verts,
+ GSet *bm_other_verts,
+ bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
void *tri_data;
@@ -1803,7 +1797,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
}
}
-GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading)
+GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
{
GPU_PBVH_Buffers *buffers;
@@ -1816,8 +1810,9 @@ GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading)
return buffers;
}
-void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe, bool fast)
+void GPU_pbvh_buffers_draw(
+ GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
+ bool wireframe, bool fast)
{
bool do_fast = fast && buffers->index_buf_fast;
/* sets material from the first face, to solve properly face would need to
@@ -1956,7 +1951,8 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
}
}
-bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
+bool GPU_pbvh_buffers_diffuse_changed(
+ GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
{
float diffuse_color[4];
bool use_matcaps = GPU_material_use_matcaps_get();
@@ -1999,7 +1995,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
return !equals_v3v3(diffuse_color, buffers->diffuse_color);
}
-void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
+void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
if (buffers->vert_buf)
@@ -2017,7 +2013,7 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
}
}
-void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer)
+void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer)
{
GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer;
@@ -2033,7 +2029,7 @@ void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer)
}
/* debug function, draws the pbvh BB */
-void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
+void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf)
{
const float quads[4][4][3] = {
{
@@ -2074,7 +2070,7 @@ void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
glDrawArrays(GL_QUADS, 0, 16);
}
-void GPU_init_draw_pbvh_BB(void)
+void GPU_pbvh_BB_draw_init(void)
{
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_CULL_FACE);
@@ -2084,7 +2080,7 @@ void GPU_init_draw_pbvh_BB(void)
glEnable(GL_BLEND);
}
-void GPU_end_draw_pbvh_BB(void)
+void GPU_pbvh_BB_draw_end(void)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glPopAttrib();
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 211394e7932..b5512aa108d 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -360,7 +360,7 @@ static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
for (i = 0; i < type; i++) {
- BLI_dynstr_appendf(ds, "%f", data[i]);
+ BLI_dynstr_appendf(ds, "%.12f", data[i]);
if (i == type - 1)
BLI_dynstr_append(ds, ")");
else
@@ -410,6 +410,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "unfparticlevel";
else if (builtin == GPU_PARTICLE_ANG_VELOCITY)
return "unfparticleangvel";
+ else if (builtin == GPU_OBJECT_INFO)
+ return "unfobjectinfo";
else
return "";
}
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 964c2b5051e..2f2a16f9e1d 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -798,7 +798,9 @@ bool GPU_fx_do_composite_pass(
ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
if (ssao_shader) {
const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
- float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
+ /* adjust attenuation to be scale invariant */
+ float attenuation = fx_ssao->attenuation / (fx_ssao->distance_max * fx_ssao->distance_max);
+ float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, attenuation, 0.0f};
float sample_params[3];
sample_params[0] = fx->ssao_sample_count_cache;
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index ba68d1a6a0f..7a0562617d6 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -29,6 +29,7 @@
* \ingroup gpu
*/
+#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#include "BLI_sys_types.h"
#include "BLI_system.h"
@@ -219,7 +220,7 @@ static void APIENTRY gpu_debug_proc(
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH:
backtrace = true;
- /* fall through */
+ ATTR_FALLTHROUGH;
case GL_DEBUG_SEVERITY_MEDIUM:
case GL_DEBUG_SEVERITY_LOW:
case GL_DEBUG_SEVERITY_NOTIFICATION: /* KHR has this, ARB does not */
@@ -249,7 +250,7 @@ static void APIENTRY gpu_debug_proc_amd(
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH:
backtrace = true;
- /* fall through */
+ ATTR_FALLTHROUGH;
case GL_DEBUG_SEVERITY_MEDIUM:
case GL_DEBUG_SEVERITY_LOW:
fprintf(stderr, "GL %s: %s\n", category_name_amd(category), message);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 7936811ab4d..1583d16ca27 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -45,6 +45,7 @@
#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_hash.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
@@ -1203,7 +1204,7 @@ void GPU_paint_set_mipmap(bool mipmap)
/* check if image has been downscaled and do scaled partial update */
-static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
+static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
{
if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y))
@@ -1296,7 +1297,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
- if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
+ if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
MEM_freeN(buffer);
BKE_image_release_ibuf(ima, ibuf, NULL);
return;
@@ -1320,7 +1321,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
return;
}
- if (GPU_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
+ if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
BKE_image_release_ibuf(ima, ibuf, NULL);
return;
}
@@ -1870,7 +1871,7 @@ void GPU_begin_object_materials(
GPU_object_material_unbind();
}
-static int GPU_get_particle_info(GPUParticleInfo *pi)
+static int gpu_get_particle_info(GPUParticleInfo *pi)
{
DupliObject *dob = GMS.dob;
if (dob->particle_system) {
@@ -1899,6 +1900,21 @@ static int GPU_get_particle_info(GPUParticleInfo *pi)
return 0;
}
+static void GPU_get_object_info(float oi[3], Material *mat)
+{
+ Object *ob = GMS.gob;
+ oi[0] = ob->index;
+ oi[1] = mat->index;
+ unsigned int random;
+ if (GMS.dob) {
+ random = GMS.dob->random_id;
+ }
+ else {
+ random = BLI_hash_int_2d(BLI_hash_string(GMS.gob->id.name + 2), 0);
+ }
+ oi[2] = random * (1.0f / (float)0xFFFFFFFF);
+}
+
int GPU_object_material_bind(int nr, void *attribs)
{
GPUVertexAttribs *gattribs = attribs;
@@ -1958,21 +1974,27 @@ int GPU_object_material_bind(int nr, void *attribs)
/* bind glsl material and get attributes */
Material *mat = GMS.gmatbuf[nr];
GPUParticleInfo partile_info;
+ float object_info[3] = {0};
float auto_bump_scale;
GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
GPU_material_vertex_attributes(gpumat, gattribs);
- if (GMS.dob)
- GPU_get_particle_info(&partile_info);
+ if (GMS.dob) {
+ gpu_get_particle_info(&partile_info);
+ }
+
+ if (GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) {
+ GPU_get_object_info(object_info, mat);
+ }
GPU_material_bind(
gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info);
+ GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info);
GMS.gboundmat = mat;
/* for glsl use alpha blend mode, unless it's set to solid and
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index f62ef677434..e7a8beae5cc 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -52,7 +52,7 @@ struct GPUFrameBuffer {
GPUTexture *depthtex;
};
-static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
+static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
{
const char *err = "unknown";
@@ -164,7 +164,7 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot
if (error == GL_INVALID_OPERATION) {
GPU_framebuffer_restore();
- GPU_print_framebuffer_error(error, err_out);
+ gpu_print_framebuffer_error(error, err_out);
return 0;
}
@@ -331,7 +331,7 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
GPU_framebuffer_restore();
- GPU_print_framebuffer_error(status, err_out);
+ gpu_print_framebuffer_error(status, err_out);
return false;
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 4e2043471b6..1f3ae7f708a 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -122,6 +122,8 @@ struct GPUMaterial {
int partvel;
int partangvel;
+ int objectinfoloc;
+
ListBase lamps;
bool bound;
@@ -225,7 +227,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
attribs->totlayer = b;
}
-static int GPU_material_construct_end(GPUMaterial *material, const char *passname)
+static int gpu_material_construct_end(GPUMaterial *material, const char *passname)
{
if (material->outlink) {
GPUNodeLink *outlink = material->outlink;
@@ -268,6 +270,8 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam
material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY));
if (material->builtins & GPU_PARTICLE_ANG_VELOCITY)
material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY));
+ if (material->builtins & GPU_OBJECT_INFO)
+ material->objectinfoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_INFO));
return 1;
}
else {
@@ -398,9 +402,14 @@ void GPU_material_bind(
}
}
+GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
+{
+ return material->builtins;
+}
+
void GPU_material_bind_uniforms(
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
- float autobumpscale, GPUParticleInfo *pi)
+ float autobumpscale, GPUParticleInfo *pi, float object_info[3])
{
if (material->pass) {
GPUShader *shader = GPU_pass_shader(material->pass);
@@ -449,6 +458,9 @@ void GPU_material_bind_uniforms(
if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) {
GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity);
}
+ if (material->builtins & GPU_OBJECT_INFO) {
+ GPU_shader_uniform_vector(shader, material->objectinfoloc, 3, 1, object_info);
+ }
}
}
@@ -1891,7 +1903,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv
GPU_material_output_link(mat, outlink);
- GPU_material_construct_end(mat, "matcap_pass");
+ gpu_material_construct_end(mat, "matcap_pass");
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -2044,7 +2056,7 @@ static void do_world_tex(GPUShadeInput *shi, struct World *wo, GPUNodeLink **hor
}
}
-static void GPU_material_old_world(struct GPUMaterial *mat, struct World *wo)
+static void gpu_material_old_world(struct GPUMaterial *mat, struct World *wo)
{
GPUShadeInput shi;
GPUShadeResult shr;
@@ -2112,17 +2124,18 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
mat->type = GPU_MATERIAL_TYPE_WORLD;
/* create nodes */
- if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes)
+ if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) {
ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING);
+ }
else {
- GPU_material_old_world(mat, wo);
+ gpu_material_old_world(mat, wo);
}
if (GPU_material_do_color_management(mat))
if (mat->outlink)
GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
- GPU_material_construct_end(mat, wo->id.name);
+ gpu_material_construct_end(mat, wo->id.name);
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -2188,7 +2201,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open
if (mat->outlink)
GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
- GPU_material_construct_end(mat, ma->id.name);
+ gpu_material_construct_end(mat, ma->id.name);
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 9496ff137dc..632b0cfee1b 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -75,6 +75,12 @@ static GPUSelectState g_select_state = {0};
*/
void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits)
{
+ if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ /* In the case hits was '-1', don't start the second pass since it's not going to give useful results.
+ * As well as buffer overflow in 'gpu_select_query_load_id'. */
+ BLI_assert(oldhits != -1);
+ }
+
g_select_state.select_is_active = true;
g_select_state.use_gpu_select = GPU_select_query_check_active();
g_select_state.mode = mode;
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index ba5fefc5227..3d589986281 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -142,13 +142,17 @@ bool gpu_select_query_load_id(unsigned int id)
g_query_state.active_query++;
g_query_state.query_issued = true;
- if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) {
- if (g_query_state.buffer[g_query_state.index][3] == id) {
- g_query_state.index++;
- return true;
- }
- else {
- return false;
+ if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ /* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */
+ BLI_assert(g_query_state.oldhits != -1);
+ if (g_query_state.index < g_query_state.oldhits) {
+ if (g_query_state.buffer[g_query_state.index][3] == id) {
+ g_query_state.index++;
+ return true;
+ }
+ else {
+ return false;
+ }
}
}
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 14f2764b009..b579f87698c 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -39,6 +39,7 @@
#include "GPU_glew.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_material.h"
/* TODO(sergey): Find better default values for this constants. */
#define MAX_DEFINE_LENGTH 1024
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 54f0003c086..1c97c2ce811 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -79,7 +79,7 @@ static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixel
return pixels;
}
-static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
+static void gpu_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
{
void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
@@ -193,7 +193,7 @@ static GPUTexture *GPU_texture_create_nD(
pixels ? pixels : fpixels);
if (tex->w > w) {
- GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
+ gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
}
}
}
@@ -210,10 +210,12 @@ static GPUTexture *GPU_texture_create_nD(
glTexSubImage2D(tex->target, 0, 0, 0, w, h,
format, type, pixels ? pixels : fpixels);
- if (tex->w > w)
- GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
- if (tex->h > h)
- GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
+ if (tex->w > w) {
+ gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
+ }
+ if (tex->h > h) {
+ gpu_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
+ }
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
index 50c8e255162..f19ff4ec65a 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -75,7 +75,7 @@ float calculate_ssao_factor(float depth)
float f = dot(dir, normal);
/* use minor bias here to avoid self shadowing */
- if (f > 0.05 * len + 0.0001)
+ if (f > 0.05 * len)
factor += f * 1.0 / (len * (1.0 + len * len * ssao_params.z));
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 0f3ffa8244b..ef2060122e0 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -403,7 +403,7 @@ void math_modulo(float val1, float val2, out float outval)
/* change sign to match C convention, mod in GLSL will take absolute for negative numbers,
* see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */
- outval = (val1 > 0.0) ? outval : -outval;
+ outval = (val1 > 0.0) ? outval : outval - val2;
}
void math_abs(float val1, out float outval)
@@ -2378,11 +2378,19 @@ void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
/*********** NEW SHADER UTILITIES **************/
-float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
+float fresnel_dielectric_0(float eta)
+{
+ /* compute fresnel reflactance at normal incidence => cosi = 1.0 */
+ float A = (eta - 1.0) / (eta + 1.0);
+
+ return A * A;
+}
+
+float fresnel_dielectric_cos(float cosi, float eta)
{
/* compute fresnel reflectance without explicitly computing
* the refracted direction */
- float c = abs(dot(Incoming, Normal));
+ float c = abs(cosi);
float g = eta * eta - 1.0 + c * c;
float result;
@@ -2399,6 +2407,13 @@ float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
return result;
}
+float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
+{
+ /* compute fresnel reflectance without explicitly computing
+ * the refracted direction */
+ return fresnel_dielectric_cos(dot(Incoming, Normal), eta);
+}
+
float hypot(float x, float y)
{
return sqrt(x * x + y * y);
@@ -2492,6 +2507,57 @@ float floorfrac(float x, out int i)
return x - i;
}
+
+/* Principled BSDF operations */
+
+float sqr(float a)
+{
+ return a*a;
+}
+
+float schlick_fresnel(float u)
+{
+ float m = clamp(1.0 - u, 0.0, 1.0);
+ float m2 = m * m;
+ return m2 * m2 * m; // pow(m,5)
+}
+
+float GTR1(float NdotH, float a)
+{
+ if (a >= 1.0) return M_1_PI;
+ float a2 = a*a;
+ float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
+ return (a2 - 1.0) / (M_PI * log(a2) * t);
+}
+
+float GTR2(float NdotH, float a)
+{
+ float a2 = a*a;
+ float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
+ return a2 / (M_PI * t*t);
+}
+
+float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
+{
+ return 1.0 / (M_PI * ax*ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH*NdotH));
+}
+
+float smithG_GGX(float NdotV, float alphaG)
+{
+ float a = alphaG*alphaG;
+ float b = NdotV*NdotV;
+ return 1.0 / (NdotV + sqrt(a + b - a * b));
+}
+
+vec3 rotate_vector(vec3 p, vec3 n, float theta) {
+ return (
+ p * cos(theta) + cross(n, p) *
+ sin(theta) + n * dot(p, n) *
+ (1.0 - cos(theta))
+ );
+}
+
+
/*********** NEW SHADER NODES ***************/
#define NUM_LIGHTS 3
@@ -2553,6 +2619,126 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 resu
node_bsdf_diffuse(color, 0.0, N, result);
}
+void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+{
+ /* ambient light */
+ // TODO: set ambient light to an appropriate value
+ vec3 L = vec3(mix(0.1, 0.03, metallic)) * base_color.rgb;
+
+ float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
+
+ /* set the viewing vector */
+ vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0);
+
+ /* get the tangent */
+ vec3 Tangent = T;
+ if (T == vec3(0.0)) {
+ // if no tangent is set, use a default tangent
+ Tangent = vec3(1.0, 0.0, 0.0);
+ if (N.x != 0.0 || N.y != 0.0) {
+ vec3 N_xz = normalize(vec3(N.x, 0.0, N.z));
+
+ vec3 axis = normalize(cross(vec3(0.0, 0.0, 1.0), N_xz));
+ float angle = acos(dot(vec3(0.0, 0.0, 1.0), N_xz));
+
+ Tangent = normalize(rotate_vector(vec3(1.0, 0.0, 0.0), axis, angle));
+ }
+ }
+
+ /* rotate tangent */
+ if (anisotropic_rotation != 0.0) {
+ Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI);
+ }
+
+ /* calculate the tangent and bitangent */
+ vec3 Y = normalize(cross(N, Tangent));
+ vec3 X = cross(Y, N);
+
+ /* fresnel normalization parameters */
+ float F0 = fresnel_dielectric_0(eta);
+ float F0_norm = 1.0 / (1.0 - F0);
+
+ /* directional lights */
+ for (int i = 0; i < NUM_LIGHTS; i++) {
+ vec3 light_position_world = gl_LightSource[i].position.xyz;
+ vec3 light_position = normalize(gl_NormalMatrix * light_position_world);
+
+ vec3 H = normalize(light_position + V);
+
+ vec3 light_specular = gl_LightSource[i].specular.rgb;
+
+ float NdotL = dot(N, light_position);
+ float NdotV = dot(N, V);
+ float LdotH = dot(light_position, H);
+
+ vec3 diffuse_and_specular_bsdf = vec3(0.0);
+ if (NdotL >= 0.0 && NdotV >= 0.0) {
+ float NdotH = dot(N, H);
+
+ float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx.
+
+ vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat
+ vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic);
+ vec3 Csheen = mix(vec3(1.0), Ctint, sheen_tint);
+
+ // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
+ // and mix in diffuse retro-reflection based on roughness
+
+ float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
+ float Fd90 = 0.5 + 2.0 * LdotH*LdotH * roughness;
+ float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
+
+ // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
+ // 1.25 scale is used to (roughly) preserve albedo
+ // Fss90 used to "flatten" retroreflection based on roughness
+ float Fss90 = LdotH*LdotH * roughness;
+ float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
+ float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5);
+
+ // specular
+ float aspect = sqrt(1.0 - anisotropic * 0.9);
+ float a = sqr(roughness);
+ float ax = max(0.001, a / aspect);
+ float ay = max(0.001, a * aspect);
+ float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a);
+ float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm;
+ vec3 Fs = mix(Cspec0, vec3(1.0), FH);
+ float roughg = sqr(roughness * 0.5 + 0.5);
+ float Gs = smithG_GGX(NdotL, roughg) * smithG_GGX(NdotV, roughg);
+
+ // sheen
+ vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen;
+
+ diffuse_and_specular_bsdf = (M_1_PI * mix(Fd, ss, subsurface) * base_color.rgb + Fsheen)
+ * (1.0 - metallic) + Gs * Fs * Ds;
+ }
+ diffuse_and_specular_bsdf *= max(NdotL, 0.0);
+
+ float CNdotL = dot(CN, light_position);
+ float CNdotV = dot(CN, V);
+
+ vec3 clearcoat_bsdf = vec3(0.0);
+ if (CNdotL >= 0.0 && CNdotV >= 0.0 && clearcoat > 0.0) {
+ float CNdotH = dot(CN, H);
+ //float FH = schlick_fresnel(LdotH);
+
+ // clearcoat (ior = 1.5 -> F0 = 0.04)
+ float Dr = GTR1(CNdotH, sqr(clearcoat_roughness));
+ float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH);
+ float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25);
+
+ clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25);
+ }
+ clearcoat_bsdf *= max(CNdotL, 0.0);
+
+ L += light_specular * (diffuse_and_specular_bsdf + clearcoat_bsdf);
+ }
+
+ result = vec4(L, 1.0);
+}
+
void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
{
node_bsdf_diffuse(color, 0.0, N, result);
@@ -2846,10 +3032,10 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bi
float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0);
float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
- if(min_dist >= mortar_size) {
+ if (min_dist >= mortar_size) {
return vec2(tint, 0.0);
}
- else if(mortar_smooth == 0.0) {
+ else if (mortar_smooth == 0.0) {
return vec2(tint, 1.0);
}
else {
@@ -3563,12 +3749,12 @@ void node_light_falloff(float strength, float tsmooth, out float quadratic, out
constant = strength;
}
-void node_object_info(out vec3 location, out float object_index, out float material_index, out float random)
+void node_object_info(mat4 obmat, vec3 info, out vec3 location, out float object_index, out float material_index, out float random)
{
- location = vec3(0.0);
- object_index = 0.0;
- material_index = 0.0;
- random = 0.0;
+ location = obmat[3].xyz;
+ object_index = info.x;
+ material_index = info.y;
+ random = info.z;
}
void node_normal_map(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 4164f5fa75d..ff1784c54dd 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -162,7 +162,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_look_items_add(struct EnumPropertyItem **items, int *totitem, const char *view_name);
void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem);
/* ** Tile-based buffer management ** */
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 93d2b3e0cd0..e7abfdc7d67 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -166,7 +166,7 @@ struct ImBuf *IMB_makeSingleUser(struct ImBuf *ibuf);
*
* \attention Defined in allocimbuf.c
*/
-struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1);
+struct ImBuf *IMB_dupImBuf(const struct ImBuf *ibuf1);
/**
*
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index f4b2539d7d7..1701c2ba307 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -237,9 +237,8 @@ typedef struct ImBuf {
/**
* \name Imbuf Component flags
* \brief These flags determine the components of an ImBuf struct.
- */
-/**@{*/
-/** \brief Flag defining the components of the ImBuf struct. */
+ *
+ * \{ */
#define IB_rect (1 << 0)
#define IB_test (1 << 1)
@@ -259,15 +258,20 @@ typedef struct ImBuf {
#define IB_thumbnail (1 << 15)
#define IB_multiview (1 << 16)
+/** \} */
+
/**
* \name Imbuf preset profile tags
* \brief Some predefined color space profiles that 8 bit imbufs can represent
- */
+ *
+ * \{ */
#define IB_PROFILE_NONE 0
#define IB_PROFILE_LINEAR_RGB 1
#define IB_PROFILE_SRGB 2
#define IB_PROFILE_CUSTOM 3
+/** \} */
+
/* dds */
#ifdef WITH_DDS
#ifndef DDS_MAKEFOURCC
@@ -298,8 +302,16 @@ extern const char *imb_ext_audio[];
/* image formats that can only be loaded via filepath */
extern const char *imb_ext_image_filepath_only[];
+/**
+ * \name Imbuf Color Management Flag
+ * \brief Used with #ImBuf.colormanage_flag
+ *
+ * \{ */
+
enum {
IMB_COLORMANAGE_IS_DATA = (1 << 0)
};
-#endif
+/** \} */
+
+#endif /* __IMB_IMBUF_TYPES_H__ */
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index d89393b9903..6d7ad7985f9 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -40,10 +40,7 @@
# include <mmsystem.h>
# include <memory.h>
# include <commdlg.h>
-
-# ifndef FREE_WINDOWS
-# include <vfw.h>
-# endif
+# include <vfw.h>
# undef AVIIF_KEYFRAME // redefined in AVI_avi.h
# undef AVIIF_LIST // redefined in AVI_avi.h
@@ -130,7 +127,7 @@ struct anim {
/* avi */
struct _AviMovie *avi;
-#if defined(_WIN32) && !defined(FREE_WINDOWS)
+#if defined(_WIN32)
/* windows avi */
int avistreams;
int firstvideo;
diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
index b75f12b239d..0b4557e7bef 100644
--- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h
+++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
@@ -79,6 +79,8 @@ typedef struct ColorManagedLook {
struct ColorManagedLook *next, *prev;
int index;
char name[MAX_COLORSPACE_NAME];
+ char ui_name[MAX_COLORSPACE_NAME];
+ char view[MAX_COLORSPACE_NAME];
char process_space[MAX_COLORSPACE_NAME];
bool is_noop;
} ColorManagedLook;
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 33750478bb4..6e9bfa1fc4e 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -506,7 +506,7 @@ bool IMB_initImBuf(struct ImBuf *ibuf,
}
/* does no zbuffers? */
-ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
+ImBuf *IMB_dupImBuf(const ImBuf *ibuf1)
{
ImBuf *ibuf2, tbuf;
int flags = 0;
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index a40b257b75b..9806ff006d7 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -37,10 +37,7 @@
#include <mmsystem.h>
#include <memory.h>
#include <commdlg.h>
-
-#ifndef FREE_WINDOWS
#include <vfw.h>
-#endif
#undef AVIIF_KEYFRAME /* redefined in AVI_avi.h */
#undef AVIIF_LIST /* redefined in AVI_avi.h */
@@ -173,7 +170,7 @@ static void an_stringenc(char *string, const char *head, const char *tail, unsig
#ifdef WITH_AVI
static void free_anim_avi(struct anim *anim)
{
-#if defined(_WIN32) && !defined(FREE_WINDOWS)
+#if defined(_WIN32)
int i;
#endif
@@ -184,7 +181,7 @@ static void free_anim_avi(struct anim *anim)
MEM_freeN(anim->avi);
anim->avi = NULL;
-#if defined(_WIN32) && !defined(FREE_WINDOWS)
+#if defined(_WIN32)
if (anim->pgf) {
AVIStreamGetFrameClose(anim->pgf);
@@ -283,7 +280,7 @@ static int startavi(struct anim *anim)
{
AviError avierror;
-#if defined(_WIN32) && !defined(FREE_WINDOWS)
+#if defined(_WIN32)
HRESULT hr;
int i, firstvideo = -1;
int streamcount;
@@ -304,7 +301,7 @@ static int startavi(struct anim *anim)
avierror = AVI_open_movie(anim->name, anim->avi);
-#if defined(_WIN32) && !defined(FREE_WINDOWS)
+#if defined(_WIN32)
if (avierror == AVI_ERROR_COMPRESSION) {
AVIFileInit();
hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L);
@@ -401,7 +398,7 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position)
return NULL;
}
-#if defined(_WIN32) && !defined(FREE_WINDOWS)
+#if defined(_WIN32)
if (anim->avistreams) {
LPBITMAPINFOHEADER lpbi;
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 8b4e95ac452..429a19936a5 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -183,7 +183,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
if (verbose) printf("DPX: File is LSB.\n");
}
else {
- if (verbose) {
+ if (verbose) {
printf("DPX: Bad magic number %u in \"%s\".\n",
header.fileHeader.magic_num, byteStuff);
}
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c
index 6fb1bccf491..600642f5e44 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.c
+++ b/source/blender/imbuf/intern/cineon/logImageCore.c
@@ -177,19 +177,18 @@ unsigned int getRowLength(int width, LogImageElement logElement)
return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4;
else if (logElement.packing == 1 || logElement.packing == 2)
return ((width * logElement.depth - 1) / 3 + 1) * 4;
-
+ break;
case 12:
if (logElement.packing == 0)
return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4;
else if (logElement.packing == 1 || logElement.packing == 2)
return width * logElement.depth * 2;
-
+ break;
case 16:
return width * logElement.depth * 2;
- default:
- return 0;
}
+ return 0;
}
@@ -572,20 +571,20 @@ static int logImageElementGetData(LogImageFile *logImage, LogImageElement logEle
return logImageElementGetData10Packed(logImage, logElement, data);
else if (logElement.packing == 1 || logElement.packing == 2)
return logImageElementGetData10(logImage, logElement, data);
+ break;
case 12:
if (logElement.packing == 0)
return logImageElementGetData12Packed(logImage, logElement, data);
else if (logElement.packing == 1 || logElement.packing == 2)
return logImageElementGetData12(logImage, logElement, data);
+ break;
case 16:
return logImageElementGetData16(logImage, logElement, data);
-
- default:
- /* format not supported */
- return 1;
}
+ /* format not supported */
+ return 1;
}
static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data)
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 48cba3e0800..ff19a14dbff 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -214,7 +214,7 @@ typedef struct ColormanageCacheKey {
int display; /* display device name */
} ColormanageCacheKey;
-typedef struct ColormnaageCacheData {
+typedef struct ColormanageCacheData {
int flag; /* view flags of cached buffer */
int look; /* Additional artistics transform */
float exposure; /* exposure value cached buffer is calculated with */
@@ -222,12 +222,12 @@ typedef struct ColormnaageCacheData {
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;
+} ColormanageCacheData;
typedef struct ColormanageCache {
struct MovieCache *moviecache;
- ColormnaageCacheData *data;
+ ColormanageCacheData *data;
} ColormanageCache;
static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf)
@@ -238,7 +238,7 @@ static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf)
return ibuf->colormanage_cache->moviecache;
}
-static ColormnaageCacheData *colormanage_cachedata_get(const ImBuf *ibuf)
+static ColormanageCacheData *colormanage_cachedata_get(const ImBuf *ibuf)
{
if (!ibuf->colormanage_cache)
return NULL;
@@ -281,7 +281,7 @@ static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf)
return ibuf->colormanage_cache->moviecache;
}
-static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data)
+static void colormanage_cachedata_set(ImBuf *ibuf, ColormanageCacheData *data)
{
if (!ibuf->colormanage_cache)
ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache");
@@ -361,7 +361,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle);
if (cache_ibuf) {
- ColormnaageCacheData *cache_data;
+ ColormanageCacheData *cache_data;
BLI_assert(cache_ibuf->x == ibuf->x &&
cache_ibuf->y == ibuf->y);
@@ -402,7 +402,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
{
ColormanageCacheKey key;
ImBuf *cache_ibuf;
- ColormnaageCacheData *cache_data;
+ ColormanageCacheData *cache_data;
int view_flag = 1 << (view_settings->view - 1);
struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf);
CurveMapping *curve_mapping = view_settings->curve_mapping;
@@ -421,7 +421,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
cache_ibuf->flags |= IB_rect;
/* 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 = MEM_callocN(sizeof(ColormanageCacheData), "color manage cache imbuf data");
cache_data->look = view_settings->look;
cache_data->exposure = view_settings->exposure;
cache_data->gamma = view_settings->gamma;
@@ -710,7 +710,7 @@ void colormanage_cache_free(ImBuf *ibuf)
}
if (ibuf->colormanage_cache) {
- ColormnaageCacheData *cache_data = colormanage_cachedata_get(ibuf);
+ ColormanageCacheData *cache_data = colormanage_cachedata_get(ibuf);
struct MovieCache *moviecache = colormanage_moviecache_get(ibuf);
if (cache_data) {
@@ -1406,7 +1406,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
bool is_data = handle->is_data;
if (cm_processor == NULL) {
- if (display_buffer_byte) {
+ if (display_buffer_byte && display_buffer_byte != handle->byte_buffer) {
IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
false, width, height, width, width);
}
@@ -1759,9 +1759,14 @@ void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsig
return;
}
if (STREQ(from_colorspace, to_colorspace)) {
- /* If source and destination color spaces are identical, skip
- * threading overhead and simply do nothing
+ /* Because this function always takes a byte buffer and returns a float buffer, it must
+ * always do byte-to-float conversion of some kind. To avoid threading overhead
+ * IMB_buffer_float_from_byte is used when color spaces are identical. See T51002.
*/
+ IMB_buffer_float_from_byte(float_buffer, byte_buffer,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ true,
+ width, height, width, width);
return;
}
cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
@@ -2060,6 +2065,10 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, boo
}
}
+ if (colormanaged_ibuf != ibuf) {
+ IMB_metadata_copy(colormanaged_ibuf, ibuf);
+ }
+
return colormanaged_ibuf;
}
@@ -2568,9 +2577,17 @@ ColorManagedLook *colormanage_look_add(const char *name, const char *process_spa
look = MEM_callocN(sizeof(ColorManagedLook), "ColorManagedLook");
look->index = index + 1;
BLI_strncpy(look->name, name, sizeof(look->name));
+ BLI_strncpy(look->ui_name, name, sizeof(look->ui_name));
BLI_strncpy(look->process_space, process_space, sizeof(look->process_space));
look->is_noop = is_noop;
+ /* Detect view specific looks. */
+ const char *separator_offset = strstr(look->name, " - ");
+ if (separator_offset) {
+ BLI_strncpy(look->view, look->name, separator_offset - look->name + 1);
+ BLI_strncpy(look->ui_name, separator_offset + strlen(" - "), sizeof(look->ui_name));
+ }
+
BLI_addtail(&global_looks, look);
global_tot_looks++;
@@ -2671,15 +2688,27 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem,
}
}
-void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem)
+void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem, const char *view_name)
{
ColorManagedLook *look;
+ const char *view_filter = NULL;
+
+ /* Test if this view transform is limited to specific looks. */
+ for (look = global_looks.first; look; look = look->next) {
+ if (STREQ(look->view, view_name)) {
+ view_filter = view_name;
+ }
+ }
for (look = global_looks.first; look; look = look->next) {
+ if (!look->is_noop && view_filter && !STREQ(look->view, view_filter)) {
+ continue;
+ }
+
EnumPropertyItem item;
item.value = look->index;
- item.name = look->name;
+ item.name = look->ui_name;
item.identifier = look->name;
item.icon = 0;
item.description = "";
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index 12e03f55450..67a0b0ffd00 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -37,7 +37,7 @@ extern "C" {
#include <stdio.h> // printf
#include <fstream>
-#if defined (WIN32) && !defined(FREE_WINDOWS)
+#if defined (WIN32)
#include "utfconv.h"
#endif
@@ -62,7 +62,7 @@ int imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/)
/* open file for writing */
std::ofstream fildes;
-#if defined (WIN32) && !defined(FREE_WINDOWS)
+#if defined (WIN32)
wchar_t *wname = alloc_utf16_from_8(name, 0);
fildes.open(wname);
free(wname);
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
index 1987c6d2a9a..38609d0a342 100644
--- a/source/blender/imbuf/intern/filter.c
+++ b/source/blender/imbuf/intern/filter.c
@@ -406,7 +406,7 @@ void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter)
const int height = ibuf->y;
const int depth = 4; /* always 4 channels */
const int chsize = ibuf->rect_float ? sizeof(float) : sizeof(unsigned char);
- const int bsize = width * height * depth * chsize;
+ const size_t bsize = ((size_t)width) * height * depth * chsize;
const bool is_float = (ibuf->rect_float != NULL);
void *dstbuf = (void *) MEM_dupallocN(ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect);
char *dstmask = mask == NULL ? NULL : (char *) MEM_dupallocN(mask);
@@ -499,7 +499,9 @@ void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter)
/* keep the original buffer up to date. */
memcpy(srcbuf, dstbuf, bsize);
- if (dstmask != NULL) memcpy(srcmask, dstmask, width * height);
+ if (dstmask != NULL) {
+ memcpy(srcmask, dstmask, ((size_t)width) * height);
+ }
}
/* free memory */
diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c
index 134bbe88f15..da39967a4fe 100644
--- a/source/blender/imbuf/intern/metadata.c
+++ b/source/blender/imbuf/intern/metadata.c
@@ -81,7 +81,9 @@ bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, con
void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb)
{
+ BLI_assert(dimb != simb);
if (simb->metadata) {
+ IMB_metadata_free(dimb);
dimb->metadata = IDP_CopyProperty(simb->metadata);
}
}
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
index 11bf45418d6..b123d508f99 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -31,7 +31,7 @@
#include <set>
-#if defined(WIN32) && !defined(FREE_WINDOWS)
+#if defined(WIN32)
#include "utfconv.h"
#endif
@@ -213,7 +213,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac
in = ImageInput::create(filename);
if (!in) {
std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl
- << OpenImageIO::geterror() << std::endl;
+ << OIIO_NAMESPACE::geterror() << std::endl;
return NULL;
}
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 89e796fb7ee..ec544e65355 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -69,7 +69,7 @@
#include <openexr_api.h>
-#if defined (WIN32) && !defined(FREE_WINDOWS)
+#if defined (WIN32)
#include "utfconv.h"
#endif
@@ -77,7 +77,7 @@ extern "C"
{
// The following prevents a linking error in debug mode for MSVC using the libs in CVS
-#if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && _MSC_VER < 1900
+#if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && _MSC_VER < 1900
_CRTIMP void __cdecl _invalid_parameter_noinfo(void)
{
}
@@ -180,7 +180,7 @@ public:
: IStream(filename)
{
/* utf-8 file path support on windows */
-#if defined (WIN32) && !defined(FREE_WINDOWS)
+#if defined (WIN32)
wchar_t *wfilename = alloc_utf16_from_8(filename, 0);
ifs.open(wfilename, std::ios_base::binary);
free(wfilename);
@@ -243,7 +243,7 @@ public:
: OStream(filename)
{
/* utf-8 file path support on windows */
-#if defined (WIN32) && !defined(FREE_WINDOWS)
+#if defined (WIN32)
wchar_t *wfilename = alloc_utf16_from_8(filename, 0);
ofs.open(wfilename, std::ios_base::binary);
free(wfilename);
@@ -1026,15 +1026,16 @@ void IMB_exr_set_channel(void *handle, const char *layname, const char *passname
ExrChannel *echan;
char name[EXR_TOT_MAXNAME + 1];
- if (layname) {
+ if (layname && layname[0] != '\0') {
char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1];
BLI_strncpy(lay, layname, EXR_LAY_MAXNAME);
BLI_strncpy(pass, passname, EXR_PASS_MAXNAME);
BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass);
}
- else
+ else {
BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1);
+ }
echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name));
@@ -1043,8 +1044,9 @@ void IMB_exr_set_channel(void *handle, const char *layname, const char *passname
echan->ystride = ystride;
echan->rect = rect;
}
- else
+ else {
printf("IMB_exr_set_channel error %s\n", name);
+ }
}
float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *viewname)
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index 5192e3f2d26..503e63a3fb1 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -613,11 +613,12 @@ ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colors
int unit_type;
png_uint_32 xres, yres;
- if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type))
+ if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) {
if (unit_type == PNG_RESOLUTION_METER) {
ibuf->ppm[0] = xres;
ibuf->ppm[1] = yres;
}
+ }
}
}
else {
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 71e74928e20..a21468e474c 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -340,13 +340,14 @@ static int fwritecolrs(FILE *file, int width, int channels, unsigned char *ibufs
}
if (((beg - j) > 1) && ((beg - j) < MINRUN)) {
c2 = j + 1;
- while (rgbe_scan[c2++][i] == rgbe_scan[j][i])
+ while (rgbe_scan[c2++][i] == rgbe_scan[j][i]) {
if (c2 == beg) { /* short run */
putc((unsigned char)(128 + beg - j), file);
putc((unsigned char)(rgbe_scan[j][i]), file);
j = beg;
break;
}
+ }
}
while (j < beg) { /* write out non-run */
if ((c2 = beg - j) > 128) c2 = 128;
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 2c6f3d2fc66..da0f505c4f3 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -82,8 +82,6 @@ enum {
IDP_FLOAT = 2,
IDP_ARRAY = 5,
IDP_GROUP = 6,
- /* the ID link property type hasn't been implemented yet, this will require
- * some cleanup of blenkernel, most likely. */
IDP_ID = 7,
IDP_DOUBLE = 8,
IDP_IDPARRAY = 9,
diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h
index 46b1adf2725..a353c94ae64 100644
--- a/source/blender/makesdna/DNA_cachefile_types.h
+++ b/source/blender/makesdna/DNA_cachefile_types.h
@@ -47,10 +47,12 @@ enum {
CACHEFILE_KEYFRAME_DRAWN = (1 << 0),
};
+/* Representation of an object's path inside the Alembic file.
+ * Note that this is not a file path. */
typedef struct AlembicObjectPath {
struct AlembicObjectPath *next, *prev;
- char path[1024]; /* 1024 = FILE_MAX, might use PATH_MAX in the future. */
+ char path[4096];
} AlembicObjectPath;
typedef struct CacheFile {
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index df1142cb61e..3e878fab66b 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -164,8 +164,8 @@ typedef struct MLoop {
* MEdge *ed = &medge[mloop[lt->tri[j]].e];
* unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
*
- * if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) &&
- * ELEM(ed->v2, tri_edge[0], tri_edge[1]))
+ * if (((ed->v1 == tri_edge[0]) && (ed->v1 == tri_edge[1])) ||
+ * ((ed->v1 == tri_edge[1]) && (ed->v1 == tri_edge[0])))
* {
* printf("real edge found %u %u\n", tri_edge[0], tri_edge[1]);
* }
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 32b43c7ea55..823a7f0812f 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -277,6 +277,7 @@ typedef struct MirrorModifierData {
short axis DNA_DEPRECATED; /* deprecated, use flag instead */
short flag;
float tolerance;
+ float uv_offset[2];
struct Object *mirror_ob;
} MirrorModifierData;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 47677e50451..b922ac072b0 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -569,9 +569,9 @@ typedef struct NodeEllipseMask {
/* layer info for image node outputs */
typedef struct NodeImageLayer {
/* index in the Image->layers->passes lists */
- int pass_index;
- /* render pass flag, in case this is an original render pass */
- int pass_flag;
+ int pass_index DNA_DEPRECATED;
+ /* render pass name */
+ char pass_name[64]; /* amount defined in openexr_multi.h */
} NodeImageLayer;
typedef struct NodeBlurData {
diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h
index a714195dd5d..846d5788d63 100644
--- a/source/blender/makesdna/DNA_object_fluidsim.h
+++ b/source/blender/makesdna/DNA_object_fluidsim.h
@@ -179,6 +179,7 @@ typedef struct FluidsimSettings {
#define OB_FLUIDSIM_ACTIVE (1 << 1)
#define OB_FLUIDSIM_OVERRIDE_TIME (1 << 2)
+#define OB_FLUIDSIM_SURF_DIR_DEFAULT "cache_fluid"
#define OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME "fluidsurface_preview_####.bobj.gz"
#define OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME "fluidsurface_final_####.bobj.gz"
#define OB_FLUIDSIM_SURF_FINAL_VEL_FNAME "fluidsurface_final_####.bvel.gz"
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index d24c7faa9f5..6d79e6d49f8 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -335,6 +335,8 @@ typedef struct DupliObject {
/* particle this dupli was generated from */
struct ParticleSystem *particle_system;
+ unsigned int random_id;
+ unsigned int pad;
} DupliObject;
/* **************** OBJECT ********************* */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index b7539eaedd9..92c789f2feb 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -229,7 +229,9 @@ typedef struct SceneRenderLayer {
int samples;
float pass_alpha_threshold;
-
+
+ IDProperty *prop;
+
struct FreestyleConfig freestyleConfig;
} SceneRenderLayer;
@@ -283,9 +285,43 @@ typedef enum ScenePassType {
SCE_PASS_SUBSURFACE_DIRECT = (1 << 28),
SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29),
SCE_PASS_SUBSURFACE_COLOR = (1 << 30),
- SCE_PASS_DEBUG = (1 << 31), /* This is a virtual pass. */
} ScenePassType;
+#define RE_PASSNAME_COMBINED "Combined"
+#define RE_PASSNAME_Z "Depth"
+#define RE_PASSNAME_VECTOR "Vector"
+#define RE_PASSNAME_NORMAL "Normal"
+#define RE_PASSNAME_UV "UV"
+#define RE_PASSNAME_RGBA "Color"
+#define RE_PASSNAME_EMIT "Emit"
+#define RE_PASSNAME_DIFFUSE "Diffuse"
+#define RE_PASSNAME_SPEC "Spec"
+#define RE_PASSNAME_SHADOW "Shadow"
+
+#define RE_PASSNAME_AO "AO"
+#define RE_PASSNAME_ENVIRONMENT "Env"
+#define RE_PASSNAME_INDIRECT "Indirect"
+#define RE_PASSNAME_REFLECT "Reflect"
+#define RE_PASSNAME_REFRACT "Refract"
+#define RE_PASSNAME_INDEXOB "IndexOB"
+#define RE_PASSNAME_INDEXMA "IndexMA"
+#define RE_PASSNAME_MIST "Mist"
+
+#define RE_PASSNAME_RAYHITS "RayHits"
+#define RE_PASSNAME_DIFFUSE_DIRECT "DiffDir"
+#define RE_PASSNAME_DIFFUSE_INDIRECT "DiffInd"
+#define RE_PASSNAME_DIFFUSE_COLOR "DiffCol"
+#define RE_PASSNAME_GLOSSY_DIRECT "GlossDir"
+#define RE_PASSNAME_GLOSSY_INDIRECT "GlossInd"
+#define RE_PASSNAME_GLOSSY_COLOR "GlossCol"
+#define RE_PASSNAME_TRANSM_DIRECT "TransDir"
+#define RE_PASSNAME_TRANSM_INDIRECT "TransInd"
+#define RE_PASSNAME_TRANSM_COLOR "TransCol"
+
+#define RE_PASSNAME_SUBSURFACE_DIRECT "SubsurfaceDir"
+#define RE_PASSNAME_SUBSURFACE_INDIRECT "SubsurfaceInd"
+#define RE_PASSNAME_SUBSURFACE_COLOR "SubsurfaceCol"
+
/* note, srl->passflag is treestore element 'nr' in outliner, short still... */
/* View - MultiView */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 5e015544dc9..0e5d9bd33e6 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1151,7 +1151,7 @@ typedef enum eSpaceNode_Flag {
SNODE_SHOW_G = (1 << 8),
SNODE_SHOW_B = (1 << 9),
SNODE_AUTO_RENDER = (1 << 5),
- SNODE_SHOW_HIGHLIGHT = (1 << 6),
+// SNODE_SHOW_HIGHLIGHT = (1 << 6), DNA_DEPRECATED
// SNODE_USE_HIDDEN_PREVIEW = (1 << 10), DNA_DEPRECATED December2013
SNODE_NEW_SHADERS = (1 << 11),
SNODE_PIN = (1 << 12),
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 73c341e35ba..5e7e7366e35 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -467,13 +467,18 @@ typedef struct UserDef {
int audioformat;
int audiochannels;
- int scrollback; /* console scrollback limit */
- int dpi; /* range 48-128? */
- char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
+ int scrollback; /* console scrollback limit */
+ int dpi; /* range 48-128? */
+ float ui_scale; /* interface scale */
+ int pad1;
+ char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
char pad2;
short transopts;
short menuthreshold1, menuthreshold2;
-
+
+ /* startup template */
+ char app_template[64];
+
struct ListBase themes;
struct ListBase uifonts;
struct ListBase uistyles;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index f9aaec69ce7..a1af3f98274 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -767,6 +767,8 @@ void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type);
struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create);
bool RNA_struct_idprops_check(StructRNA *srna);
bool RNA_struct_idprops_register_check(const StructRNA *type);
+bool RNA_struct_idprops_datablock_allowed(const StructRNA *type);
+bool RNA_struct_idprops_contains_datablock(const StructRNA *type);
bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier);
PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier);
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 2a680b6eaeb..6e62313b00a 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -167,6 +167,7 @@ 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, const void *func);
+void RNA_def_property_poll_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_types.h b/source/blender/makesrna/RNA_types.h
index dee8df7d933..cd04f9e8a6d 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -434,6 +434,8 @@ typedef enum StructFlag {
STRUCT_GENERATED = (1 << 4),
STRUCT_FREE_POINTERS = (1 << 5),
STRUCT_NO_IDPROPERTIES = (1 << 6), /* Menus and Panels don't need properties */
+ STRUCT_NO_DATABLOCK_IDPROPERTIES = (1 << 7), /* e.g. for Operator */
+ STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES = (1 << 8), /* for PropertyGroup which contains pointers to datablocks */
} StructFlag;
typedef int (*StructValidateFunc)(struct PointerRNA *ptr, void *data, int *have_function);
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 0f3ea27a7f9..6a08d762920 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -176,9 +176,6 @@ set(INC_SYS
if(WITH_CYCLES)
add_definitions(-DWITH_CYCLES)
- if(WITH_CYCLES_DEBUG)
- add_definitions(-DWITH_CYCLES_DEBUG)
- endif()
endif()
if(WITH_PYTHON)
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 4552c773097..de436172bfd 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -507,7 +507,7 @@ static void rna_float_print(FILE *f, float num)
{
if (num == -FLT_MAX) fprintf(f, "-FLT_MAX");
else if (num == FLT_MAX) fprintf(f, "FLT_MAX");
- else if ((int64_t)num == num) fprintf(f, "%.1ff", num);
+ else if ((ABS(num) < INT64_MAX) && ((int64_t)num == num)) fprintf(f, "%.1ff", num);
else fprintf(f, "%.10ff", num);
}
@@ -3746,7 +3746,7 @@ static const char *cpp_classes = ""
"template<typename T, TBeginFunc Tbegin, TNextFunc Tnext, TEndFunc Tend>\n"
"class CollectionIterator {\n"
"public:\n"
-" CollectionIterator() : t(iter.ptr), init(false) { iter.valid = false; }\n"
+" CollectionIterator() : iter(), t(iter.ptr), init(false) { iter.valid = false; }\n"
" ~CollectionIterator(void) { if (init) Tend(&iter); };\n"
"\n"
" operator bool(void)\n"
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 671902c5cc7..a74758a4f71 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -342,7 +342,7 @@ static void rna_ID_user_clear(ID *id)
static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id)
{
- if (GS(id->name) == GS(new_id->name)) {
+ if ((GS(id->name) == GS(new_id->name)) && (id != new_id)) {
/* For now, do not allow remapping data in linked data from here... */
BKE_libblock_remap(bmain, id, new_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
}
@@ -802,7 +802,11 @@ static void rna_def_ID_properties(BlenderRNA *brna)
RNA_def_struct_name_property(srna, prop);
#endif
- /* IDP_ID -- not implemented yet in id properties */
+ /* IDP_ID */
+ prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EXPORT | PROP_IDPROPERTY | PROP_NEVER_UNLINK);
+ RNA_def_property_struct_type(prop, "ID");
+
/* ID property groups > level 0, since level 0 group is merged
* with native RNA properties. the builtin_properties will take
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index bb839fd77f8..5a4db47d281 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -50,6 +50,7 @@
#include "BKE_idcode.h"
#include "BKE_idprop.h"
#include "BKE_fcurve.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -380,6 +381,7 @@ static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDPr
return false;
break;
case IDP_GROUP:
+ case IDP_ID:
if (prop->type != PROP_POINTER)
return false;
break;
@@ -395,7 +397,8 @@ static PropertyRNA *typemap[IDP_NUMTYPES] = {
(PropertyRNA *)&rna_PropertyGroupItem_int,
(PropertyRNA *)&rna_PropertyGroupItem_float,
NULL, NULL, NULL,
- (PropertyRNA *)&rna_PropertyGroupItem_group, NULL,
+ (PropertyRNA *)&rna_PropertyGroupItem_group,
+ (PropertyRNA *)&rna_PropertyGroupItem_id,
(PropertyRNA *)&rna_PropertyGroupItem_double,
(PropertyRNA *)&rna_PropertyGroupItem_idp_array
};
@@ -587,6 +590,21 @@ bool RNA_struct_idprops_register_check(const StructRNA *type)
return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
}
+bool RNA_struct_idprops_datablock_allowed(const StructRNA *type)
+{
+ return (type->flag & (STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_NO_IDPROPERTIES)) == 0;
+}
+
+/**
+ * Whether given type implies datablock usage by IDProperties.
+ * This is used to prevent classes allowed to have IDProperties, but not datablock ones, to indirectly use some
+ * (e.g. by assigning an IDP_GROUP containing some IDP_ID pointers...).
+ */
+bool RNA_struct_idprops_contains_datablock(const StructRNA *type)
+{
+ return (type->flag & (STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES | STRUCT_ID)) != 0;
+}
+
/* remove an id-property */
bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
{
@@ -628,8 +646,11 @@ PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
/* id prop lookup, not so common */
PropertyRNA *r_prop = NULL;
PointerRNA r_ptr; /* only support single level props */
- if (RNA_path_resolve(ptr, identifier, &r_ptr, &r_prop) && (r_ptr.type == ptr->type) && (r_ptr.data == ptr->data))
+ if (RNA_path_resolve_property(ptr, identifier, &r_ptr, &r_prop) &&
+ (r_ptr.type == ptr->type) && (r_ptr.data == ptr->data))
+ {
return r_prop;
+ }
}
else {
/* most common case */
@@ -1201,13 +1222,20 @@ int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *va
if (prop->type == PROP_POINTER) {
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
- if (pprop->poll)
- return pprop->poll(ptr, *value);
+
+ if (pprop->poll) {
+ if (rna_idproperty_check(&prop, ptr)) {
+ return ((PropPointerPollFuncPy) pprop->poll)(ptr, *value, prop);
+ }
+ else {
+ return pprop->poll(ptr, *value);
+ }
+ }
return 1;
}
- printf("%s %s: is not a pointer property.\n", __func__, prop->identifier);
+ printf("%s: %s is not a pointer property.\n", __func__, prop->identifier);
return 0;
}
@@ -2967,6 +2995,10 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
if ((idprop = rna_idproperty_check(&prop, ptr))) {
pprop = (PointerPropertyRNA *)prop;
+ if (RNA_struct_is_ID(pprop->type)) {
+ return rna_pointer_inherit_refine(ptr, pprop->type, IDP_Id(idprop));
+ }
+
/* for groups, data is idprop itself */
if (pprop->typef)
return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
@@ -2989,22 +3021,32 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
{
- /*IDProperty *idprop;*/
-
+ PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_POINTER);
- if ((/*idprop = */ rna_idproperty_check(&prop, ptr))) {
- /* not supported */
- /* rna_idproperty_touch(idprop); */
+ /* Check types */
+ if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
+ printf("%s: expected %s type, not %s.\n", __func__, pprop->type->identifier, ptr_value.type->identifier);
+ return;
}
- else {
- PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
- if (pprop->set &&
- !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
- !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data))
- {
- pprop->set(ptr, ptr_value);
+ /* RNA */
+ if (pprop->set &&
+ !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
+ !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data))
+ {
+ pprop->set(ptr, ptr_value);
+ }
+ /* IDProperty */
+ else if (prop->flag & PROP_EDITABLE) {
+ IDPropertyTemplate val = {0};
+ IDProperty *group;
+
+ val.id = ptr_value.data;
+
+ group = RNA_struct_idprops(ptr, true);
+ if (group) {
+ IDP_ReplaceInGroup(group, IDP_New(IDP_ID, &val, prop->identifier));
}
}
}
@@ -5547,6 +5589,9 @@ static char *rna_pointer_as_string__bldata(PointerRNA *ptr)
return BLI_strdup("None");
}
else if (RNA_struct_is_ID(ptr->type)) {
+ if (ptr->id.data == NULL) {
+ return BLI_strdup("None");
+ }
return RNA_path_full_ID_py(ptr->id.data);
}
else {
@@ -5554,9 +5599,13 @@ static char *rna_pointer_as_string__bldata(PointerRNA *ptr)
}
}
-char *RNA_pointer_as_string(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *prop_ptr, PointerRNA *ptr_prop)
+char *RNA_pointer_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop_ptr, PointerRNA *ptr_prop)
{
- if (RNA_property_flag(prop_ptr) & PROP_IDPROPERTY) {
+ IDProperty *prop;
+ if (ptr_prop->data == NULL) {
+ return BLI_strdup("None");
+ }
+ else if ((prop = rna_idproperty_check(&prop_ptr, ptr)) && prop->type != IDP_ID) {
return RNA_pointer_as_string_id(C, ptr_prop);
}
else {
@@ -6397,7 +6446,7 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop
tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(srna));
return -1;
}
-
+
*((void **)dest) = *((void **)src);
break;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 0c4c7ddac81..d398ce95a52 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -34,6 +34,8 @@
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "BKE_action.h"
#include "RNA_access.h"
@@ -731,6 +733,7 @@ static void rna_def_action(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "ID Root Type",
"Type of ID block that action can be used on - "
"DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
/* API calls */
RNA_api_action(srna);
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 9adbf5f6b2e..f271bccd326 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -32,6 +32,8 @@
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
@@ -742,6 +744,7 @@ static void rna_def_keyingset_path(BlenderRNA *brna)
RNA_def_property_enum_default(prop, ID_OB);
RNA_def_property_enum_funcs(prop, NULL, "rna_ksPath_id_type_set", NULL);
RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */
/* Group */
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 07d295c8bbc..891f5c43ca6 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -187,6 +187,9 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
}
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
+
+ /* spaces that show animation data of the selected bone need updating */
+ WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN, id);
}
static char *rna_Bone_path(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index d3cd3d12c4d..5339df34a38 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -508,12 +508,13 @@ static void rna_ColorManagedViewSettings_look_set(PointerRNA *ptr, int value)
}
static EnumPropertyItem *rna_ColorManagedViewSettings_look_itemf(
- bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
+ ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
EnumPropertyItem *items = NULL;
int totitem = 0;
- IMB_colormanagement_look_items_add(&items, &totitem);
+ IMB_colormanagement_look_items_add(&items, &totitem, view->view_transform);
RNA_enum_item_end(&items, &totitem);
*r_free = true;
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 1d232d2df39..42c0344f46e 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -71,8 +71,8 @@ BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
if (description && (description)[0]) { \
int i = strlen(description); \
if (i > 3 && (description)[i - 1] == '.' && (description)[i - 3] != '.') { \
- fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \
- __func__, id1 ? id1 : "", id2 ? id2 : ""); \
+ fprintf(stderr, "%s: '%s' description from '%s' '%s' ends with a '.' !\n", \
+ __func__, description, id1 ? id1 : "", id2 ? id2 : ""); \
} \
} (void)0
@@ -2168,6 +2168,16 @@ void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func)
prop->update = (void *)func;
}
+void RNA_def_property_poll_runtime(PropertyRNA *prop, const void *func)
+{
+ if (prop->type == PROP_POINTER) {
+ ((PointerPropertyRNA *)prop)->poll = func;
+ }
+ else {
+ fprintf(stderr, "%s: %s is not a Pointer Property.\n", __func__, prop->identifier);
+ }
+}
+
void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength)
{
if (!DefRNA.preprocess) {
@@ -2982,6 +2992,9 @@ PropertyRNA *RNA_def_pointer_runtime(StructOrFunctionRNA *cont_, const char *ide
prop = RNA_def_property(cont, identifier, PROP_POINTER, PROP_NONE);
RNA_def_property_struct_runtime(prop, type);
+ if ((type->flag & STRUCT_ID) != 0) {
+ prop->flag |= PROP_EDITABLE;
+ }
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 4acdee490b8..bccc47aa95d 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -35,6 +35,8 @@
#include "BLI_math.h"
+#include "BLT_translation.h"
+
#include "BKE_action.h"
#include "RNA_access.h"
@@ -1448,6 +1450,7 @@ static void rna_def_drivertarget(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, NULL, "rna_DriverTarget_id_type_set", NULL);
RNA_def_property_editable_func(prop, "rna_DriverTarget_id_type_editable");
RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
/* Target Properties - Property to Drive */
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 091950a8e66..8c3984e4b29 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -185,12 +185,16 @@ static void rna_DomainFluidSettings_memory_estimate_get(PointerRNA *ptr, char *v
#endif
}
-static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *UNUSED(ptr))
+static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *ptr)
{
#ifndef WITH_MOD_FLUID
+ UNUSED_VARS(ptr);
return 0;
#else
- return 31;
+ char value[32];
+
+ rna_DomainFluidSettings_memory_estimate_get(ptr, value);
+ return strlen(value);
#endif
}
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index f65aa90ea71..b6e84cf8ac3 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -871,7 +871,7 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "has_data", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_Image_has_data_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Has data", "True if this image has data");
+ RNA_def_property_ui_text(prop, "Has Data", "True if the image data is loaded into memory");
prop = RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_Image_depth_get", NULL, NULL);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 76455adbc78..dfd5af788f6 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -344,6 +344,7 @@ extern IntPropertyRNA rna_PropertyGroupItem_int_array;
extern FloatPropertyRNA rna_PropertyGroupItem_float;
extern FloatPropertyRNA rna_PropertyGroupItem_float_array;
extern PointerPropertyRNA rna_PropertyGroupItem_group;
+extern PointerPropertyRNA rna_PropertyGroupItem_id;
extern CollectionPropertyRNA rna_PropertyGroupItem_collection;
extern CollectionPropertyRNA rna_PropertyGroupItem_idp_array;
extern FloatPropertyRNA rna_PropertyGroupItem_double;
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index fce81e6967e..df591659fdb 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -94,6 +94,7 @@ typedef PointerRNA (*PropPointerGetFunc)(struct PointerRNA *ptr);
typedef StructRNA *(*PropPointerTypeFunc)(struct PointerRNA *ptr);
typedef void (*PropPointerSetFunc)(struct PointerRNA *ptr, const PointerRNA value);
typedef int (*PropPointerPollFunc)(struct PointerRNA *ptr, const PointerRNA value);
+typedef int (*PropPointerPollFuncPy)(struct PointerRNA *ptr, const PointerRNA value, const PropertyRNA *prop);
typedef void (*PropCollectionBeginFunc)(struct CollectionPropertyIterator *iter, struct PointerRNA *ptr);
typedef void (*PropCollectionNextFunc)(struct CollectionPropertyIterator *iter);
typedef void (*PropCollectionEndFunc)(struct CollectionPropertyIterator *iter);
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 1199cccc4e6..a163d9764c1 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -1620,6 +1620,7 @@ static void rna_def_linestyle(BlenderRNA *brna)
prop = RNA_def_property(srna, "panel", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "panel");
RNA_def_property_enum_items(prop, panel_items);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Panel", "Select the property panel to be shown");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 47c4b425155..1a8dd05a7b5 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1526,6 +1526,20 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mirror V", "Mirror the V texture coordinate around the 0.5 point");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "mirror_offset_u", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "uv_offset[0]");
+ RNA_def_property_range(prop, -1, 1);
+ RNA_def_property_ui_range(prop, -1, 1, 2, 4);
+ RNA_def_property_ui_text(prop, "U Offset", "Amount to offset mirrored UVs from the 0.5 point on the U axis");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "mirror_offset_v", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "uv_offset[1]");
+ RNA_def_property_range(prop, -1, 1);
+ RNA_def_property_ui_range(prop, -1, 1, 2, 4);
+ RNA_def_property_ui_text(prop, "V Offset", "Amount to offset mirrored UVs from the 0.5 point on the V axis");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "tolerance");
RNA_def_property_range(prop, 0, FLT_MAX);
@@ -4717,7 +4731,7 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SurfaceDeformModifier", "Modifier");
- RNA_def_struct_ui_text(srna, "SurfaceDeform Modifier", "blablabla");
+ RNA_def_struct_ui_text(srna, "SurfaceDeform Modifier", "");
RNA_def_struct_sdna(srna, "SurfaceDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 784004182dd..10422c85579 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -64,6 +64,8 @@
#include "RE_render_ext.h"
+#include "NOD_composite.h"
+
EnumPropertyItem rna_enum_node_socket_in_out_items[] = {
{ SOCK_IN, "IN", 0, "Input", "" },
{ SOCK_OUT, "OUT", 0, "Output", "" },
@@ -2608,7 +2610,7 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p
rna_Node_update(bmain, scene, ptr);
if (scene->nodetree != NULL) {
- ntreeCompositForceHidden(scene->nodetree);
+ ntreeCompositUpdateRLayers(scene->nodetree);
}
}
@@ -2747,7 +2749,7 @@ static void rna_Node_scene_layer_update(Main *bmain, Scene *scene, PointerRNA *p
{
rna_Node_update(bmain, scene, ptr);
if (scene->nodetree != NULL) {
- ntreeCompositForceHidden(scene->nodetree);
+ ntreeCompositUpdateRLayers(scene->nodetree);
}
}
@@ -2995,6 +2997,15 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
ED_node_tag_update_nodetree(bmain, ntree, node);
}
+static void rna_ShaderNodePrincipled_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_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@ -3254,6 +3265,12 @@ static EnumPropertyItem node_script_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem node_principled_distribution_items[] = {
+ { SHD_GLOSSY_GGX, "GGX", 0, "GGX", "" },
+ { SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", "" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
/* -- Common nodes ---------------------------------------------------------- */
static void def_group_input(StructRNA *srna)
@@ -3327,6 +3344,7 @@ static void def_frame(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_struct_sdna_from(srna, "NodeFrame", "storage");
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_ID_NODETREE);
prop = RNA_def_property(srna, "shrink", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_FRAME_SHRINK);
@@ -4187,6 +4205,17 @@ static void def_glass(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_principled(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, node_principled_distribution_items);
+ RNA_def_property_ui_text(prop, "Distribution", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update");
+}
+
static void def_refraction(StructRNA *srna)
{
PropertyRNA *prop;
@@ -4769,7 +4798,7 @@ static void def_cmp_render_layers(StructRNA *srna)
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Scene", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update");
prop = RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
@@ -5210,6 +5239,16 @@ static void def_cmp_luma_matte(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_brightcontrast(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1);
+ RNA_def_property_ui_text(prop, "Convert Premul", "Keep output image premultiplied alpha");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
static void def_cmp_chroma_matte(StructRNA *srna)
{
PropertyRNA *prop;
@@ -6281,14 +6320,8 @@ static void def_cmp_switch(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
-static void def_cmp_switch_view(StructRNA *srna)
+static void def_cmp_switch_view(StructRNA *UNUSED(srna))
{
- PropertyRNA *prop;
-
- prop = RNA_def_property(srna, "check", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0);
- RNA_def_property_ui_text(prop, "Switch", "Off: first socket, On: second socket");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_colorcorrection(StructRNA *srna)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index b3c166a6810..a167ab03ba1 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -432,11 +432,7 @@ static void rna_Object_parent_set(PointerRNA *ptr, PointerRNA value)
{
Object *ob = (Object *)ptr->data;
Object *par = (Object *)value.data;
-
-#ifdef FREE_WINDOWS
- /* NOTE: this dummy check here prevents this method causing weird runtime errors on mingw 4.6.2 */
- if (ob)
-#endif
+
{
ED_object_parent(ob, par, ob->partype, ob->parsubstr);
}
@@ -532,8 +528,9 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
* thus causing a cycle/infinite-recursion leading to crashes on load [#25298]
*/
if (BKE_group_object_exists(grp, ob) == 0) {
+ id_us_min(&ob->dup_group->id);
ob->dup_group = grp;
- id_lib_extern((ID *)grp);
+ id_us_plus(&ob->dup_group->id);
}
else {
BKE_report(NULL, RPT_ERROR,
@@ -2897,6 +2894,10 @@ static void rna_def_dupli_object(BlenderRNA *brna)
RNA_def_property_enum_items(prop, dupli_items);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object");
+
+ prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object");
}
static void rna_def_object_base(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index c680abe71a4..9b9f0705bb4 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -321,49 +321,55 @@ static void rna_Object_ray_cast(
float origin[3], float direction[3], float distance,
int *r_success, float r_location[3], float r_normal[3], int *r_index)
{
- BVHTreeFromMesh treeData = {NULL};
-
+ bool success = false;
+
if (ob->derivedFinal == NULL) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' has no mesh data to be used for ray casting", ob->id.name + 2);
return;
}
- /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */
- bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6);
+ /* Test BoundBox first (efficiency) */
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ float distmin;
+ if (!bb || (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) {
- /* may fail if the mesh has no faces, in that case the ray-cast misses */
- if (treeData.tree != NULL) {
- BVHTreeRayHit hit;
+ BVHTreeFromMesh treeData = {NULL};
- hit.index = -1;
- hit.dist = distance;
-
- normalize_v3(direction);
+ /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */
+ bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6);
+
+ /* may fail if the mesh has no faces, in that case the ray-cast misses */
+ if (treeData.tree != NULL) {
+ BVHTreeRayHit hit;
+ hit.index = -1;
+ hit.dist = distance;
- if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit,
- treeData.raycast_callback, &treeData) != -1)
- {
- if (hit.dist <= distance) {
- *r_success = true;
+ normalize_v3(direction);
- copy_v3_v3(r_location, hit.co);
- copy_v3_v3(r_normal, hit.no);
- *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
- goto finally;
+ if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit,
+ treeData.raycast_callback, &treeData) != -1)
+ {
+ if (hit.dist <= distance) {
+ *r_success = success = true;
+
+ copy_v3_v3(r_location, hit.co);
+ copy_v3_v3(r_normal, hit.no);
+ *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
+ }
}
+
+ free_bvhtree_from_mesh(&treeData);
}
}
+ if (success == false) {
+ *r_success = false;
- *r_success = false;
-
- zero_v3(r_location);
- zero_v3(r_normal);
- *r_index = -1;
-
-finally:
- free_bvhtree_from_mesh(&treeData);
+ zero_v3(r_location);
+ zero_v3(r_normal);
+ *r_index = -1;
+ }
}
static void rna_Object_closest_point_on_mesh(
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 95dab13571d..a11b755c3c4 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -2095,7 +2095,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Even Distribution",
"Use even distribution from faces based on face areas or edge lengths");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
+
prop = RNA_def_property(srna, "use_die_on_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_DIE_ON_COL);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -2300,7 +2300,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_render_adaptive", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT);
- RNA_def_property_ui_text(prop, "Adaptive render", "Draw steps of the particle path");
+ RNA_def_property_ui_text(prop, "Adaptive Render", "Draw steps of the particle path");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "use_velocity_length", PROP_BOOLEAN, PROP_NONE);
@@ -2315,7 +2315,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_strand_primitive", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_STRAND);
- RNA_def_property_ui_text(prop, "Strand render", "Use the strand primitive for rendering");
+ RNA_def_property_ui_text(prop, "Strand Render", "Use the strand primitive for rendering");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "draw_method", PROP_ENUM, PROP_NONE);
@@ -2363,7 +2363,8 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Render", "How many steps paths are rendered with (power of 2)");
prop = RNA_def_property(srna, "hair_step", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 2, 50);
+ RNA_def_property_range(prop, 2, SHRT_MAX);
+ RNA_def_property_ui_range(prop, 2, 50, 1, 1);
RNA_def_property_ui_text(prop, "Segments", "Number of hair segments");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 518c7efd915..44dcb72264a 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
+#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -41,6 +42,7 @@
#include "RE_pipeline.h"
+/* Deprecated, only provided for API compatibility. */
EnumPropertyItem rna_enum_render_pass_type_items[] = {
{SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""},
{SCE_PASS_Z, "Z", 0, "Z", ""},
@@ -77,18 +79,6 @@ EnumPropertyItem rna_enum_render_pass_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem rna_enum_render_pass_debug_type_items[] = {
- {RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES, "BVH_TRAVERSED_NODES", 0, "BVH Traversed Nodes",
- "Number of nodes traversed in BVH for the camera rays"},
- {RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances",
- "Number of BVH instances traversed by camera rays"},
- {RENDER_PASS_DEBUG_BVH_INTERSECTIONS, "BVH_INTERSECTIONS", 0, "BVH Intersections",
- "Number of primitive intersections performed by the camera rays"},
- {RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps",
- "Number of bounces done by the main integration loop"},
- {0, NULL, 0, NULL, NULL}
-};
-
EnumPropertyItem rna_enum_bake_pass_type_items[] = {
{SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""},
{SCE_PASS_AO, "AO", 0, "AO", ""},
@@ -261,6 +251,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
RNA_parameter_list_free(&list);
}
+static void engine_update_render_passes(RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl)
+{
+ extern FunctionRNA rna_RenderEngine_update_render_passes_func;
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
+ func = &rna_RenderEngine_update_render_passes_func;
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "scene", &scene);
+ RNA_parameter_set_lookup(&list, "renderlayer", &srl);
+ engine->type->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
/* RenderEngine registration */
static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
@@ -281,7 +289,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
RenderEngineType *et, dummyet = {NULL};
RenderEngine dummyengine = {NULL};
PointerRNA dummyptr;
- int have_function[6];
+ int have_function[7];
/* setup dummy engine & engine type to store static properties in */
dummyengine.type = &dummyet;
@@ -323,6 +331,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
et->view_update = (have_function[3]) ? engine_view_update : NULL;
et->view_draw = (have_function[4]) ? engine_view_draw : NULL;
et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
+ et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL;
BLI_addtail(&R_engines, et);
@@ -419,6 +428,11 @@ static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, co
return RE_pass_find_by_type(rl, passtype, view);
}
+static RenderPass *rna_RenderPass_find_by_name(RenderLayer *rl, const char *name, const char *view)
+{
+ return RE_pass_find_by_name(rl, name, view);
+}
+
#else /* RNA_RUNTIME */
static void rna_def_render_engine(BlenderRNA *brna)
@@ -429,6 +443,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
FunctionRNA *func;
PropertyRNA *parm;
+ static EnumPropertyItem render_pass_type_items[] = {
+ {SOCK_FLOAT, "VALUE", 0, "Value", ""},
+ {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
+ {SOCK_RGBA, "COLOR", 0, "Color", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "RenderEngine", NULL);
RNA_def_struct_sdna(srna, "RenderEngine");
RNA_def_struct_ui_text(srna, "Render Engine", "Render engine");
@@ -497,6 +518,12 @@ static void rna_def_render_engine(BlenderRNA *brna)
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, "update_render_passes", NULL);
+ RNA_def_function_ui_description(func, "Update the render passes that will be generated");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "scene", "Scene", "", "");
+ parm = RNA_def_pointer(func, "renderlayer", "SceneRenderLayer", "", "");
+
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");
parm = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX);
@@ -522,8 +549,20 @@ static void rna_def_render_engine(BlenderRNA *brna)
parm = RNA_def_pointer(func, "result", "RenderResult", "Result", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't mark tile as done, don't merge results unless forced");
+ RNA_def_boolean(func, "highlight", 0, "Highlight", "Don't mark tile as done yet");
RNA_def_boolean(func, "do_merge_results", 0, "Merge Results", "Merge results even if cancel=true");
+ func = RNA_def_function(srna, "add_pass", "RE_engine_add_pass");
+ RNA_def_function_ui_description(func, "Add a pass to the render layer");
+ parm = RNA_def_string(func, "name", NULL, 0, "Name", "Name of the Pass, without view or channel tag");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_int(func, "channels", 0, 0, INT_MAX, "Channels", "", 0, INT_MAX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_string(func, "chan_id", NULL, 0, "Channel IDs", "Channel names, one character per channel");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_string(func, "layer", NULL, 0, "Layer", "Single layer to add render pass to"); /* NULL ok here */
+
+
func = RNA_def_function(srna, "test_break", "RE_engine_test_break");
RNA_def_function_ui_description(func, "Test if the render operation should been canceled, this is a fast call that should be used regularly for responsiveness");
parm = RNA_def_boolean(func, "do_break", 0, "Break", "");
@@ -646,6 +685,21 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_highlight_tiles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_HIGHLIGHT_TILES);
+ func = RNA_def_function(srna, "register_pass", "RE_engine_register_pass");
+ RNA_def_function_ui_description(func, "Register a render pass that will be part of the render with the current settings");
+ prop = RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ prop = RNA_def_pointer(func, "srl", "SceneRenderLayer", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ prop = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ prop = RNA_def_int(func, "channels", 1, 1, 8, "Channels", "", 1, 4);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ prop = RNA_def_string(func, "chanid", NULL, 8, "Channel IDs", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ prop = RNA_def_enum(func, "type", render_pass_type_items, SOCK_FLOAT, "Type", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
@@ -774,6 +828,15 @@ static void rna_def_render_passes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass");
RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "find_by_name", "rna_RenderPass_find_by_name");
+ RNA_def_function_ui_description(func, "Get the render pass for a given name and view");
+ parm = RNA_def_string(func, "name", RE_PASSNAME_COMBINED, 0, "Pass", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_string(func, "view", NULL, 0, "View", "Render view to get pass from"); /* NULL ok here */
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass");
+ RNA_def_function_return(func, parm);
}
static void rna_def_render_layer(BlenderRNA *brna)
@@ -822,6 +885,11 @@ static void rna_def_render_pass(BlenderRNA *brna)
RNA_define_verify_sdna(0);
+ prop = RNA_def_property(srna, "fullname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "fullname");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -835,11 +903,6 @@ static void rna_def_render_pass(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "channels");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "passtype");
- RNA_def_property_enum_items(prop, rna_enum_render_pass_type_items);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
prop = RNA_def_property(srna, "rect", PROP_FLOAT, PROP_NONE);
RNA_def_property_flag(prop, PROP_DYNAMIC);
RNA_def_property_multi_array(prop, 2, NULL);
@@ -850,11 +913,6 @@ static void rna_def_render_pass(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "view_id");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- prop = RNA_def_property(srna, "debug_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "debug_type");
- RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
RNA_define_verify_sdna(1);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 121e4f56a6e..b9231574a24 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -88,7 +88,8 @@ EnumPropertyItem rna_enum_exr_codec_items[] = {
{R_IMF_EXR_CODEC_B44, "B44", 0, "B44 (lossy)", ""},
{R_IMF_EXR_CODEC_B44A, "B44A", 0, "B44A (lossy)", ""},
{R_IMF_EXR_CODEC_DWAA, "DWAA", 0, "DWAA (lossy)", ""},
- {R_IMF_EXR_CODEC_DWAB, "DWAB", 0, "DWAB (lossy)", ""},
+ /* NOTE: Commented out for until new OpenEXR is released, see T50673. */
+ /* {R_IMF_EXR_CODEC_DWAB, "DWAB", 0, "DWAB (lossy)", ""}, */
{0, NULL, 0, NULL, NULL}
};
#endif
@@ -448,6 +449,7 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -1608,6 +1610,18 @@ static void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUS
#endif
}
+static IDProperty *rna_SceneRenderLayer_idprops(PointerRNA *ptr, bool create)
+{
+ SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data;
+
+ if (create && !srl->prop) {
+ IDPropertyTemplate val = {0};
+ srl->prop = IDP_New(IDP_GROUP, &val, "SceneRenderLayer ID properties");
+ }
+
+ return srl->prop;
+}
+
static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -1712,11 +1726,18 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po
Scene *scene = (Scene *)ptr->id.data;
if (scene->nodetree)
- ntreeCompositForceHidden(scene->nodetree);
-
+ ntreeCompositUpdateRLayers(scene->nodetree);
+
rna_Scene_glsl_update(bmain, activescene, ptr);
}
+static void rna_SceneRenderLayer_update_render_passes(ID *id)
+{
+ Scene *scene = (Scene *)id;
+ if (scene->nodetree)
+ ntreeCompositUpdateRLayers(scene->nodetree);
+}
+
static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
@@ -1795,7 +1816,7 @@ static void object_simplify_update(Object *ob)
}
}
-static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Scene_use_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Scene *sce = ptr->id.data;
Scene *sce_iter;
@@ -1806,6 +1827,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi
object_simplify_update(base->object);
WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
+ DAG_id_tag_update(&scene->id, 0);
}
static void rna_Scene_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -5072,14 +5094,20 @@ static void rna_def_scene_render_layer(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
srna = RNA_def_struct(brna, "SceneRenderLayer", NULL);
RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer");
RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path");
+ RNA_def_struct_idprops_func(srna, "rna_SceneRenderLayer_idprops");
rna_def_render_layer_common(srna, 1);
+ func = RNA_def_function(srna, "update_render_passes", "rna_SceneRenderLayer_update_render_passes");
+ RNA_def_function_ui_description(func, "Requery the enabled render passes from the render engine");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
+
/* Freestyle */
rna_def_freestyle_settings(brna);
@@ -5390,7 +5418,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "jpeg2k_codec", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "jp2_codec");
RNA_def_property_enum_items(prop, jp2_codec_items);
- RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpek2000");
+ RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpeg2000");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
#endif
@@ -6742,14 +6770,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "BakeSettings");
RNA_def_property_ui_text(prop, "Bake Data", "");
- /* Debugging settings. */
-#ifdef WITH_CYCLES_DEBUG
- prop = RNA_def_property(srna, "debug_pass_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items);
- RNA_def_property_ui_text(prop, "Debug Pass Type", "Type of the debug pass to use");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-#endif
-
/* Nestled Data */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
@@ -6968,7 +6988,7 @@ static void rna_def_display_safe_areas(BlenderRNA *brna)
RNA_def_property_array(prop, 2);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_array_default(prop, default_title);
- RNA_def_property_ui_text(prop, "Title Safe margins", "Safe area for text and graphics");
+ RNA_def_property_ui_text(prop, "Title Safe Margins", "Safe area for text and graphics");
RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
prop = RNA_def_property(srna, "action", PROP_FLOAT, PROP_XYZ);
@@ -6979,7 +6999,6 @@ static void rna_def_display_safe_areas(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Action Safe Margins", "Safe area for general elements");
RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL);
-
prop = RNA_def_property(srna, "title_center", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "title_center");
RNA_def_property_array(prop, 2);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index bb70f9dccd0..2619d231adc 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -208,6 +208,8 @@ static void rna_Scene_alembic_export(
int renderable_only,
int face_sets,
int use_subdiv_schema,
+ int export_hair,
+ int export_particles,
int compression_type,
int packuv,
float scale,
@@ -225,8 +227,8 @@ static void rna_Scene_alembic_export(
.frame_start = frame_start,
.frame_end = frame_end,
- .frame_step_xform = 1.0 / (double)xform_samples,
- .frame_step_shape = 1.0 / (double)geom_samples,
+ .frame_samples_xform = xform_samples,
+ .frame_samples_shape = geom_samples,
.shutter_open = shutter_open,
.shutter_close = shutter_close,
@@ -241,6 +243,8 @@ static void rna_Scene_alembic_export(
.renderable_only = renderable_only,
.face_sets = face_sets,
.use_subdiv_schema = use_subdiv_schema,
+ .export_hair = export_hair,
+ .export_particles = export_particles,
.compression_type = compression_type,
.packuv = packuv,
.triangulate = triangulate,
@@ -250,7 +254,7 @@ static void rna_Scene_alembic_export(
.global_scale = scale,
};
- ABC_export(scene, C, filepath, &params);
+ ABC_export(scene, C, filepath, &params, true);
#ifdef WITH_PYTHON
BPy_END_ALLOW_THREADS;
@@ -263,34 +267,55 @@ static void rna_Scene_alembic_export(
/* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
#include "../../collada/collada.h"
+/* Note: This definition must match to the generated function call */
static void rna_Scene_collada_export(
Scene *scene,
- const char *filepath,
+ const char *filepath,
int apply_modifiers,
- int export_mesh_type,
+ int export_mesh_type,
int selected,
int include_children,
int include_armatures,
int include_shapekeys,
int deform_bones_only,
-
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ int export_texture_type,
int use_texture_copies,
-
- int use_ngons,
+ int triangulate,
int use_object_instantiation,
int use_blender_profile,
int sort_by_name,
+ int export_transformation_type,
int open_sim,
- int export_transformation_type)
+ int limit_precision,
+ int keep_bind_info)
{
- collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected,
- include_children, include_armatures, include_shapekeys, deform_bones_only,
- active_uv_only, include_uv_textures, include_material_textures,
- use_texture_copies, use_ngons, use_object_instantiation, use_blender_profile, sort_by_name, export_transformation_type, open_sim);
+ collada_export(scene,
+ filepath,
+
+ apply_modifiers,
+ export_mesh_type,
+
+ selected,
+ include_children,
+ include_armatures,
+ include_shapekeys,
+ deform_bones_only,
+
+ active_uv_only,
+ export_texture_type,
+ use_texture_copies,
+
+ triangulate,
+ use_object_instantiation,
+ use_blender_profile,
+ sort_by_name,
+
+ export_transformation_type,
+ open_sim,
+ limit_precision,
+ keep_bind_info);
}
#endif
@@ -354,35 +379,64 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Collada file");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */
- RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers");
+
+ RNA_def_boolean(func, "apply_modifiers", false,
+ "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))");
+
RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
"Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
- RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements");
- RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)");
- RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)");
- RNA_def_boolean(func, "include_shapekeys", 0, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
- RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures");
-
- RNA_def_boolean(func, "active_uv_only", 0, "Active UV Layer only", "Export only the active UV Layer");
- RNA_def_boolean(func, "include_uv_textures", 0, "Include UV Textures", "Export textures assigned to the object UV maps");
- RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures", "Export textures assigned to the object Materials");
- RNA_def_boolean(func, "use_texture_copies", 0, "copy", "Copy textures to same folder where the .dae file is exported");
-
- RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export");
- RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data");
- RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile", "Export additional Blender specific information (for material, shaders, bones, etc.)");
- RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
- RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds");
+
+ RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
+
+ RNA_def_boolean(func, "include_children", false,
+ "Include Children", "Export all children of selected objects (even if not selected)");
+
+ RNA_def_boolean(func, "include_armatures", false,
+ "Include Armatures", "Export related armatures (even if not selected)");
+
+ RNA_def_boolean(func, "include_shapekeys", true, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
+
+ RNA_def_boolean(func, "deform_bones_only", false,
+ "Deform Bones only", "Only export deforming bones with armatures");
+
+ RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map");
+
+ RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
+ "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
+
+ RNA_def_boolean(func, "use_texture_copies", true,
+ "Copy", "Copy textures to same folder where the .dae file is exported");
+
+ RNA_def_boolean(func, "triangulate", true, "Triangulate", "Export Polygons (Quads & NGons) as Triangles");
+
+ RNA_def_boolean(func, "use_object_instantiation", true,
+ "Use Object Instances", "Instantiate multiple Objects from same Data");
+
+ RNA_def_boolean(func, "use_blender_profile", true, "Use Blender Profile",
+ "Export additional Blender specific information (for material, shaders, bones, etc.)");
+
+ RNA_def_boolean(func, "sort_by_name", false, "Sort by Object name", "Sort exported data by Object name");
RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
- "Transformation", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+ "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+
+ RNA_def_boolean(func, "open_sim", false,
+ "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds");
+
+ RNA_def_boolean(func, "limit_precision", false,
+ "Limit Precision",
+ "Reduce the precision of the exported data to 6 digits");
+
+ RNA_def_boolean(func, "keep_bind_info", false,
+ "Keep Bind Info",
+ "Store bind pose information in custom bone properties for later use during Collada export");
- RNA_def_function_ui_description(func, "Export to collada file");
#endif
#ifdef WITH_ALEMBIC
+ /* XXX Deprecated, will be removed in 2.8 in favour of calling the export operator. */
func = RNA_def_function(srna, "alembic_export", "rna_Scene_alembic_export");
- RNA_def_function_ui_description(func, "Export to Alembic file");
+ RNA_def_function_ui_description(func, "Export to Alembic file (deprecated, use the Alembic export operator)");
parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Alembic file");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
@@ -404,6 +458,8 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_boolean(func, "renderable_only" , 0, "Renderable objects only", "Export only objects marked renderable in the outliner");
RNA_def_boolean(func, "face_sets" , 0, "Facesets", "Export face sets");
RNA_def_boolean(func, "subdiv_schema", 0, "Use Alembic subdivision Schema", "Use Alembic subdivision Schema");
+ RNA_def_boolean(func, "export_hair", 1, "Export Hair", "Exports hair particle systems as animated curves");
+ RNA_def_boolean(func, "export_particles", 1, "Export Particles", "Exports non-hair particle systems");
RNA_def_enum(func, "compression_type", rna_enum_abc_compression_items, 0, "Compression", "");
RNA_def_boolean(func, "packuv" , 0, "Export with packed UV islands", "Export with packed UV islands");
RNA_def_float(func, "scale", 1.0f, 0.0001f, 1000.0f, "Scale", "Value by which to enlarge or shrink the objects with respect to the world's origin", 0.0001f, 1000.0f);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 3e6d8441363..6f8aa32da86 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1095,7 +1095,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_ui_text(prop, "Filename", "Name of the source file");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceElement_update");
prop = RNA_def_property(srna, "orig_width", PROP_INT, PROP_NONE);
@@ -1120,25 +1120,25 @@ static void rna_def_strip_crop(BlenderRNA *brna)
prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "top");
- RNA_def_property_ui_text(prop, "Top", "");
+ RNA_def_property_ui_text(prop, "Top", "Number of pixels to crop from the top");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "bottom");
- RNA_def_property_ui_text(prop, "Bottom", "");
+ RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the bottom");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "left");
- RNA_def_property_ui_text(prop, "Left", "");
+ RNA_def_property_ui_text(prop, "Left", "Number of pixels to crop from the left side");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "right");
- RNA_def_property_ui_text(prop, "Right", "");
+ RNA_def_property_ui_text(prop, "Right", "Number of pixels to crop from the right side");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
@@ -1156,13 +1156,13 @@ static void rna_def_strip_transform(BlenderRNA *brna)
prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "xofs");
- RNA_def_property_ui_text(prop, "Offset X", "");
+ RNA_def_property_ui_text(prop, "Offset X", "Amount to move the input on the X axis within its boundaries");
RNA_def_property_ui_range(prop, -4096, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update");
prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "yofs");
- RNA_def_property_ui_text(prop, "Offset Y", "");
+ RNA_def_property_ui_text(prop, "Offset Y", "Amount to move the input on the Y axis within its boundaries");
RNA_def_property_ui_range(prop, -4096, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update");
@@ -1246,7 +1246,7 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
prop = RNA_def_property(srna, "timecode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "tc");
RNA_def_property_enum_items(prop, seq_tc_items);
- RNA_def_property_ui_text(prop, "Timecode", "");
+ RNA_def_property_ui_text(prop, "Timecode", "Method for reading the inputs timecode");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_tcindex_update");
prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE);
@@ -1289,17 +1289,17 @@ static void rna_def_color_balance(BlenderRNA *brna)
prop = RNA_def_property(srna, "invert_gain", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAIN);
- RNA_def_property_ui_text(prop, "Inverse Gain", "");
+ RNA_def_property_ui_text(prop, "Inverse Gain", "Invert the gain color`");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
prop = RNA_def_property(srna, "invert_gamma", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAMMA);
- RNA_def_property_ui_text(prop, "Inverse Gamma", "");
+ RNA_def_property_ui_text(prop, "Inverse Gamma", "Invert the gamma color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
prop = RNA_def_property(srna, "invert_lift", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_LIFT);
- RNA_def_property_ui_text(prop, "Inverse Lift", "");
+ RNA_def_property_ui_text(prop, "Inverse Lift", "Invert the lift color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
/* not yet used */
@@ -1453,13 +1453,13 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MUTE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, true);
- RNA_def_property_ui_text(prop, "Mute", "");
+ RNA_def_property_ui_text(prop, "Mute", "Disable strip so that it cannot be viewed in the output");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_mute_update");
prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_LOCK);
RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true);
- RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it can't be transformed");
+ RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it cannot be transformed");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
/* strip positioning */
@@ -1481,7 +1481,7 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "start");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Start Frame", "");
+ RNA_def_property_ui_text(prop, "Start Frame", "X position where the strip begins");
RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_set", NULL); /* overlap tests and calc_seq_disp */
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -1552,12 +1552,12 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "blend_mode");
RNA_def_property_enum_items(prop, blend_mode_items);
- RNA_def_property_ui_text(prop, "Blend Mode", "");
+ RNA_def_property_ui_text(prop, "Blend Mode", "Method for controlling how the strip combines with other strips");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "blend_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Blend Opacity", "");
+ RNA_def_property_ui_text(prop, "Blend Opacity", "Percentage of how much the strip's colors affect other strips");
/* stupid 0-100 -> 0-1 */
RNA_def_property_float_funcs(prop, "rna_Sequence_opacity_get", "rna_Sequence_opacity_set", NULL);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -1566,7 +1566,7 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
RNA_def_property_float_sdna(prop, NULL, "effect_fader");
- RNA_def_property_ui_text(prop, "Effect fader position", "");
+ RNA_def_property_ui_text(prop, "Effect fader position", "Custom fade value");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "use_default_fade", PROP_BOOLEAN, PROP_NONE);
@@ -1714,7 +1714,7 @@ static void rna_def_filter_video(StructRNA *srna)
RNA_def_property_range(prop, 0.0f, 20.0f);
RNA_def_property_ui_range(prop, 0.0f, 2.0f, 3, 3);
RNA_def_property_float_default(prop, 1.0f);
- RNA_def_property_ui_text(prop, "Saturation", "");
+ RNA_def_property_ui_text(prop, "Saturation", "Adjust the intensity of the input's color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "strobe", PROP_FLOAT, PROP_NONE);
@@ -2205,13 +2205,13 @@ static void rna_def_transform(StructRNA *srna)
prop = RNA_def_property(srna, "scale_start_x", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "ScalexIni");
- RNA_def_property_ui_text(prop, "Scale X", "");
+ RNA_def_property_ui_text(prop, "Scale X", "Amount to scale the input in the X axis");
RNA_def_property_ui_range(prop, 0, 10, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "ScaleyIni");
- RNA_def_property_ui_text(prop, "Scale Y", "");
+ RNA_def_property_ui_text(prop, "Scale Y", "Amount to scale the input in the Y axis");
RNA_def_property_ui_range(prop, 0, 10, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -2222,33 +2222,33 @@ static void rna_def_transform(StructRNA *srna)
prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xIni");
- RNA_def_property_ui_text(prop, "Translate X", "");
+ RNA_def_property_ui_text(prop, "Translate X", "Amount to move the input on the X axis");
RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "yIni");
- RNA_def_property_ui_text(prop, "Translate Y", "");
+ RNA_def_property_ui_text(prop, "Translate Y", "Amount to move the input on the Y axis");
RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rotIni");
RNA_def_property_range(prop, -360.0f, 360.0f);
- RNA_def_property_ui_text(prop, "Rotation", "");
+ RNA_def_property_ui_text(prop, "Rotation", "Degrees to rotate the input");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "translation_unit", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "percent");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */
RNA_def_property_enum_items(prop, translation_unit_items);
- RNA_def_property_ui_text(prop, "Translation Unit", "");
+ RNA_def_property_ui_text(prop, "Translation Unit", "Unit of measure to translate the input");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, interpolation_items);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */
- RNA_def_property_ui_text(prop, "Interpolation", "");
+ RNA_def_property_ui_text(prop, "Interpolation", "Method to determine how missing pixels are created");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
@@ -2260,7 +2260,7 @@ static void rna_def_solid_color(StructRNA *srna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "col");
- RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_ui_text(prop, "Color", "Effect Strip color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
@@ -2333,7 +2333,7 @@ static void rna_def_text(StructRNA *srna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "color");
- RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_ui_text(prop, "Color", "Text color");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA);
@@ -2358,13 +2358,13 @@ static void rna_def_text(StructRNA *srna)
prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align");
RNA_def_property_enum_items(prop, text_align_x_items);
- RNA_def_property_ui_text(prop, "Align X", "");
+ RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align_y");
RNA_def_property_enum_items(prop, text_align_y_items);
- RNA_def_property_ui_text(prop, "Align Y", "");
+ RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
@@ -2512,7 +2512,7 @@ static void rna_def_colorbalance_modifier(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "color_multiply");
RNA_def_property_range(prop, 0.0f, 20.0f);
RNA_def_property_float_default(prop, 1.0f);
- RNA_def_property_ui_text(prop, "Multiply Colors", "");
+ RNA_def_property_ui_text(prop, "Multiply Colors", "Multiply the intensity of each pixel");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
}
@@ -2576,13 +2576,13 @@ static void rna_def_brightcontrast_modifier(BlenderRNA *brna)
prop = RNA_def_property(srna, "bright", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "bright");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
- RNA_def_property_ui_text(prop, "Bright", "");
+ RNA_def_property_ui_text(prop, "Bright", "Adjust the luminosity of the colors");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "contrast");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
- RNA_def_property_ui_text(prop, "Contrast", "");
+ RNA_def_property_ui_text(prop, "Contrast", "Adjust the difference in luminosity between pixels");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
}
@@ -2599,13 +2599,12 @@ static void rna_def_tonemap_modifier(BlenderRNA *brna)
srna = RNA_def_struct(brna, "SequencerTonemapModifierData", "SequenceModifier");
RNA_def_struct_sdna(srna, "SequencerTonemapModifierData");
- RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData",
- "Tone mapping modifier");
+ RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData", "Tone mapping modifier");
prop = RNA_def_property(srna, "tonemap_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, type_items);
- RNA_def_property_ui_text(prop, "Tonemap Type", "");
+ RNA_def_property_ui_text(prop, "Tonemap Type", "Tone mapping algorithm");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
prop = RNA_def_property(srna, "key", PROP_FLOAT, PROP_FACTOR);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 5e364a3adf1..f2e856bf1ba 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -71,10 +71,10 @@ EnumPropertyItem rna_enum_space_type_items[] = {
{SPACE_NLA, "NLA_EDITOR", ICON_NLA, "NLA Editor", "Combine and layer Actions"},
{0, "", ICON_NONE, NULL, NULL},
{SPACE_IMAGE, "IMAGE_EDITOR", ICON_IMAGE_COL, "UV/Image Editor", "View and edit images and UV Maps"},
- {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequence Editor", "Video editing tools"},
{SPACE_CLIP, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", "Motion tracking tools"},
- {SPACE_TEXT, "TEXT_EDITOR", ICON_TEXT, "Text Editor", "Edit scripts and in-file documentation"},
+ {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequence Editor", "Video editing tools"},
{SPACE_NODE, "NODE_EDITOR", ICON_NODETREE, "Node Editor", "Editor for node-based shading and compositing tools"},
+ {SPACE_TEXT, "TEXT_EDITOR", ICON_TEXT, "Text Editor", "Edit scripts and in-file documentation"},
{SPACE_LOGIC, "LOGIC_EDITOR", ICON_LOGIC, "Logic Editor", "Game logic editing"},
{0, "", ICON_NONE, NULL, NULL},
{SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"},
@@ -492,7 +492,7 @@ static void rna_View3D_CursorLocation_get(PointerRNA *ptr, float *values)
bScreen *sc = (bScreen *)ptr->id.data;
Scene *scene = (Scene *)sc->scene;
const float *loc = ED_view3d_cursor3d_get(scene, v3d);
-
+
copy_v3_v3(values, loc);
}
@@ -502,7 +502,7 @@ static void rna_View3D_CursorLocation_set(PointerRNA *ptr, const float *values)
bScreen *sc = (bScreen *)ptr->id.data;
Scene *scene = (Scene *)sc->scene;
float *cursor = ED_view3d_cursor3d_get(scene, v3d);
-
+
copy_v3_v3(cursor, values);
}
@@ -518,7 +518,7 @@ static float rna_View3D_GridScaleUnit_get(PointerRNA *ptr)
static void rna_SpaceView3D_layer_set(PointerRNA *ptr, const int *values)
{
View3D *v3d = (View3D *)(ptr->data);
-
+
v3d->lay = ED_view3d_scene_layer_set(v3d->lay, values, &v3d->layact);
}
@@ -545,16 +545,16 @@ static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *scene, Poi
static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
-
+
if (v3d->defmaterial) {
Material *ma = v3d->defmaterial;
-
+
if (ma->preview)
BKE_previewimg_free(&ma->preview);
-
+
if (ma->gpumaterial.first)
GPU_material_free(&ma->gpumaterial);
-
+
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
}
}
@@ -562,7 +562,7 @@ static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(sce
static void rna_SpaceView3D_matcap_enable(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
-
+
if (v3d->matcap_icon < ICON_MATCAP_01 ||
v3d->matcap_icon > ICON_MATCAP_24)
{
@@ -719,7 +719,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C
{
Scene *scene = ((bScreen *)ptr->id.data)->scene;
RenderEngineType *type = RE_engines_find(scene->r.engine);
-
+
EnumPropertyItem *item = NULL;
int totitem = 0;
@@ -728,7 +728,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C
RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_SOLID);
RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_TEXTURE);
RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_MATERIAL);
-
+
if (type && type->view_draw)
RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_RENDER);
@@ -844,7 +844,7 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *UNUS
int zbuf, alpha, totitem = 0;
ibuf = ED_space_image_acquire_buffer(sima, &lock);
-
+
alpha = ibuf && (ibuf->channels == 4);
zbuf = ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1));
@@ -895,14 +895,14 @@ static void rna_SpaceImageEditor_zoom_get(PointerRNA *ptr, float *values)
static void rna_SpaceImageEditor_cursor_location_get(PointerRNA *ptr, float *values)
{
SpaceImage *sima = (SpaceImage *)ptr->data;
-
+
if (sima->flag & SI_COORDFLOATS) {
copy_v2_v2(values, sima->cursor);
}
else {
int w, h;
ED_space_image_get_size(sima, &w, &h);
-
+
values[0] = sima->cursor[0] * w;
values[1] = sima->cursor[1] * h;
}
@@ -911,14 +911,14 @@ static void rna_SpaceImageEditor_cursor_location_get(PointerRNA *ptr, float *val
static void rna_SpaceImageEditor_cursor_location_set(PointerRNA *ptr, const float *values)
{
SpaceImage *sima = (SpaceImage *)ptr->data;
-
+
if (sima->flag & SI_COORDFLOATS) {
copy_v2_v2(sima->cursor, values);
}
else {
int w, h;
ED_space_image_get_size(sima, &w, &h);
-
+
sima->cursor[0] = values[0] / w;
sima->cursor[1] = values[1] / h;
}
@@ -947,7 +947,7 @@ static void rna_SpaceImageEditor_scopes_update(struct bContext *C, struct Pointe
SpaceImage *sima = (SpaceImage *)ptr->data;
ImBuf *ibuf;
void *lock;
-
+
ibuf = ED_space_image_acquire_buffer(sima, &lock);
if (ibuf) {
ED_space_image_scopes_update(C, sima, ibuf, true);
@@ -1026,12 +1026,12 @@ static void rna_SpaceProperties_pin_id_update(Main *UNUSED(bmain), Scene *UNUSED
{
SpaceButs *sbuts = (SpaceButs *)(ptr->data);
ID *id = sbuts->pinid;
-
+
if (id == NULL) {
sbuts->flag &= ~SB_PIN_CONTEXT;
return;
}
-
+
switch (GS(id->name)) {
case ID_MA:
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
@@ -1052,7 +1052,7 @@ static void rna_SpaceProperties_pin_id_update(Main *UNUSED(bmain), Scene *UNUSED
static void rna_SpaceProperties_context_set(PointerRNA *ptr, int value)
{
SpaceButs *sbuts = (SpaceButs *)(ptr->data);
-
+
sbuts->mainb = value;
sbuts->mainbuser = value;
}
@@ -1130,7 +1130,8 @@ static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSED(C),
static void rna_SpaceProperties_context_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
SpaceButs *sbuts = (SpaceButs *)(ptr->data);
- if (ELEM(sbuts->mainb, BCONTEXT_WORLD, BCONTEXT_MATERIAL, BCONTEXT_TEXTURE)) {
+ /* XXX BCONTEXT_DATA is ugly, but required for lamps... See T51318. */
+ if (ELEM(sbuts->mainb, BCONTEXT_WORLD, BCONTEXT_MATERIAL, BCONTEXT_TEXTURE, BCONTEXT_DATA)) {
sbuts->preview = 1;
}
}
@@ -1203,7 +1204,7 @@ static void rna_ConsoleLine_body_set(PointerRNA *ptr, const char *value)
{
ConsoleLine *ci = (ConsoleLine *)ptr->data;
int len = strlen(value);
-
+
if ((len >= ci->len_alloc) || (len * 2 < ci->len_alloc) ) { /* allocate a new string */
MEM_freeN(ci->line);
ci->line = MEM_mallocN((len + 1) * sizeof(char), "rna_consoleline");
@@ -1231,7 +1232,7 @@ static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr, PointerRNA valu
{
SpaceAction *saction = (SpaceAction *)(ptr->data);
bAction *act = (bAction *)value.data;
-
+
if ((act == NULL) || (act->idroot == 0)) {
/* just set if we're clearing the action or if the action is "amorphous" still */
saction->action = act;
@@ -1268,7 +1269,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po
/* we must set this action to be the one used by active object (if not pinned) */
if (obact /* && saction->pin == 0*/) {
AnimData *adt = NULL;
-
+
if (saction->mode == SACTCONT_ACTION) {
/* TODO: context selector could help decide this with more control? */
adt = BKE_animdata_add_id(&obact->id); /* this only adds if non-existent */
@@ -1278,7 +1279,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po
if (key)
adt = BKE_animdata_add_id(&key->id); /* this only adds if non-existent */
}
-
+
/* set action */
// FIXME: this overlaps a lot with the BKE_animdata_set_action() API method
if (adt) {
@@ -1286,11 +1287,11 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po
if (adt->action != saction->action) {
/* NLA Tweak Mode needs special handling... */
if (adt->flag & ADT_NLA_EDIT_ON) {
- /* Exit editmode first - we cannot change actions while in tweakmode
+ /* Exit editmode first - we cannot change actions while in tweakmode
* NOTE: This will clear the action ref properly
*/
BKE_nla_tweakmode_exit(adt);
-
+
/* Assign new action, and adjust the usercounts accordingly */
adt->action = saction->action;
id_us_plus((ID *)adt->action);
@@ -1300,7 +1301,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po
if (adt->action) {
/* Fix id-count of action we're replacing */
id_us_min(&adt->action->id);
-
+
/* To prevent data loss (i.e. if users flip between actions using the Browse menu),
* stash this action if nothing else uses it.
*
@@ -1317,17 +1318,17 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po
BKE_nla_action_stash(adt);
}
}
-
+
/* Assign new action, and adjust the usercounts accordingly */
adt->action = saction->action;
id_us_plus((ID *)adt->action);
}
}
-
+
/* Force update of animdata */
adt->recalc |= ADT_RECALC_ANIM;
}
-
+
/* force depsgraph flush too */
DAG_id_tag_update(&obact->id, OB_RECALC_OB | OB_RECALC_DATA);
/* Update relations as well, so new time source dependency is added. */
@@ -1339,17 +1340,17 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce
{
SpaceAction *saction = (SpaceAction *)(ptr->data);
Object *obact = (scene->basact) ? scene->basact->object : NULL;
-
+
/* special exceptions for ShapeKey Editor mode */
if (saction->mode == SACTCONT_SHAPEKEY) {
Key *key = BKE_key_from_object(obact);
-
+
/* 1) update the action stored for the editor */
if (key)
saction->action = (key->adt) ? key->adt->action : NULL;
else
saction->action = NULL;
-
+
/* 2) enable 'show sliders' by default, since one of the main
* points of the ShapeKey Editor is to provide a one-stop shop
* for controlling the shapekeys, whose main control is the value
@@ -1365,7 +1366,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce
else
saction->action = NULL;
}
-
+
/* recalculate extents of channel list */
saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
}
@@ -1375,7 +1376,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce
static void rna_SpaceGraphEditor_display_mode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ScrArea *sa = rna_area_from_space(ptr);
-
+
/* after changing view mode, must force recalculation of F-Curve colors
* which can only be achieved using refresh as opposed to redraw
*/
@@ -1465,7 +1466,7 @@ static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, const PointerRNA
{
SpaceNode *snode = (SpaceNode *)ptr->data;
bNodeTree *ntree = (bNodeTree *)value.data;
-
+
/* node tree type must match the selected type in node editor */
return (STREQ(snode->tree_idname, ntree->idname));
}
@@ -1544,7 +1545,7 @@ static void rna_SpaceNodeEditor_show_backdrop_update(Main *UNUSED(bmain), Scene
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;
@@ -1896,12 +1897,12 @@ static void rna_def_space(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "Space", NULL);
RNA_def_struct_sdna(srna, "SpaceLink");
RNA_def_struct_ui_text(srna, "Space", "Space data for a screen area");
RNA_def_struct_refine_func(srna, "rna_Space_refine");
-
+
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "spacetype");
RNA_def_property_enum_items(prop, rna_enum_space_type_items);
@@ -2102,28 +2103,28 @@ static void rna_def_space_outliner(BlenderRNA *brna)
"Display data-blocks which are unused and/or will be lost when the file is reloaded"},
{0, NULL, 0, NULL, NULL}
};
-
+
srna = RNA_def_struct(brna, "SpaceOutliner", "Space");
RNA_def_struct_sdna(srna, "SpaceOops");
RNA_def_struct_ui_text(srna, "Space Outliner", "Outliner space data");
-
+
prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "outlinevis");
RNA_def_property_enum_items(prop, display_mode_items);
RNA_def_property_ui_text(prop, "Display Mode", "Type of information to display");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
+
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "search_string");
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");
RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
+
prop = RNA_def_property(srna, "use_filter_case_sensitive", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_CASE_SENSITIVE);
RNA_def_property_ui_text(prop, "Case Sensitive Matches Only", "Only use case sensitive matches of search string");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
+
prop = RNA_def_property(srna, "use_filter_complete", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_COMPLETE);
RNA_def_property_ui_text(prop, "Complete Matches Only", "Only use complete matches of search string");
@@ -2219,17 +2220,17 @@ static void rna_def_background_image(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "cuser");
RNA_def_property_ui_text(prop, "Clip User", "Parameters defining which frame of the movie clip is displayed");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xof");
RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally from the world origin");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "yof");
RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the world origin");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "size");
RNA_def_property_float_funcs(prop, "rna_BackgroundImage_size_get", "rna_BackgroundImage_size_set", NULL);
@@ -2349,7 +2350,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{RV3D_CAMOB, "CAMERA", 0, "Camera", ""},
{0, NULL, 0, NULL, NULL}
};
-
+
static EnumPropertyItem bundle_drawtype_items[] = {
{OB_PLAINAXES, "PLAIN_AXES", 0, "Plain Axes", ""},
{OB_ARROWS, "ARROWS", 0, "Arrows", ""},
@@ -2360,7 +2361,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{OB_EMPTY_CONE, "CONE", 0, "Cone", ""},
{0, NULL, 0, NULL, NULL}
};
-
+
static EnumPropertyItem view3d_matcap_items[] = {
{ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
{ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
@@ -2388,11 +2389,11 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
{0, NULL, 0, NULL, NULL}
};
-
+
srna = RNA_def_struct(brna, "SpaceView3D", "Space");
RNA_def_struct_sdna(srna, "View3D");
RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data");
-
+
prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_sdna(prop, NULL, "camera");
@@ -2437,7 +2438,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "ob_centre");
RNA_def_property_ui_text(prop, "Lock to Object", "3D View center is locked to this object's position");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "lock_bone", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "ob_centre_bone");
RNA_def_property_ui_text(prop, "Lock to Bone", "3D View center is locked to this bone's position");
@@ -2460,7 +2461,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "localvd");
RNA_def_property_ui_text(prop, "Local View",
"Display an isolated sub-set of objects, apart from the scene visibility");
-
+
prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ_LENGTH);
RNA_def_property_array(prop, 3);
RNA_def_property_float_funcs(prop, "rna_View3D_CursorLocation_get", "rna_View3D_CursorLocation_set", NULL);
@@ -2468,13 +2469,13 @@ static void rna_def_space_view3d(BlenderRNA *brna)
"3D cursor location for this view (dependent on local view setting)");
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_UNIT_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "lens");
RNA_def_property_ui_text(prop, "Lens", "Viewport lens angle");
RNA_def_property_range(prop, 1.0f, 250.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "near");
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
@@ -2505,7 +2506,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_range(prop, 0, 1024);
RNA_def_property_int_default(prop, 16);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "grid_subdivisions", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gridsubdiv");
RNA_def_property_ui_text(prop, "Grid Subdivisions", "Number of subdivisions between grid lines");
@@ -2522,28 +2523,28 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_FLOOR);
RNA_def_property_ui_text(prop, "Display Grid Floor", "Show the ground plane grid in perspective view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "show_axis_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_X);
RNA_def_property_ui_text(prop, "Display X Axis", "Show the X axis line in perspective view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "show_axis_y", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_Y);
RNA_def_property_ui_text(prop, "Display Y Axis", "Show the Y axis line in perspective view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "show_axis_z", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_Z);
RNA_def_property_ui_text(prop, "Display Z Axis", "Show the Z axis line in perspective view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "show_outline_selected", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SELECT_OUTLINE);
RNA_def_property_ui_text(prop, "Outline Selected",
"Show an outline highlight around selected objects in non-wireframe views");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "show_all_objects_origin", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_DRAW_CENTERS);
RNA_def_property_ui_text(prop, "All Object Origins",
@@ -2555,7 +2556,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Relationship Lines",
"Show dashed lines indicating parent or constraint relationships");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SHOW_GPENCIL);
RNA_def_property_ui_text(prop, "Show Grease Pencil",
@@ -2591,7 +2592,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_RENDER_OVERRIDE);
RNA_def_property_ui_text(prop, "Only Render", "Display only objects which will be rendered");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "show_world", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag3", V3D_SHOW_WORLD);
RNA_def_property_ui_text(prop, "World Background", "Display world colors in the background");
@@ -2621,7 +2622,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_enum_items(prop, pivot_items_full);
RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_pivot_update");
-
+
prop = RNA_def_property(srna, "use_pivot_point_align", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_ALIGN);
RNA_def_property_ui_text(prop, "Align", "Manipulate center points (object, pose and weight paint mode only)");
@@ -2640,7 +2641,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Transform Manipulators", "Transformation manipulators");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
prop = RNA_def_property(srna, "transform_orientation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "twmode");
RNA_def_property_enum_items(prop, transform_orientation_items);
@@ -2678,7 +2679,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_array(prop, 8);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Local View Layers", "Local view layers visible in this 3D View");
-
+
prop = RNA_def_property(srna, "layers_used", PROP_BOOLEAN, PROP_LAYER_MEMBER);
RNA_def_property_boolean_sdna(prop, NULL, "lay_used", 1);
RNA_def_property_array(prop, 20);
@@ -2730,7 +2731,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SOLID_MATCAP);
RNA_def_property_ui_text(prop, "Matcap", "Active Objects draw images mapped on normals, enhancing Solid Draw Mode");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_enable");
-
+
prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "matcap_icon");
RNA_def_property_enum_items(prop, view3d_matcap_items);
@@ -2793,17 +2794,17 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_LOCKED);
RNA_def_property_ui_text(prop, "Lock", "Lock view rotation in side views");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_RegionView3D_quadview_update");
-
+
prop = RNA_def_property(srna, "show_sync_view", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_BOXVIEW);
RNA_def_property_ui_text(prop, "Box", "Sync view position between side views");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_RegionView3D_quadview_update");
-
+
prop = RNA_def_property(srna, "use_box_clip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_BOXCLIP);
RNA_def_property_ui_text(prop, "Clip", "Clip objects based on what's visible in other side views");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_RegionView3D_quadview_clip_update");
-
+
prop = RNA_def_property(srna, "perspective_matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "persmat");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */
@@ -2816,7 +2817,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_ui_text(prop, "Window Matrix", "Current window matrix");
-
+
prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "viewmat");
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
@@ -2834,7 +2835,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "is_persp", 1);
RNA_def_property_ui_text(prop, "Is Perspective", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
-
+
prop = RNA_def_property(srna, "view_location", PROP_FLOAT, PROP_TRANSLATION);
#if 0
RNA_def_property_float_sdna(prop, NULL, "ofs"); /* cant use because its negated */
@@ -2846,7 +2847,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "View Location", "View pivot location");
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_WINDOW, NULL);
-
+
prop = RNA_def_property(srna, "view_rotation", PROP_FLOAT, PROP_QUATERNION); /* cant use because its inverted */
#if 0
RNA_def_property_float_sdna(prop, NULL, "viewquat");
@@ -2857,7 +2858,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
#endif
RNA_def_property_ui_text(prop, "View Rotation", "Rotation in quaternions (keep normalized)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
+
/* not sure we need rna access to these but adding anyway */
prop = RNA_def_property(srna, "view_distance", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "dist");
@@ -2893,14 +2894,14 @@ static void rna_def_space_buttons(BlenderRNA *brna)
srna = RNA_def_struct(brna, "SpaceProperties", "Space");
RNA_def_struct_sdna(srna, "SpaceButs");
RNA_def_struct_ui_text(srna, "Properties Space", "Properties space data");
-
+
prop = RNA_def_property(srna, "context", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mainb");
RNA_def_property_enum_items(prop, buttons_context_items);
RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_context_set", "rna_SpaceProperties_context_itemf");
RNA_def_property_ui_text(prop, "Context", "Type of active data to display and edit");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_SpaceProperties_context_update");
-
+
prop = RNA_def_property(srna, "align", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align");
RNA_def_property_enum_items(prop, align_items);
@@ -2988,7 +2989,7 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_SpaceImageEditor_zoom_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Zoom", "Zoom factor");
-
+
/* image draw */
prop = RNA_def_property(srna, "show_repeat", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_TILE);
@@ -3020,7 +3021,7 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SpaceUVEditor");
RNA_def_property_pointer_funcs(prop, "rna_SpaceImageEditor_uvedit_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "UV Editor", "UV editor settings");
-
+
/* mode */
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
@@ -3050,7 +3051,7 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
-
+
/* update */
prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "lock", 0);
@@ -3089,7 +3090,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
static EnumPropertyItem view_type_items[] = {
{SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""},
{SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""},
@@ -3143,7 +3144,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
srna = RNA_def_struct(brna, "SpaceSequenceEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceSeq");
RNA_def_struct_ui_text(srna, "Space Sequence Editor", "Sequence editor space data");
-
+
/* view type, fairly important */
prop = RNA_def_property(srna, "view_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "view");
@@ -3164,17 +3165,17 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Frame Number Indicator",
"Show frame number beside the current frame indicator line");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
prop = RNA_def_property(srna, "show_frames", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES);
RNA_def_property_ui_text(prop, "Draw Frames", "Draw frames rather than seconds");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
prop = RNA_def_property(srna, "use_marker_sync", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MARKER_TRANS);
RNA_def_property_ui_text(prop, "Sync Markers", "Transform markers as well as strips");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
prop = RNA_def_property(srna, "show_separate_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_DRAW_COLOR_SEPARATED);
RNA_def_property_ui_text(prop, "Separate Colors", "Separate color channels in preview");
@@ -3199,7 +3200,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES);
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_GPENCIL);
RNA_def_property_ui_text(prop, "Show Grease Pencil",
@@ -3230,14 +3231,14 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Overexposed", "Show overexposed areas with zebra stripes");
RNA_def_property_range(prop, 0, 110);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
prop = RNA_def_property(srna, "proxy_render_size", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "render_size");
RNA_def_property_enum_items(prop, proxy_render_size_items);
RNA_def_property_ui_text(prop, "Proxy render size",
"Draw preview using full resolution or different proxy resolutions");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
/* grease pencil */
prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
@@ -3298,7 +3299,7 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Syntax Highlight", "Syntax highlight for scripting");
RNA_def_property_ui_icon(prop, ICON_SYNTAX_OFF, 1);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
-
+
prop = RNA_def_property(srna, "show_line_highlight", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "line_hlight", 0);
RNA_def_property_ui_text(prop, "Highlight Line", "Highlight the current line");
@@ -3343,12 +3344,12 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "overwrite", 1);
RNA_def_property_ui_text(prop, "Overwrite", "Overwrite characters when typing rather than inserting them");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
-
+
prop = RNA_def_property(srna, "use_live_edit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "live_edit", 1);
RNA_def_property_ui_text(prop, "Live Edit", "Run python while editing");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL);
-
+
/* find */
prop = RNA_def_property(srna, "use_find_all", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", ST_FIND_ALL);
@@ -3382,7 +3383,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
/* XXX: action-editor is currently for object-level only actions, so show that using object-icon hint */
static EnumPropertyItem mode_items[] = {
{SACTCONT_DOPESHEET, "DOPESHEET", ICON_OOPS, "Dope Sheet", "Edit all keyframes in scene"},
@@ -3393,8 +3394,8 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
{SACTCONT_CACHEFILE, "CACHEFILE", ICON_FILE, "Cache File", "Edit timings for Cache File data-blocks"},
{0, NULL, 0, NULL, NULL}
};
-
-
+
+
srna = RNA_def_struct(brna, "SpaceDopeSheetEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceAction");
RNA_def_struct_ui_text(srna, "Space Dope Sheet Editor", "Dope Sheet space data");
@@ -3406,51 +3407,51 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
"rna_Action_actedit_assign_poll");
RNA_def_property_ui_text(prop, "Action", "Action displayed and edited in this space");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_SpaceDopeSheetEditor_action_update");
-
+
/* mode */
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, "rna_SpaceDopeSheetEditor_mode_update");
-
+
/* display */
prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_DRAWTIME);
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
-
+
prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWCFRANUM);
RNA_def_property_ui_text(prop, "Show Frame Number Indicator",
"Show frame number beside the current frame indicator line");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
-
+
prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SLIDERS);
RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
-
+
prop = RNA_def_property(srna, "show_pose_markers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_POSEMARKERS_SHOW);
RNA_def_property_ui_text(prop, "Show Pose Markers",
"Show markers belonging to the active action instead of Scene markers "
"(Action and Shape Key Editors only)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
-
+
prop = RNA_def_property(srna, "show_group_colors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWGCOLORS);
RNA_def_property_ui_text(prop, "Show Group Colors",
"Draw groups and channels with colors matching their corresponding groups "
"(pose bones only currently)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
-
+
/* editing */
prop = RNA_def_property(srna, "use_auto_merge_keyframes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NOTRANSKEYCULL);
RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Automatically merge nearby keyframes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
-
+
prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NOREALTIMEUPDATES);
RNA_def_property_ui_text(prop, "Realtime Updates",
@@ -3479,14 +3480,14 @@ static void rna_def_space_graph(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
static EnumPropertyItem mode_items[] = {
{SIPO_MODE_ANIMATION, "FCURVES", ICON_IPO, "F-Curve",
"Edit animation/keyframes displayed as 2D curves"},
{SIPO_MODE_DRIVERS, "DRIVERS", ICON_DRIVER, "Drivers", "Edit drivers"},
{0, NULL, 0, NULL, NULL}
};
-
+
/* this is basically the same as the one for the 3D-View, but with some entries omitted */
static EnumPropertyItem gpivot_items[] = {
{V3D_AROUND_CENTER_BOUNDS, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", ""},
@@ -3497,93 +3498,93 @@ static void rna_def_space_graph(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
-
+
srna = RNA_def_struct(brna, "SpaceGraphEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceIpo");
RNA_def_struct_ui_text(srna, "Space Graph Editor", "Graph Editor space data");
-
+
/* mode */
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, "rna_SpaceGraphEditor_display_mode_update");
-
+
/* display */
prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_DRAWTIME);
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCFRANUM);
RNA_def_property_ui_text(prop, "Show Frame Number Indicator",
"Show frame number beside the current frame indicator line");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SLIDERS);
RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "show_handles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOHANDLES);
RNA_def_property_ui_text(prop, "Show Handles", "Show handles of Bezier control points");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "use_only_selected_curves_handles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SELCUVERTSONLY);
RNA_def_property_ui_text(prop, "Only Selected Curve Keyframes",
"Only keyframes of selected F-Curves are visible and editable");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "use_only_selected_keyframe_handles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SELVHANDLESONLY);
RNA_def_property_ui_text(prop, "Only Selected Keyframes Handles",
"Only show and edit handles of selected keyframes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "use_beauty_drawing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_BEAUTYDRAW_OFF);
RNA_def_property_ui_text(prop, "Use High Quality Drawing",
"Draw F-Curves using Anti-Aliasing and other fancy effects "
"(disable for better performance)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "show_group_colors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWGCOLORS);
RNA_def_property_ui_text(prop, "Show Group Colors",
"Draw groups and channels with colors matching their corresponding groups");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
/* editing */
prop = RNA_def_property(srna, "use_auto_merge_keyframes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOTRANSKEYCULL);
RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Automatically merge nearby keyframes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOREALTIMEUPDATES);
RNA_def_property_ui_text(prop, "Realtime Updates",
"When transforming keyframes, changes to the animation data are flushed to other views");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
/* cursor */
prop = RNA_def_property(srna, "show_cursor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCURSOR);
RNA_def_property_ui_text(prop, "Show Cursor", "Show 2D cursor");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "cursor_position_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "cursorTime");
RNA_def_property_ui_text(prop, "Cursor X-Value", "Graph Editor 2D-Value cursor - X-Value component");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "cursor_position_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "cursorVal");
RNA_def_property_ui_text(prop, "Cursor Y-Value", "Graph Editor 2D-Value cursor - Y-Value component");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
+
prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "around");
RNA_def_property_enum_items(prop, gpivot_items);
@@ -3627,34 +3628,34 @@ static void rna_def_space_nla(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "SpaceNLA", "Space");
RNA_def_struct_sdna(srna, "SpaceNla");
RNA_def_struct_ui_text(srna, "Space Nla Editor", "NLA editor space data");
-
+
/* display */
prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_DRAWTIME);
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL);
-
+
prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM);
RNA_def_property_ui_text(prop, "Show Frame Number Indicator",
"Show frame number beside the current frame indicator line");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL);
-
+
prop = RNA_def_property(srna, "show_strip_curves", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOSTRIPCURVES);
RNA_def_property_ui_text(prop, "Show Control F-Curves", "Show influence F-Curves on strips");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL);
-
+
prop = RNA_def_property(srna, "show_local_markers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOLOCALMARKERS);
RNA_def_property_ui_text(prop, "Show Local Markers",
"Show action-local markers on the strips, useful when synchronizing timing across strips");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL);
-
+
/* editing */
prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOREALTIMEUPDATES);
@@ -3680,54 +3681,54 @@ static void rna_def_space_time(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "SpaceTimeline", "Space");
RNA_def_struct_sdna(srna, "SpaceTime");
RNA_def_struct_ui_text(srna, "Space Timeline Editor", "Timeline editor space data");
-
+
/* view settings */
prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", TIME_CFRA_NUM);
RNA_def_property_ui_text(prop, "Show Frame Number Indicator",
"Show frame number beside the current frame indicator line");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", TIME_DRAWFRAMES);
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
/* displaying cache status */
prop = RNA_def_property(srna, "show_cache", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DISPLAY);
RNA_def_property_ui_text(prop, "Show Cache", "Show the status of cached frames in the timeline");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
prop = RNA_def_property(srna, "cache_softbody", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_SOFTBODY);
RNA_def_property_ui_text(prop, "Softbody", "Show the active object's softbody point cache");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
prop = RNA_def_property(srna, "cache_particles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_PARTICLES);
RNA_def_property_ui_text(prop, "Particles", "Show the active object's particle point cache");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
prop = RNA_def_property(srna, "cache_cloth", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_CLOTH);
RNA_def_property_ui_text(prop, "Cloth", "Show the active object's cloth point cache");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
prop = RNA_def_property(srna, "cache_smoke", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_SMOKE);
RNA_def_property_ui_text(prop, "Smoke", "Show the active object's smoke cache");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
prop = RNA_def_property(srna, "cache_dynamicpaint", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DYNAMICPAINT);
RNA_def_property_ui_text(prop, "Dynamic Paint", "Show the active object's Dynamic Paint cache");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
+
prop = RNA_def_property(srna, "cache_rigidbody", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_RIGIDBODY);
RNA_def_property_ui_text(prop, "Rigid Body", "Show the active object's Rigid Body cache");
@@ -3746,17 +3747,17 @@ static void rna_def_console_line(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "ConsoleLine", NULL);
RNA_def_struct_ui_text(srna, "Console Input", "Input line for the interactive console");
-
+
prop = RNA_def_property(srna, "body", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ConsoleLine_body_get", "rna_ConsoleLine_body_length",
"rna_ConsoleLine_body_set");
RNA_def_property_ui_text(prop, "Line", "Text in the line");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL);
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
-
+
prop = RNA_def_property(srna, "current_character", PROP_INT, PROP_NONE); /* copied from text editor */
RNA_def_property_int_sdna(prop, NULL, "cursor");
RNA_def_property_int_funcs(prop, NULL, NULL, "rna_ConsoleLine_cursor_index_range");
@@ -3767,16 +3768,16 @@ static void rna_def_console_line(BlenderRNA *brna)
RNA_def_property_enum_items(prop, console_line_type_items);
RNA_def_property_ui_text(prop, "Type", "Console line type when used in scrollback");
}
-
+
static void rna_def_space_console(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "SpaceConsole", "Space");
RNA_def_struct_sdna(srna, "SpaceConsole");
RNA_def_struct_ui_text(srna, "Space Console", "Interactive python console");
-
+
/* display */
prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_NONE); /* copied from text editor */
RNA_def_property_int_sdna(prop, NULL, "lheight");
@@ -3788,14 +3789,14 @@ static void rna_def_space_console(BlenderRNA *brna)
prop = RNA_def_property(srna, "select_start", PROP_INT, PROP_UNSIGNED); /* copied from text editor */
RNA_def_property_int_sdna(prop, NULL, "sel_start");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL);
-
+
prop = RNA_def_property(srna, "select_end", PROP_INT, PROP_UNSIGNED); /* copied from text editor */
RNA_def_property_int_sdna(prop, NULL, "sel_end");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL);
prop = RNA_def_property(srna, "prompt", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Prompt", "Command line prompt");
-
+
prop = RNA_def_property(srna, "language", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Language", "Command line prompt language");
@@ -3803,7 +3804,7 @@ static void rna_def_space_console(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "history", NULL);
RNA_def_property_struct_type(prop, "ConsoleLine");
RNA_def_property_ui_text(prop, "History", "Command history");
-
+
prop = RNA_def_property(srna, "scrollback", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "scrollback", NULL);
RNA_def_property_struct_type(prop, "ConsoleLine");
@@ -3814,7 +3815,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
static EnumPropertyItem file_display_items[] = {
{FILE_SHORTDISPLAY, "LIST_SHORT", ICON_SHORTDISPLAY, "Short List", "Display files as short list"},
{FILE_LONGDISPLAY, "LIST_LONG", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"},
@@ -4078,7 +4079,7 @@ static void rna_def_space_filebrowser(BlenderRNA *brna)
prop = RNA_def_property(srna, "params", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "params");
RNA_def_property_ui_text(prop, "Filebrowser Parameter", "Parameters and Settings for the Filebrowser");
-
+
prop = RNA_def_property(srna, "active_operator", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "op");
RNA_def_property_ui_text(prop, "Active Operator", "");
@@ -4159,28 +4160,28 @@ static void rna_def_space_info(BlenderRNA *brna)
srna = RNA_def_struct(brna, "SpaceInfo", "Space");
RNA_def_struct_sdna(srna, "SpaceInfo");
RNA_def_struct_ui_text(srna, "Space Info", "Info space data");
-
+
/* reporting display */
prop = RNA_def_property(srna, "show_report_debug", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_DEBUG);
RNA_def_property_ui_text(prop, "Show Debug", "Display debug reporting info");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
-
+
prop = RNA_def_property(srna, "show_report_info", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_INFO);
RNA_def_property_ui_text(prop, "Show Info", "Display general information");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
-
+
prop = RNA_def_property(srna, "show_report_operator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_OP);
RNA_def_property_ui_text(prop, "Show Operator", "Display the operator log");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
-
+
prop = RNA_def_property(srna, "show_report_warning", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_WARN);
RNA_def_property_ui_text(prop, "Show Warn", "Display warnings");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
-
+
prop = RNA_def_property(srna, "show_report_error", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_ERR);
RNA_def_property_ui_text(prop, "Show Error", "Display error text");
@@ -4196,7 +4197,7 @@ static void rna_def_space_userpref(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "SpaceUserPreferences", "Space");
RNA_def_struct_sdna(srna, "SpaceUserPref");
RNA_def_struct_ui_text(srna, "Space User Preferences", "User preferences space data");
@@ -4218,7 +4219,7 @@ static void rna_def_node_tree_path(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
srna = RNA_def_struct(brna, "NodeTreePath", NULL);
RNA_def_struct_sdna(srna, "bNodeTreePath");
RNA_def_struct_ui_text(srna, "Node Tree Path", "Element of the node space tree path");
@@ -4385,7 +4386,7 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_AUTO_RENDER);
RNA_def_property_ui_text(prop, "Auto Render", "Re-render and composite changed layers on 3D edits");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
-
+
prop = RNA_def_property(srna, "backdrop_zoom", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "zoom");
RNA_def_property_float_default(prop, 1.0f);
@@ -4393,7 +4394,7 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0.01, 100, 1, 2);
RNA_def_property_ui_text(prop, "Backdrop Zoom", "Backdrop zoom factor");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
-
+
prop = RNA_def_property(srna, "backdrop_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xof");
RNA_def_property_ui_text(prop, "Backdrop X", "Backdrop X offset");
@@ -4410,11 +4411,6 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the image to draw");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
- prop = RNA_def_property(srna, "show_highlight", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_SHOW_HIGHLIGHT);
- RNA_def_property_ui_text(prop, "Highlight", "Highlight nodes that are being calculated");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
-
/* the mx/my "cursor" in the node editor is used only by operators to store the mouse position */
prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ);
RNA_def_property_array(prop, 2);
@@ -4453,12 +4449,12 @@ static void rna_def_space_logic(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_SENS_SEL);
RNA_def_property_ui_text(prop, "Show Selected Object", "Show sensors of all selected objects");
RNA_def_property_update(prop, NC_LOGIC, NULL);
-
+
prop = RNA_def_property(srna, "show_sensors_active_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_SENS_ACT);
RNA_def_property_ui_text(prop, "Show Active Object", "Show sensors of active object");
RNA_def_property_update(prop, NC_LOGIC, NULL);
-
+
prop = RNA_def_property(srna, "show_sensors_linked_controller", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_SENS_LINK);
RNA_def_property_ui_text(prop, "Show Linked to Controller", "Show linked objects to the controller");
@@ -4474,7 +4470,7 @@ static void rna_def_space_logic(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_CONT_SEL);
RNA_def_property_ui_text(prop, "Show Selected Object", "Show controllers of all selected objects");
RNA_def_property_update(prop, NC_LOGIC, NULL);
-
+
prop = RNA_def_property(srna, "show_controllers_active_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_CONT_ACT);
RNA_def_property_ui_text(prop, "Show Active Object", "Show controllers of active object");
@@ -4490,12 +4486,12 @@ static void rna_def_space_logic(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_ACT_SEL);
RNA_def_property_ui_text(prop, "Show Selected Object", "Show actuators of all selected objects");
RNA_def_property_update(prop, NC_LOGIC, NULL);
-
+
prop = RNA_def_property(srna, "show_actuators_active_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_ACT_ACT);
RNA_def_property_ui_text(prop, "Show Active Object", "Show actuators of active object");
RNA_def_property_update(prop, NC_LOGIC, NULL);
-
+
prop = RNA_def_property(srna, "show_actuators_linked_controller", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_ACT_LINK);
RNA_def_property_ui_text(prop, "Show Linked to Actuator", "Show linked objects to the actuator");
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index c72d6d9e581..8f771eda99d 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -47,7 +47,7 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
v3d = (View3D *)sa->spacedata.first;
- ED_view3d_update_viewmat(sc->scene, v3d, ar, NULL, NULL);
+ ED_view3d_update_viewmat(sc->scene, v3d, ar, NULL, NULL, NULL);
}
}
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 7a3c862f04c..54b82fc89d6 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1039,6 +1039,7 @@ static void rna_def_uilist(BlenderRNA *brna)
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");
+ RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES);
/* Registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 46775af21db..7d8d24670a7 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -557,8 +557,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
- parm = RNA_def_pointer(func, "properties", "OperatorProperties", "",
- "Operator properties to fill in, return when 'properties' is set to true");
+ parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "Operator properties to fill in");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_function_return(func, parm);
RNA_def_function_ui_description(func, "Item. Places a button into the layout to call an Operator");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 74888bf4f00..c0f2dbd0706 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -138,23 +138,11 @@ static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
}
/* also used by buffer swap switching */
-static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+static void rna_userdef_dpi_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
/* font's are stored at each DPI level, without this we can easy load 100's of fonts */
BLF_cache_clear();
- BKE_blender_userdef_refresh();
- WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
-}
-
-static void rna_userdef_virtual_pixel_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
-{
- /* font's are stored at each DPI level, without this we can easy load 100's of fonts */
- BLF_cache_clear();
-
- BKE_blender_userdef_refresh();
-
/* force setting drawable again */
wmWindowManager *wm = bmain->wm.first;
if (wm) {
@@ -3168,6 +3156,7 @@ static void rna_def_userdef_addon_pref(BlenderRNA *brna)
RNA_def_struct_refine_func(srna, "rna_AddonPref_refine");
RNA_def_struct_register_funcs(srna, "rna_AddonPref_register", "rna_AddonPref_unregister", NULL);
RNA_def_struct_idprops_func(srna, "rna_AddonPref_idprops");
+ RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Mandatory! */
/* registration */
RNA_define_verify_sdna(0);
@@ -3325,6 +3314,12 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "View & Controls", "Preferences related to viewing data");
/* View */
+ prop = RNA_def_property(srna, "ui_scale", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_text(prop, "UI Scale", "Changes the size of the fonts and buttons in the interface");
+ RNA_def_property_range(prop, 0.25f, 4.0f);
+ RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 2);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
/* display */
prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE);
@@ -3916,12 +3911,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem virtual_pixel_mode_items[] = {
- {VIRTUAL_PIXEL_NATIVE, "NATIVE", 0, "Native", "Use native pixel size of the display"},
- {VIRTUAL_PIXEL_DOUBLE, "DOUBLE", 0, "Double", "Use double the native pixel size of the display"},
- {0, NULL, 0, NULL, NULL}
- };
-
srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL);
RNA_def_struct_sdna(srna, "UserDef");
RNA_def_struct_nested(brna, srna, "UserPreferences");
@@ -3936,16 +3925,8 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update");
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "dpi");
- RNA_def_property_range(prop, 48, 144);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
- RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
-
- prop = RNA_def_property(srna, "virtual_pixel_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "virtual_pixel");
- RNA_def_property_enum_items(prop, virtual_pixel_mode_items);
- RNA_def_property_ui_text(prop, "Virtual Pixel Mode", "Modify the pixel size for hi-res devices");
- RNA_def_property_update(prop, 0, "rna_userdef_virtual_pixel_update");
prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -4678,6 +4659,11 @@ void RNA_def_userdef(BlenderRNA *brna)
"Active section of the user preferences shown in the user interface");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ /* don't expose this directly via the UI, modify via an operator */
+ prop = RNA_def_property(srna, "app_template", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "app_template");
+ RNA_def_property_ui_text(prop, "Application Template", "");
+
prop = RNA_def_property(srna, "themes", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "themes", NULL);
RNA_def_property_struct_type(prop, "Theme");
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 35c9c9bcc89..b5ecaf739c7 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -939,35 +939,8 @@ static void rna_wmClipboard_set(PointerRNA *UNUSED(ptr), const char *value)
}
#ifdef WITH_PYTHON
-static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
-{
- const char *idname;
- wmOperatorType *ot = RNA_struct_blender_type_get(type);
- wmWindowManager *wm;
-
- if (!ot)
- return;
-
- /* update while blender is running */
- wm = bmain->wm.first;
- if (wm) {
- WM_operator_stack_clear(wm);
- WM_operator_handlers_clear(wm, ot);
- }
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
-
- RNA_struct_free_extension(type, &ot->ext);
-
- idname = ot->idname;
- WM_operatortype_remove_ptr(ot);
- MEM_freeN((void *)idname);
-
- /* not to be confused with the RNA_struct_free that WM_operatortype_remove calls, they are 2 different srna's */
- RNA_struct_free(&BLENDER_RNA, type);
-}
-
-static int operator_poll(bContext *C, wmOperatorType *ot)
+static int rna_operator_poll_cb(bContext *C, wmOperatorType *ot)
{
extern FunctionRNA rna_Operator_poll_func;
@@ -992,7 +965,7 @@ static int operator_poll(bContext *C, wmOperatorType *ot)
return visible;
}
-static int operator_execute(bContext *C, wmOperator *op)
+static int rna_operator_execute_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_execute_func;
@@ -1018,7 +991,7 @@ static int operator_execute(bContext *C, wmOperator *op)
}
/* same as execute() but no return value */
-static bool operator_check(bContext *C, wmOperator *op)
+static bool rna_operator_check_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_check_func;
@@ -1043,7 +1016,7 @@ static bool operator_check(bContext *C, wmOperator *op)
return result;
}
-static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int rna_operator_invoke_cb(bContext *C, wmOperator *op, const wmEvent *event)
{
extern FunctionRNA rna_Operator_invoke_func;
@@ -1070,7 +1043,7 @@ static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
/* same as invoke */
-static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event)
+static int rna_operator_modal_cb(bContext *C, wmOperator *op, const wmEvent *event)
{
extern FunctionRNA rna_Operator_modal_func;
@@ -1096,7 +1069,7 @@ static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event)
return result;
}
-static void operator_draw(bContext *C, wmOperator *op)
+static void rna_operator_draw_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_draw_func;
@@ -1115,7 +1088,7 @@ static void operator_draw(bContext *C, wmOperator *op)
}
/* same as exec(), but call cancel */
-static void operator_cancel(bContext *C, wmOperator *op)
+static void rna_operator_cancel_cb(bContext *C, wmOperator *op)
{
extern FunctionRNA rna_Operator_cancel_func;
@@ -1133,35 +1106,42 @@ static void operator_cancel(bContext *C, wmOperator *op)
RNA_parameter_list_free(&list);
}
-void operator_wrapper(wmOperatorType *ot, void *userdata);
-void macro_wrapper(wmOperatorType *ot, void *userdata);
+static void rna_Operator_unregister(struct Main *bmain, StructRNA *type);
-static char _operator_idname[OP_MAX_TYPENAME];
-static char _operator_name[OP_MAX_TYPENAME];
-static char _operator_descr[RNA_DYN_DESCR_MAX];
-static char _operator_ctxt[RNA_DYN_DESCR_MAX];
-static char _operator_undo_group[OP_MAX_TYPENAME];
-static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+/* bpy_operator_wrap.c */
+extern void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata);
+extern void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata);
+
+static StructRNA *rna_Operator_register(
+ Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
wmOperatorType dummyot = {NULL};
wmOperator dummyop = {NULL};
PointerRNA dummyotr;
int have_function[7];
+ struct {
+ char idname[OP_MAX_TYPENAME];
+ char name[OP_MAX_TYPENAME];
+ char descr[RNA_DYN_DESCR_MAX];
+ char ctxt[RNA_DYN_DESCR_MAX];
+ char undo_group[OP_MAX_TYPENAME];
+ } temp_buffers;
+
/* setup dummy operator & operator type to store static properties in */
dummyop.type = &dummyot;
- dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
- dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
- dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
- dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
- dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */
+ dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
+ dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
+ dummyot.description = temp_buffers.descr; /* only assigne the pointer, string is NULL'd */
+ dummyot.translation_context = temp_buffers.ctxt; /* only assigne the pointer, string is NULL'd */
+ dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr);
/* clear in case they are left unset */
- _operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0';
+ temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.descr[0] = temp_buffers.undo_group[0] = '\0';
/* We have to set default op context! */
- strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ strcpy(temp_buffers.ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
@@ -1172,7 +1152,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
/* inconveniently long name sanity check */
{
- char *ch = _operator_idname;
+ char *ch = temp_buffers.idname;
int i;
int dot = 0;
for (i = 0; *ch; i++) {
@@ -1185,7 +1165,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
else {
BKE_reportf(reports, RPT_ERROR,
"Registering operator class: '%s', invalid bl_idname '%s', at position %d",
- identifier, _operator_idname, i);
+ identifier, temp_buffers.idname, i);
return NULL;
}
@@ -1194,7 +1174,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
if (i > ((int)sizeof(dummyop.idname)) - 3) {
BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', "
- "is too long, maximum length is %d", identifier, _operator_idname,
+ "is too long, maximum length is %d", identifier, temp_buffers.idname,
(int)sizeof(dummyop.idname) - 3);
return NULL;
}
@@ -1202,34 +1182,34 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
if (dot != 1) {
BKE_reportf(reports, RPT_ERROR,
"Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character",
- identifier, _operator_idname);
+ identifier, temp_buffers.idname);
return NULL;
}
}
/* end sanity check */
{
- int idlen = strlen(_operator_idname) + 4;
- int namelen = strlen(_operator_name) + 1;
- int desclen = strlen(_operator_descr) + 1;
- int ctxtlen = strlen(_operator_ctxt) + 1;
- int ugrouplen = strlen(_operator_undo_group) + 1;
- char *ch;
+ const uint idname_len = strlen(temp_buffers.idname) + 4;
+ const uint name_len = strlen(temp_buffers.name) + 1;
+ const uint desc_len = strlen(temp_buffers.descr) + 1;
+ const uint ctxt_len = strlen(temp_buffers.ctxt) + 1;
+ const uint undo_group_len = strlen(temp_buffers.undo_group) + 1;
/* 2 terminators and 3 to convert a.b -> A_OT_b */
- ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname");
- WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
+ char *ch = MEM_mallocN(
+ sizeof(char) * (idname_len + name_len + desc_len + ctxt_len + undo_group_len), __func__);
+ WM_operator_bl_idname(ch, temp_buffers.idname); /* convert the idname from python */
dummyot.idname = ch;
- ch += idlen;
- strcpy(ch, _operator_name);
+ ch += idname_len;
+ memcpy(ch, temp_buffers.name, name_len);
dummyot.name = ch;
- ch += namelen;
- strcpy(ch, _operator_descr);
+ ch += name_len;
+ memcpy(ch, temp_buffers.descr, desc_len);
dummyot.description = ch;
- ch += desclen;
- strcpy(ch, _operator_ctxt);
+ ch += desc_len;
+ memcpy(ch, temp_buffers.ctxt, ctxt_len);
dummyot.translation_context = ch;
- ch += ctxtlen;
- strcpy(ch, _operator_undo_group);
+ ch += ctxt_len;
+ memcpy(ch, temp_buffers.undo_group, undo_group_len);
dummyot.undo_group = ch;
}
}
@@ -1252,14 +1232,14 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
dummyot.ext.call = call;
dummyot.ext.free = free;
- dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL;
- dummyot.exec = (have_function[1]) ? operator_execute : NULL;
- dummyot.check = (have_function[2]) ? operator_check : NULL;
- dummyot.invoke = (have_function[3]) ? operator_invoke : NULL;
- dummyot.modal = (have_function[4]) ? operator_modal : NULL;
- dummyot.ui = (have_function[5]) ? operator_draw : NULL;
- dummyot.cancel = (have_function[6]) ? operator_cancel : NULL;
- WM_operatortype_append_ptr(operator_wrapper, (void *)&dummyot);
+ dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL;
+ dummyot.exec = (have_function[1]) ? rna_operator_execute_cb : NULL;
+ dummyot.check = (have_function[2]) ? rna_operator_check_cb : NULL;
+ dummyot.invoke = (have_function[3]) ? rna_operator_invoke_cb : NULL;
+ dummyot.modal = (have_function[4]) ? rna_operator_modal_cb : NULL;
+ dummyot.ui = (have_function[5]) ? rna_operator_draw_cb : NULL;
+ dummyot.cancel = (have_function[6]) ? rna_operator_cancel_cb : NULL;
+ WM_operatortype_append_ptr(BPY_RNA_operator_wrapper, (void *)&dummyot);
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
@@ -1267,70 +1247,107 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
return dummyot.ext.srna;
}
+static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
+{
+ const char *idname;
+ wmOperatorType *ot = RNA_struct_blender_type_get(type);
+ wmWindowManager *wm;
+
+ if (!ot)
+ return;
+
+ /* update while blender is running */
+ wm = bmain->wm.first;
+ if (wm) {
+ WM_operator_stack_clear(wm);
+
+ WM_operator_handlers_clear(wm, ot);
+ }
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+ RNA_struct_free_extension(type, &ot->ext);
+
+ idname = ot->idname;
+ WM_operatortype_remove_ptr(ot);
+ MEM_freeN((void *)idname);
+
+ /* not to be confused with the RNA_struct_free that WM_operatortype_remove calls, they are 2 different srna's */
+ RNA_struct_free(&BLENDER_RNA, type);
+}
+
static void **rna_Operator_instance(PointerRNA *ptr)
{
wmOperator *op = ptr->data;
return &op->py_instance;
}
-static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
- StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+static StructRNA *rna_MacroOperator_register(
+ Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
wmOperatorType dummyot = {NULL};
wmOperator dummyop = {NULL};
PointerRNA dummyotr;
int have_function[4];
+ struct {
+ char idname[OP_MAX_TYPENAME];
+ char name[OP_MAX_TYPENAME];
+ char descr[RNA_DYN_DESCR_MAX];
+ char ctxt[RNA_DYN_DESCR_MAX];
+ char undo_group[OP_MAX_TYPENAME];
+ } temp_buffers;
+
/* setup dummy operator & operator type to store static properties in */
dummyop.type = &dummyot;
- dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
- dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
- dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
- dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
- dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */
+ dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
+ dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
+ dummyot.description = temp_buffers.descr; /* only assigne the pointer, string is NULL'd */
+ dummyot.translation_context = temp_buffers.ctxt; /* only assigne the pointer, string is NULL'd */
+ dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr);
/* clear in case they are left unset */
- _operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0';
+ temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.descr[0] = temp_buffers.undo_group[0] = '\0';
/* We have to set default op context! */
- strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ strcpy(temp_buffers.ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
return NULL;
+ if (strlen(identifier) >= sizeof(dummyop.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummyop.idname));
+ return NULL;
+ }
+
{ /* convert foo.bar to FOO_OT_bar
* allocate the description and the idname in 1 go */
- int idlen = strlen(_operator_idname) + 4;
- int namelen = strlen(_operator_name) + 1;
- int desclen = strlen(_operator_descr) + 1;
- int ctxtlen = strlen(_operator_ctxt) + 1;
- int ugrouplen = strlen(_operator_undo_group) + 1;
- char *ch;
+ const uint idname_len = strlen(temp_buffers.idname) + 4;
+ const uint name_len = strlen(temp_buffers.name) + 1;
+ const uint desc_len = strlen(temp_buffers.descr) + 1;
+ const uint ctxt_len = strlen(temp_buffers.ctxt) + 1;
+ const uint undo_group_len = strlen(temp_buffers.undo_group) + 1;
/* 2 terminators and 3 to convert a.b -> A_OT_b */
- ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname");
- WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
+ char *ch = MEM_mallocN(
+ sizeof(char) * (idname_len + name_len + desc_len + ctxt_len + undo_group_len), __func__);
+ WM_operator_bl_idname(ch, temp_buffers.idname); /* convert the idname from python */
dummyot.idname = ch;
- ch += idlen;
- strcpy(ch, _operator_name);
+ ch += idname_len;
+ memcpy(ch, temp_buffers.name, name_len);
dummyot.name = ch;
- ch += namelen;
- strcpy(ch, _operator_descr);
+ ch += name_len;
+ memcpy(ch, temp_buffers.descr, desc_len);
dummyot.description = ch;
- ch += desclen;
- strcpy(ch, _operator_ctxt);
+ ch += desc_len;
+ memcpy(ch, temp_buffers.ctxt, ctxt_len);
dummyot.translation_context = ch;
- ch += ctxtlen;
- strcpy(ch, _operator_undo_group);
+ ch += ctxt_len;
+ memcpy(ch, temp_buffers.undo_group, undo_group_len);
dummyot.undo_group = ch;
}
- if (strlen(identifier) >= sizeof(dummyop.idname)) {
- BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s' is too long, maximum length is %d",
- identifier, (int)sizeof(dummyop.idname));
- return NULL;
- }
-
/* check if we have registered this operator type before, and remove it */
{
wmOperatorType *ot = WM_operatortype_find(dummyot.idname, true);
@@ -1348,10 +1365,10 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
dummyot.ext.call = call;
dummyot.ext.free = free;
- dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL;
- dummyot.ui = (have_function[3]) ? operator_draw : NULL;
+ dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL;
+ dummyot.ui = (have_function[3]) ? rna_operator_draw_cb : NULL;
- WM_operatortype_append_macro_ptr(macro_wrapper, (void *)&dummyot);
+ WM_operatortype_append_macro_ptr(BPY_RNA_operator_macro_wrapper, (void *)&dummyot);
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
@@ -1556,6 +1573,7 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Operator Properties", "Input properties of an Operator");
RNA_def_struct_refine_func(srna, "rna_OperatorProperties_refine");
RNA_def_struct_idprops_func(srna, "rna_OperatorProperties_idprops");
+ RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES);
}
static void rna_def_macro_operator(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 1f23ab938fb..677ea92aea1 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -87,6 +87,11 @@ static void rna_Operator_report(wmOperator *op, int type, const char *msg)
BKE_report(op->reports, type, msg);
}
+static int rna_Operator_is_repeat(wmOperator *op, bContext *C)
+{
+ return WM_operator_is_repeat(C, op);
+}
+
/* since event isn't needed... */
static void rna_Operator_enum_search_invoke(bContext *C, wmOperator *op)
{
@@ -521,6 +526,12 @@ void RNA_api_operator(StructRNA *srna)
parm = RNA_def_string(func, "message", NULL, 0, "Report Message", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* utility, not for registering */
+ func = RNA_def_function(srna, "is_repeat", "rna_Operator_is_repeat");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ /* return */
+ parm = RNA_def_boolean(func, "result", 0, "result", "");
+ RNA_def_function_return(func, parm);
/* Registration */
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 2b739dc0093..874ac34b613 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -50,6 +50,7 @@
#include "BKE_curve.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
+#include "BKE_mesh.h"
#include "MOD_util.h"
@@ -137,7 +138,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
- struct Scene *scene,
+ struct Scene *UNUSED(scene),
Object *UNUSED(ob),
struct DepsNodeHandle *node)
{
@@ -149,33 +150,15 @@ static void updateDepsgraph(ModifierData *md,
DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_TRANSFORM, "Array Modifier End Cap");
}
if (amd->curve_ob) {
+ struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node);
DEG_add_object_relation(node, amd->curve_ob, DEG_OB_COMP_GEOMETRY, "Array Modifier Curve");
- DEG_add_special_eval_flag(scene->depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH);
+ DEG_add_special_eval_flag(depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH);
}
if (amd->offset_ob != NULL) {
DEG_add_object_relation(node, amd->offset_ob, DEG_OB_COMP_TRANSFORM, "Array Modifier Offset");
}
}
-static float vertarray_size(const MVert *mvert, int numVerts, int axis)
-{
- int i;
- float min_co, max_co;
-
- /* if there are no vertices, width is 0 */
- if (numVerts == 0) return 0;
-
- /* find the minimum and maximum coordinates on the desired axis */
- min_co = max_co = mvert->co[axis];
- mvert++;
- for (i = 1; i < numVerts; ++i, ++mvert) {
- if (mvert->co[axis] < min_co) min_co = mvert->co[axis];
- if (mvert->co[axis] > max_co) max_co = mvert->co[axis];
- }
-
- return max_co - min_co;
-}
-
BLI_INLINE float sum_v3(const float v[3])
{
return v[0] + v[1] + v[2];
@@ -472,12 +455,22 @@ static DerivedMesh *arrayModifier_doArray(
unit_m4(offset);
src_mvert = dm->getVertArray(dm);
- if (amd->offset_type & MOD_ARR_OFF_CONST)
- add_v3_v3v3(offset[3], offset[3], amd->offset);
+ if (amd->offset_type & MOD_ARR_OFF_CONST) {
+ add_v3_v3(offset[3], amd->offset);
+ }
if (amd->offset_type & MOD_ARR_OFF_RELATIVE) {
- for (j = 0; j < 3; j++)
- offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j);
+ float min[3], max[3];
+ const MVert *src_mv;
+
+ INIT_MINMAX(min, max);
+ for (src_mv = src_mvert, j = chunk_nverts; j--; src_mv++) {
+ minmax_v3v3_v3(min, max, src_mv->co);
+ }
+
+ for (j = 3; j--; ) {
+ offset[3][j] += amd->scale[j] * (max[j] - min[j]);
+ }
}
if (use_offset_ob) {
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 09444476bfe..3c6ba7acc88 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -111,7 +111,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
- struct Scene *scene,
+ struct Scene *UNUSED(scene),
Object *object,
struct DepsNodeHandle *node)
{
@@ -123,8 +123,9 @@ static void updateDepsgraph(ModifierData *md,
/* TODO(sergey): Currently path is evaluated as a part of modifier stack,
* might be changed in the future.
*/
+ struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node);
DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier");
- DEG_add_special_eval_flag(scene->depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH);
+ DEG_add_special_eval_flag(depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH);
}
DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Curve Modifier");
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 18f60bab490..3325f05025f 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -384,6 +384,7 @@ static void displaceModifier_do(
data.vert_clnors = vert_clnors;
if (dmd->texture != NULL) {
data.pool = BKE_image_pool_new();
+ BKE_texture_fetch_images_for_pool(dmd->texture, data.pool);
}
BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512);
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index bb75d655802..83a42504180 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -36,6 +36,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_dynamicpaint.h"
+#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
@@ -58,6 +59,15 @@ static void copyData(ModifierData *md, ModifierData *target)
DynamicPaintModifierData *tpmd = (DynamicPaintModifierData *)target;
dynamicPaint_Modifier_copy(pmd, tpmd);
+
+ if (tpmd->canvas) {
+ for (DynamicPaintSurface *surface = tpmd->canvas->surfaces.first; surface; surface = surface->next) {
+ id_us_plus((ID *)surface->init_texture);
+ }
+ }
+ if (tpmd->brush) {
+ id_us_plus((ID *)tpmd->brush->mat);
+ }
}
static void freeData(ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index c202c5e1cb4..1964e940cb2 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -68,12 +68,13 @@ static void copyData(ModifierData *md, ModifierData *target)
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
FluidsimModifierData *tfluidmd = (FluidsimModifierData *) target;
- if (tfluidmd->fss)
- MEM_freeN(tfluidmd->fss);
-
- tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
- if (tfluidmd->fss && (tfluidmd->fss->meshVelocities != NULL)) {
- tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities);
+ fluidsim_free(tfluidmd);
+
+ if (fluidmd->fss) {
+ tfluidmd->fss = MEM_dupallocN(fluidmd->fss);
+ if (tfluidmd->fss && (tfluidmd->fss->meshVelocities != NULL)) {
+ tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities);
+ }
}
}
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c
index ffbbb1b0745..3684e947fe0 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c
@@ -78,8 +78,8 @@ void fluidsim_init(FluidsimModifierData *fluidmd)
fss->resolutionxyz = 65;
fss->previewresxyz = 45;
fss->realsize = 0.5;
- fss->guiDisplayMode = 2; // preview
- fss->renderDisplayMode = 3; // render
+ fss->guiDisplayMode = OB_FSDOM_PREVIEW;
+ fss->renderDisplayMode = OB_FSDOM_FINAL;
fss->viscosityValue = 1.0;
fss->viscosityExponent = 6;
@@ -98,7 +98,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd)
/* fluid/inflow settings
* fss->iniVel --> automatically set to 0 */
- modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), "cache_fluid");
+ modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), OB_FLUIDSIM_SURF_DIR_DEFAULT);
/* first init of bounding box */
/* no bounding box needed */
@@ -150,9 +150,8 @@ void fluidsim_free(FluidsimModifierData *fluidmd)
if (fluidmd && fluidmd->fss) {
if (fluidmd->fss->meshVelocities) {
MEM_freeN(fluidmd->fss->meshVelocities);
- fluidmd->fss->meshVelocities = NULL;
}
- MEM_freeN(fluidmd->fss);
+ MEM_SAFE_FREE(fluidmd->fss);
}
return;
@@ -423,8 +422,6 @@ static void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh *
static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm,
FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
{
- int displaymode = 0;
-
int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */
/* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway. (See physics_fluid.c for that. - DG */
/* If we start with frame 0, we need to remap all animation channels, too, because they will all be 1 frame late if using frame-1! - DG */
@@ -435,25 +432,23 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm,
MPoly *mpoly;
MPoly mp_example = {0};
- if (!useRenderParams) {
- displaymode = fss->guiDisplayMode;
- }
- else {
- displaymode = fss->renderDisplayMode;
- }
+ const int displaymode = useRenderParams ? fss->renderDisplayMode : fss->guiDisplayMode;
switch (displaymode) {
- case 1:
+ case OB_FSDOM_GEOM:
/* just display original object */
return NULL;
- case 2:
+ case OB_FSDOM_PREVIEW:
/* use preview mesh */
BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME);
break;
- default: /* 3 */
- /* 3. use final mesh */
+ case OB_FSDOM_FINAL:
+ /* use final mesh */
BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME);
break;
+ default:
+ BLI_assert(!"Wrong fluidsim display type");
+ return NULL;
}
/* offset baked frame */
@@ -494,7 +489,7 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm,
/* load vertex velocities, if they exist...
* TODO? use generate flag as loading flag as well?
* warning, needs original .bobj.gz mesh loading filename */
- if (displaymode == 3) {
+ if (displaymode == OB_FSDOM_FINAL) {
fluidsim_read_vel_cache(fluidmd, dm, targetFile);
}
else {
diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
index 90fc750de3b..3dd3a5fc598 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
@@ -35,6 +35,9 @@
#ifdef __LITTLE_ENDIAN__
# include "BLI_endian_switch.h"
#endif
+#ifdef WIN32
+# include "BLI_winstuff.h"
+#endif
#include "MOD_meshcache_util.h" /* own include */
@@ -157,7 +160,7 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
return false;
}
- if (fseek(fp, index * mdd_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) {
+ if (fseek(fp, sizeof(float) * 3 * index * mdd_head.verts_tot, SEEK_CUR) != 0) {
*err_str = "Failed to seek frame";
return false;
}
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
index 219eae4ecca..8360c8ffda7 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -35,6 +35,10 @@
# include "BLI_endian_switch.h"
#endif
+#ifdef WIN32
+# include "BLI_winstuff.h"
+#endif
+
#include "MOD_meshcache_util.h" /* own include */
#include "DNA_modifier_types.h"
@@ -142,7 +146,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
return false;
}
- if (fseek(fp, index * pc2_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) {
+ if (fseek(fp, sizeof(float) * 3 * index * pc2_head.verts_tot , SEEK_CUR) != 0) {
*err_str = "Failed to seek frame";
return false;
}
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 406ce398ee0..b1938395a7b 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -83,7 +83,7 @@ static void copyData(ModifierData *md, ModifierData *target)
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
MeshDeformModifierData *tmmd = (MeshDeformModifierData *) target;
- *tmmd = *mmd;
+ modifier_copyData_generic(md, target);
if (mmd->bindinfluences) tmmd->bindinfluences = MEM_dupallocN(mmd->bindinfluences);
if (mmd->bindoffsets) tmmd->bindoffsets = MEM_dupallocN(mmd->bindoffsets);
@@ -91,8 +91,8 @@ static void copyData(ModifierData *md, ModifierData *target)
if (mmd->dyngrid) tmmd->dyngrid = MEM_dupallocN(mmd->dyngrid);
if (mmd->dyninfluences) tmmd->dyninfluences = MEM_dupallocN(mmd->dyninfluences);
if (mmd->dynverts) tmmd->dynverts = MEM_dupallocN(mmd->dynverts);
- if (mmd->bindweights) tmmd->dynverts = MEM_dupallocN(mmd->bindweights); /* deprecated */
- if (mmd->bindcos) tmmd->dynverts = MEM_dupallocN(mmd->bindcos); /* deprecated */
+ if (mmd->bindweights) tmmd->bindweights = MEM_dupallocN(mmd->bindweights); /* deprecated */
+ if (mmd->bindcos) tmmd->bindcos = MEM_dupallocN(mmd->bindcos); /* deprecated */
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index d956763fc1f..f0edcc31a10 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -112,7 +112,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (!mcmd->reader) {
mcmd->reader = CacheReader_open_alembic_object(cache_file->handle,
- mcmd->reader,
+ NULL,
ob,
mcmd->object_path);
if (!mcmd->reader) {
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index dd127cc255c..9705edc580c 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -274,8 +274,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
int j = maxLoops;
dmloopuv += j; /* second set of loops only */
for (; j-- > 0; dmloopuv++) {
- if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0];
- if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1];
+ if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0] + mmd->uv_offset[0];
+ if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1] + mmd->uv_offset[1];
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index e77cc655c16..2c0bfc86e7d 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -160,40 +160,19 @@ static void freeData(ModifierData *md)
static void copyData(ModifierData *md, ModifierData *target)
{
#ifdef WITH_OCEANSIM
+#if 0
OceanModifierData *omd = (OceanModifierData *) md;
+#endif
OceanModifierData *tomd = (OceanModifierData *) target;
- tomd->geometry_mode = omd->geometry_mode;
- tomd->resolution = omd->resolution;
- tomd->spatial_size = omd->spatial_size;
-
- tomd->wind_velocity = omd->wind_velocity;
-
- tomd->damp = omd->damp;
- tomd->smallest_wave = omd->smallest_wave;
- tomd->depth = omd->depth;
+ freeData(target);
- tomd->wave_alignment = omd->wave_alignment;
- tomd->wave_direction = omd->wave_direction;
- tomd->wave_scale = omd->wave_scale;
-
- tomd->chop_amount = omd->chop_amount;
- tomd->foam_coverage = omd->foam_coverage;
- tomd->time = omd->time;
-
- tomd->seed = omd->seed;
- tomd->flag = omd->flag;
+ modifier_copyData_generic(md, target);
tomd->refresh = 0;
- tomd->size = omd->size;
- tomd->repeat_x = omd->repeat_x;
- tomd->repeat_y = omd->repeat_y;
-
/* XXX todo: copy cache runtime too */
tomd->cached = 0;
- tomd->bakestart = omd->bakestart;
- tomd->bakeend = omd->bakeend;
tomd->oceancache = NULL;
tomd->ocean = BKE_ocean_add();
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index 68987a1d28e..e5b0f9c0001 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -172,6 +172,7 @@ ModifierTypeInfo modifierType_Surface = {
/* structSize */ sizeof(SurfaceModifierData),
/* type */ eModifierTypeType_OnlyDeform,
/* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_AcceptsCVs |
eModifierTypeFlag_NoUserAdd,
/* copyData */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index a999d7629af..b692137b604 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -138,7 +138,9 @@ static void copyData(ModifierData *md, ModifierData *target)
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target;
- *tsmd = *smd;
+ freeData(target);
+
+ modifier_copyData_generic(md, target);
if (smd->verts) {
tsmd->verts = MEM_dupallocN(smd->verts);
@@ -973,7 +975,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos)
adj_result = buildAdjacencyMap(mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys);
if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
- modifier_setError((ModifierData *)smd, "Target has edges with more than two polys");
+ modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
freeAdjacencyMap(vert_edges, adj_array, edge_polys);
free_bvhtree_from_mesh(&treeData);
MEM_freeN(smd->verts);
@@ -1019,11 +1021,11 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos)
freeData((ModifierData *)smd);
}
else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
- modifier_setError((ModifierData *)smd, "Target has edges with more than two polys");
+ modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
freeData((ModifierData *)smd);
}
else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) {
- modifier_setError((ModifierData *)smd, "Target contains concave polys");
+ modifier_setError((ModifierData *)smd, "Target contains concave polygons");
freeData((ModifierData *)smd);
}
else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) {
@@ -1035,7 +1037,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos)
* to explain this whith a reasonably sized message.
* Though it shouldn't really matter all that much,
* because this is very unlikely to occur */
- modifier_setError((ModifierData *)smd, "Target contains invalid polys");
+ modifier_setError((ModifierData *)smd, "Target contains invalid polygons");
freeData((ModifierData *)smd);
}
@@ -1120,6 +1122,11 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un
tdm = smd->target->derivedFinal;
}
+ if (!tdm) {
+ modifier_setError(md, "No valid target mesh");
+ return;
+ }
+
tnumverts = tdm->getNumVerts(tdm);
tnumpoly = tdm->getNumPolys(tdm);
@@ -1139,19 +1146,19 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un
/* Poly count checks */
if (smd->numverts != numverts) {
modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts);
- tdm->release(tdm);
return;
}
else if (smd->numpoly != tnumpoly) {
modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
- tdm->release(tdm);
return;
}
/* Actual vertex location update starts here */
- SDefDeformData data = {.bind_verts = smd->verts,
- .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetVertArray"),
- .vertexCos = vertexCos};
+ SDefDeformData data = {
+ .bind_verts = smd->verts,
+ .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetVertArray"),
+ .vertexCos = vertexCos,
+ };
if (data.targetCos != NULL) {
bool tdm_vert_alloc;
@@ -1170,8 +1177,6 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un
MEM_freeN(data.targetCos);
}
-
- tdm->release(tdm);
}
static void deformVerts(ModifierData *md, Object *ob,
@@ -1194,7 +1199,7 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- return !smd->target;
+ return !smd->target && !(smd->verts && !(smd->flags & MOD_SDEF_BIND));
}
ModifierTypeInfo modifierType_SurfaceDeform = {
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 78dc1ea8bcb..01468c1143a 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -45,6 +45,7 @@
#include "BKE_camera.h"
+#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_DerivedMesh.h"
@@ -70,9 +71,12 @@ static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
UVProjectModifierData *umd = (UVProjectModifierData *) md;
- UVProjectModifierData *tumd = (UVProjectModifierData *) target;
#endif
+ UVProjectModifierData *tumd = (UVProjectModifierData *) target;
+
modifier_copyData_generic(md, target);
+
+ id_us_plus((ID *)tumd->image);
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 92d44257d03..b340356467a 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -66,6 +66,10 @@ static void copyData(ModifierData *md, ModifierData *target)
WarpModifierData *wmd = (WarpModifierData *) md;
WarpModifierData *twmd = (WarpModifierData *) target;
+ if (twmd->curfalloff != NULL) {
+ curvemapping_free(twmd->curfalloff);
+ }
+
modifier_copyData_generic(md, target);
twmd->curfalloff = curvemapping_copy(wmd->curfalloff);
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 2a822ac07b5..cd30b54350c 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -226,8 +226,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
if (!do_add)
return dm;
/* Else, add a valid data layer! */
- dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC,
- NULL, numVerts, wmd->defgrp_name);
+ dvert = CustomData_add_layer(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
/* Ultimate security check. */
if (!dvert)
return dm;
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 9bff7bf11f1..1b3188c83b3 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -282,8 +282,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
if (wmd->mix_set != MOD_WVG_SET_ALL)
return dm;
/* Else, add a valid data layer! */
- dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC,
- NULL, numVerts, wmd->defgrp_name_a);
+ dvert = CustomData_add_layer(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
/* Ultimate security check. */
if (!dvert)
return dm;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index d20881df150..c5a3c70100b 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -163,6 +163,7 @@ set(SRC
shader/nodes/node_shader_background.c
shader/nodes/node_shader_bsdf_anisotropic.c
shader/nodes/node_shader_bsdf_diffuse.c
+ shader/nodes/node_shader_bsdf_principled.c
shader/nodes/node_shader_bsdf_glass.c
shader/nodes/node_shader_bsdf_glossy.c
shader/nodes/node_shader_bsdf_toon.c
@@ -288,8 +289,4 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
-if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
- add_definitions(-DWITH_CYCLES_DEBUG)
-endif()
-
blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 0215db1dd55..a5c2e604f46 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -139,6 +139,8 @@ void register_node_type_cmp_trackpos(void);
void register_node_type_cmp_planetrackdeform(void);
void register_node_type_cmp_cornerpin(void);
-void node_cmp_rlayers_force_hidden_passes(struct bNode *node);
+void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node);
+void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
+const char *node_cmp_rlayers_sock_to_pass(int sock_index);
#endif
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 4c0047f1d58..804c1897a27 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -106,6 +106,7 @@ void register_node_type_sh_bsdf_transparent(void);
void register_node_type_sh_bsdf_velvet(void);
void register_node_type_sh_bsdf_toon(void);
void register_node_type_sh_bsdf_anisotropic(void);
+void register_node_type_sh_bsdf_principled(void);
void register_node_type_sh_emission(void);
void register_node_type_sh_holdout(void);
void register_node_type_sh_volume_absorption(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index a9c0df7d7e8..02422a8622a 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -80,6 +80,7 @@ DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BA
DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" )
DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, def_anisotropic, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_PRINCIPLED, def_principled, "BSDF_PRINCIPLED", BsdfPrincipled, "Principled BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glass, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" )
DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_refraction, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" )
@@ -178,7 +179,7 @@ DefNode( CompositorNode, CMP_NODE_DISPLACE, 0, "DISPL
DefNode( CompositorNode, CMP_NODE_COMBHSVA, 0, "COMBHSVA", CombHSVA, "Combine HSVA", "" )
DefNode( CompositorNode, CMP_NODE_MATH, def_math, "MATH", Math, "Math", "" )
DefNode( CompositorNode, CMP_NODE_LUMA_MATTE, def_cmp_luma_matte, "LUMA_MATTE", LumaMatte, "Luminance Key", "" )
-DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" )
+DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, def_cmp_brightcontrast, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" )
DefNode( CompositorNode, CMP_NODE_GAMMA, 0, "GAMMA", Gamma, "Gamma", "" )
DefNode( CompositorNode, CMP_NODE_INVERT, def_cmp_invert, "INVERT", Invert, "Invert", "" )
DefNode( CompositorNode, CMP_NODE_NORMALIZE, 0, "NORMALIZE", Normalize, "Normalize", "" )
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index cb565bd5491..36778a18f77 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -240,8 +240,15 @@ void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int r
/* *********************************************** */
-/* based on rules, force sockets hidden always */
-void ntreeCompositForceHidden(bNodeTree *ntree)
+/* Update the outputs of the render layer nodes.
+ * Since the outputs depend on the render engine, this part is a bit complex:
+ * - ntreeCompositUpdateRLayers is called and loops over all render layer nodes
+ * - Each render layer node calls the update function of the render engine that's used for its scene
+ * - The render engine calls RE_engine_register_pass for each pass
+ * - RE_engine_register_pass calls ntreeCompositRegisterPass,
+ * which calls node_cmp_rlayers_register_pass for every render layer node
+ */
+void ntreeCompositUpdateRLayers(bNodeTree *ntree)
{
bNode *node;
@@ -249,16 +256,20 @@ void ntreeCompositForceHidden(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS)
- node_cmp_rlayers_force_hidden_passes(node);
-
- /* XXX this stuff is called all the time, don't want that.
- * Updates should only happen when actually necessary.
- */
-#if 0
- else if (node->type == CMP_NODE_IMAGE) {
- nodeUpdate(ntree, node);
- }
-#endif
+ node_cmp_rlayers_outputs(ntree, node);
+ }
+
+}
+
+void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
+{
+ bNode *node;
+
+ if (ntree == NULL) return;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS)
+ node_cmp_rlayers_register_pass(ntree, node, scene, srl, name, type);
}
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
index 2ad097013ef..fde7dccb4ac 100644
--- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
@@ -47,6 +47,7 @@ static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *no
{
NodeBilateralBlurData *nbbd = MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data");
node->storage = nbbd;
+ nbbd->iter = 1;
nbbd->sigma_color = 0.3;
nbbd->sigma_space = 5.0;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.c b/source/blender/nodes/composite/nodes/node_composite_brightness.c
index 62f23f417b2..26e4d3a52c9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_brightness.c
+++ b/source/blender/nodes/composite/nodes/node_composite_brightness.c
@@ -46,6 +46,10 @@ static bNodeSocketTemplate cmp_node_brightcontrast_out[] = {
{ -1, 0, "" }
};
+static void node_composit_init_brightcontrast(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ node->custom1 = 1;
+}
void register_node_type_cmp_brightcontrast(void)
{
@@ -53,6 +57,7 @@ void register_node_type_cmp_brightcontrast(void)
cmp_node_type_base(&ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, cmp_node_brightcontrast_in, cmp_node_brightcontrast_out);
+ node_type_init(&ntype, node_composit_init_brightcontrast);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
index 6eb27a228ad..336eb3409ff 100644
--- a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
@@ -46,6 +46,7 @@ static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeDBlurData *ndbd = MEM_callocN(sizeof(NodeDBlurData), "node dblur data");
node->storage = ndbd;
+ ndbd->iter = 1;
ndbd->center_x = 0.5;
ndbd->center_y = 0.5;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 4f02c106569..8139e29bade 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -32,192 +32,108 @@
#include "node_composite_util.h"
#include "BLI_utildefines.h"
+#include "BLI_linklist.h"
#include "DNA_scene_types.h"
+#include "RE_engine.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
-#ifdef WITH_CYCLES_DEBUG
-# include "RE_pipeline.h"
-#endif
-
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
static bNodeSocketTemplate cmp_node_rlayers_out[] = {
- { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_VECTOR, 0, N_("UV"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_VECTOR, 0, N_("Speed"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Specular"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Shadow"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("AO"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Reflect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Refract"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("IndexOB"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("IndexMA"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 0, N_("Mist"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Emit"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Environment"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Diffuse Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Glossy Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Glossy Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Glossy Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Transmission Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Transmission Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Transmission Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Subsurface Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Subsurface Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_RGBA, 0, N_("Subsurface Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
-#ifdef WITH_CYCLES_DEBUG
- { SOCK_RGBA, 0, N_("Debug"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
-#endif
+ { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_Z), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_(RE_PASSNAME_NORMAL), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_(RE_PASSNAME_UV), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_(RE_PASSNAME_VECTOR), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_RGBA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SPEC), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SHADOW), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_AO), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_REFLECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_REFRACT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXOB), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXMA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_(RE_PASSNAME_MIST), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_EMIT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_ENVIRONMENT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
-static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int pass, int rres_index)
+static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node,
+ const char *name, const char *passname,
+ int rres_index, int type, int is_rlayers,
+ LinkNodePair *available_sockets, int *prev_index)
{
bNodeSocket *sock;
- NodeImageLayer *sockdata;
-
- sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
- /* extra socket info */
- sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
- sock->storage = sockdata;
-
- sockdata->pass_flag = pass;
-
- return sock;
-}
-
-static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag)
-{
- if (passflag & SCE_PASS_COMBINED) {
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE);
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA);
- }
-
- if (passflag & SCE_PASS_Z)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z);
- if (passflag & SCE_PASS_NORMAL)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL);
- if (passflag & SCE_PASS_VECTOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC);
- if (passflag & SCE_PASS_UV)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV);
- if (passflag & SCE_PASS_RGBA)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA);
- if (passflag & SCE_PASS_DIFFUSE)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF);
- if (passflag & SCE_PASS_SPEC)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC);
- if (passflag & SCE_PASS_SHADOW)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW);
- if (passflag & SCE_PASS_AO)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO);
- if (passflag & SCE_PASS_REFLECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT);
- if (passflag & SCE_PASS_REFRACT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT);
- if (passflag & SCE_PASS_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT);
- if (passflag & SCE_PASS_INDEXOB)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB);
- if (passflag & SCE_PASS_INDEXMA)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA);
- if (passflag & SCE_PASS_MIST)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST);
- if (passflag & SCE_PASS_EMIT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT);
- if (passflag & SCE_PASS_ENVIRONMENT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV);
-
- if (passflag & SCE_PASS_DIFFUSE_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT);
- if (passflag & SCE_PASS_DIFFUSE_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT);
- if (passflag & SCE_PASS_DIFFUSE_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR);
-
- if (passflag & SCE_PASS_GLOSSY_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT);
- if (passflag & SCE_PASS_GLOSSY_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT);
- if (passflag & SCE_PASS_GLOSSY_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR);
-
- if (passflag & SCE_PASS_TRANSM_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT);
- if (passflag & SCE_PASS_TRANSM_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
- if (passflag & SCE_PASS_TRANSM_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
-
- if (passflag & SCE_PASS_SUBSURFACE_DIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_DIRECT, RRES_OUT_SUBSURFACE_DIRECT);
- if (passflag & SCE_PASS_SUBSURFACE_INDIRECT)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT);
- if (passflag & SCE_PASS_SUBSURFACE_COLOR)
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR);
-
-#ifdef WITH_CYCLES_DEBUG
- cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DEBUG, RRES_OUT_DEBUG);
-#endif
-}
-
-static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
-{
- bNodeSocket *sock;
- NodeImageLayer *sockdata;
- RenderPass *rpass;
- int index;
- int passflag = 0;
- for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) {
- int type;
- if (rpass->channels == 1)
- type = SOCK_FLOAT;
- else
- type = SOCK_RGBA;
-
- /* we only need one socket per type */
- if (passflag & rpass->passtype)
- continue;
-
- passflag |= rpass->passtype;
-
- sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name);
+ int sock_index = BLI_findstringindex(&node->outputs, name, offsetof(bNodeSocket, name));
+
+ if (sock_index < 0) {
+ /* The first 31 sockets always are the legacy hardcoded sockets.
+ * Any dynamically allocated sockets follow afterwards, and are sorted in the order in which they were stored in the RenderResult.
+ * Therefore, we remember the index of the last matched socket. New sockets are placed behind the previously traversed one, but always after the first 31. */
+ int after_index = *prev_index;
+ if (is_rlayers && after_index < 30)
+ after_index = 30;
+
+ if (rres_index >= 0) {
+ sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
+ }
+ else {
+ sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name);
+ }
/* extra socket info */
- sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+ NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
-
- sockdata->pass_index = index;
- sockdata->pass_flag = rpass->passtype;
-
- if (rpass->passtype == SCE_PASS_COMBINED) {
- sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha");
- sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
- sock->storage = sockdata;
- sockdata->pass_index = index;
- sockdata->pass_flag = rpass->passtype;
+
+ BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name));
+
+ sock_index = BLI_listbase_count(&node->outputs) - 1;
+ if (sock_index != after_index + 1) {
+ bNodeSocket *after_sock = BLI_findlink(&node->outputs, after_index);
+ BLI_remlink(&node->outputs, sock);
+ BLI_insertlinkafter(&node->outputs, after_sock, sock);
+ }
+ }
+ else {
+ sock = BLI_findlink(&node->outputs, sock_index);
+ NodeImageLayer *sockdata = sock->storage;
+ if (sockdata) {
+ BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name));
}
}
+
+ BLI_linklist_append(available_sockets, sock);
+ *prev_index = sock_index;
}
-static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
+static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets)
{
Image *ima = (Image *)node->id;
+ ImBuf *ibuf;
+ int prev_index = -1;
if (ima) {
ImageUser *iuser = node->storage;
ImageUser load_iuser = {NULL};
- ImBuf *ibuf;
int offset = BKE_image_sequence_guess_offset(ima);
/* It is possible that image user in this node is not
@@ -238,104 +154,144 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
RenderLayer *rl = BLI_findlink(&ima->rr->layers, iuser->layer);
if (rl) {
- if (ima->type != IMA_TYPE_MULTILAYER)
- cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag);
- else
- cmp_node_image_add_multilayer_outputs(ntree, node, rl);
+ RenderPass *rpass;
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
+ int type;
+ if (rpass->channels == 1)
+ type = SOCK_FLOAT;
+ else
+ type = SOCK_RGBA;
+
+ cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index);
+ /* Special handling for the Combined pass to ensure compatibility. */
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", rpass->name, -1, SOCK_FLOAT, false, available_sockets, &prev_index);
+ }
+ }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
}
- else
- cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA);
}
- else
- cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA | RRES_OUT_Z);
-
+ }
+
+ cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, -1, SOCK_RGBA, false, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, -1, SOCK_FLOAT, false, available_sockets, &prev_index);
+
+ if (ima) {
BKE_image_release_ibuf(ima, ibuf, NULL);
}
- else
- cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA);
}
-static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
-{
- bNodeSocket *sock;
-
- for (sock = oldsocklist->first; sock; sock = sock->next)
- if (STREQ(sock->name, newsock->name))
- return sock;
- return NULL;
-}
+typedef struct RLayerUpdateData {
+ LinkNodePair *available_sockets;
+ int prev_index;
+} RLayerUpdateData;
-static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
+void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
{
- bNodeSocket *sock;
-
- /* first try to find matching socket name */
- for (sock = node->outputs.first; sock; sock = sock->next)
- if (STREQ(sock->name, oldsock->name))
- return sock;
-
- /* no matching name, simply link to same index */
- return BLI_findlink(&node->outputs, oldindex);
+ RLayerUpdateData *data = node->storage;
+
+ if (scene == NULL || srl == NULL || data == NULL || node->id != (ID *)scene) {
+ return;
+ }
+
+ SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1);
+ if (node_srl != srl) {
+ return;
+ }
+
+ /* Special handling for the Combined pass to ensure compatibility. */
+ if (STREQ(name, RE_PASSNAME_COMBINED)) {
+ cmp_node_image_add_pass_output(ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", name, -1, SOCK_FLOAT, true, data->available_sockets, &data->prev_index);
+ }
+ else {
+ cmp_node_image_add_pass_output(ntree, node, name, name, -1, type, true, data->available_sockets, &data->prev_index);
+ }
}
-static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
+static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets)
{
- /* pass */
+ Scene *scene = (Scene *)node->id;
+
+ if (scene) {
+ RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
+ if (engine_type && engine_type->update_render_passes) {
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1);
+ if (srl) {
+ RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data");
+ data->available_sockets = available_sockets;
+ data->prev_index = -1;
+ node->storage = data;
+
+ RenderEngine *engine = RE_engine_create(engine_type);
+ engine_type->update_render_passes(engine, scene, srl);
+ RE_engine_free(engine);
+
+ MEM_freeN(data);
+ node->storage = NULL;
+
+ return;
+ }
+ }
+ }
+
+ int prev_index = -1;
+ cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, true, available_sockets, &prev_index);
+ cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, true, available_sockets, &prev_index);
}
/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
-static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
+static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer)
{
- bNodeSocket *newsock, *oldsock, *oldsock_next;
- ListBase oldsocklist;
- int oldindex;
- bNodeLink *link;
-
- /* store current nodes in oldsocklist, then clear socket list */
- oldsocklist = node->outputs;
- BLI_listbase_clear(&node->outputs);
+ bNodeSocket *sock, *sock_next;
+ LinkNodePair available_sockets = {NULL, NULL};
+ int sock_index;
/* XXX make callback */
- cmp_node_image_create_outputs(ntree, node);
-
- for (newsock = node->outputs.first; newsock; newsock = newsock->next) {
- /* XXX make callback */
- oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
- if (oldsock) {
- /* XXX make callback */
- cmp_node_image_sync_output(node, newsock, oldsock);
+ if (rlayer)
+ cmp_node_rlayer_create_outputs(ntree, node, &available_sockets);
+ else
+ cmp_node_image_create_outputs(ntree, node, &available_sockets);
+
+ /* Get rid of sockets whose passes are not available in the image.
+ * If sockets that are not available would be deleted, the connections to them would be lost
+ * when e.g. opening a file (since there's no render at all yet).
+ * Therefore, sockets with connected links will just be set as unavailable.
+ *
+ * Another important detail comes from compatibility with the older socket model, where there
+ * was a fixed socket per pass type that was just hidden or not. Therefore, older versions expect
+ * the first 31 passes to belong to a specific pass type.
+ * So, we keep those 31 always allocated before the others as well, even if they have no links attached. */
+ sock_index = 0;
+ for (sock = node->outputs.first; sock; sock = sock_next, sock_index++) {
+ sock_next = sock->next;
+ if (BLI_linklist_index(available_sockets.list, sock) >= 0) {
+ sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN);
}
- }
-
- /* move links to new socket */
- for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) {
- newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
-
- if (newsock) {
+ else {
+ bNodeLink *link;
for (link = ntree->links.first; link; link = link->next) {
- if (link->fromsock == oldsock)
- link->fromsock = newsock;
+ if (link->fromsock == sock) break;
+ }
+ if (!link && (!rlayer || sock_index > 30)) {
+ MEM_freeN(sock->storage);
+ nodeRemoveSocket(ntree, node, sock);
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
}
}
}
-
- /* delete old sockets
- * XXX oldsock is not actually in the node->outputs list any more,
- * but the nodeRemoveSocket function works anyway. In future this
- * should become part of the core code, so can take care of this behavior.
- */
- for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) {
- oldsock_next = oldsock->next;
- MEM_freeN(oldsock->storage);
- nodeRemoveSocket(ntree, node, oldsock);
- }
+
+ BLI_linklist_free(available_sockets.list, NULL);
}
static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
{
/* avoid unnecessary updates, only changes to the image/image user data are of interest */
if (node->update & NODE_UPDATE_ID)
- cmp_node_image_verify_outputs(ntree, node);
+ cmp_node_image_verify_outputs(ntree, node, false);
}
static void node_composit_init_image(bNodeTree *ntree, bNode *node)
@@ -348,7 +304,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node)
iuser->ok = 1;
/* setup initial outputs */
- cmp_node_image_verify_outputs(ntree, node);
+ cmp_node_image_verify_outputs(ntree, node, false);
}
static void node_composit_free_image(bNode *node)
@@ -388,87 +344,44 @@ void register_node_type_cmp_image(void)
/* **************** RENDER RESULT ******************** */
-static void set_output_visible(bNode *node, int passflag, int index, int pass)
+void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *sock = BLI_findlink(&node->outputs, index);
- bool pass_enabled = ((passflag & pass) != 0);
-#ifdef WITH_CYCLES_DEBUG
- pass_enabled |= (pass == SCE_PASS_DEBUG);
-#endif
- /* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */
- if (pass_enabled)
- sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL);
- else
- sock->flag |= SOCK_UNAVAIL;
+ cmp_node_image_verify_outputs(ntree, node, true);
}
-/* clumsy checking... should do dynamic outputs once */
-void node_cmp_rlayers_force_hidden_passes(bNode *node)
+const char *node_cmp_rlayers_sock_to_pass(int sock_index)
{
- Scene *scene = (Scene *)node->id;
- SceneRenderLayer *srl;
- int passflag;
- bNodeSocket *sock;
-
- /* must always have valid scene pointer */
- if (!scene)
- return;
-
- srl = BLI_findlink(&scene->r.layers, node->custom1);
- if (!srl)
- return;
-
- passflag = srl->passflag;
-
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_UNAVAIL;
-
- set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED);
- set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED);
-
- set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z);
- set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL);
- set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR);
- set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV);
- set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA);
- set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE);
- set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC);
- set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW);
- set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO);
- set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT);
- set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT);
- set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB);
- set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA);
- set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST);
- set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT);
- set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT);
- set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR);
- set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR);
- set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR);
- set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT);
- set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT);
- set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR);
-
-#ifdef WITH_CYCLES_DEBUG
- set_output_visible(node, passflag, RRES_OUT_DEBUG, SCE_PASS_DEBUG);
-#endif
+ const char *sock_to_passname[] = {
+ RE_PASSNAME_COMBINED, RE_PASSNAME_COMBINED,
+ RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_RGBA,
+ RE_PASSNAME_DIFFUSE, RE_PASSNAME_SPEC, RE_PASSNAME_SHADOW, RE_PASSNAME_AO,
+ RE_PASSNAME_REFLECT, RE_PASSNAME_REFRACT, RE_PASSNAME_INDIRECT,
+ RE_PASSNAME_INDEXOB, RE_PASSNAME_INDEXMA, RE_PASSNAME_MIST, RE_PASSNAME_EMIT, RE_PASSNAME_ENVIRONMENT,
+ RE_PASSNAME_DIFFUSE_DIRECT, RE_PASSNAME_DIFFUSE_INDIRECT, RE_PASSNAME_DIFFUSE_COLOR,
+ RE_PASSNAME_GLOSSY_DIRECT, RE_PASSNAME_GLOSSY_INDIRECT, RE_PASSNAME_GLOSSY_COLOR,
+ RE_PASSNAME_TRANSM_DIRECT, RE_PASSNAME_TRANSM_INDIRECT, RE_PASSNAME_TRANSM_COLOR,
+ RE_PASSNAME_SUBSURFACE_DIRECT, RE_PASSNAME_SUBSURFACE_INDIRECT, RE_PASSNAME_SUBSURFACE_COLOR
+ };
+ if (sock_index > 30) {
+ return NULL;
+ }
+ return sock_to_passname[sock_index];
}
static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
bNode *node = ptr->data;
-
+ int sock_index = 0;
+
node->id = &scene->id;
-
- node_cmp_rlayers_force_hidden_passes(node);
+
+ for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++) {
+ NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
+ sock->storage = sockdata;
+
+ BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(sock_index), sizeof(sockdata->pass_name));
+ }
}
static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree)
@@ -489,6 +402,29 @@ static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree
return false;
}
+static void node_composit_free_rlayers(bNode *node)
+{
+ bNodeSocket *sock;
+
+ /* free extra socket info */
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ MEM_freeN(sock->storage);
+}
+
+static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), bNode *UNUSED(dest_node), bNode *src_node)
+{
+ bNodeSocket *sock;
+
+ /* copy extra socket info */
+ for (sock = src_node->outputs.first; sock; sock = sock->next)
+ sock->new_sock->storage = MEM_dupallocN(sock->storage);
+}
+
+static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node)
+{
+ cmp_node_image_verify_outputs(ntree, node, true);
+}
+
void register_node_type_cmp_rlayers(void)
{
static bNodeType ntype;
@@ -497,6 +433,9 @@ void register_node_type_cmp_rlayers(void)
node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
ntype.initfunc_api = node_composit_init_rlayers;
ntype.poll = node_composit_poll_rlayers;
+ node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers);
+ node_type_update(&ntype, cmp_node_rlayers_update, NULL);
+ node_type_init(&ntype, node_cmp_rlayers_outputs);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c
index d805cf4d87f..e0d9fa33f13 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switchview.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c
@@ -137,7 +137,6 @@ static void init_switch_view(const bContext *C, PointerRNA *ptr)
cmp_node_switch_view_sanitycheck(ntree, node);
}
-/* custom1 = mix type */
void register_node_type_cmp_switch_view(void)
{
static bNodeType ntype;
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 2347564c696..0cf131adbdc 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -78,7 +78,8 @@ void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack
static void node_init_input_index(bNodeSocket *sock, int *index)
{
- if (sock->link && sock->link->fromsock) {
+ /* Only consider existing link if from socket is valid! */
+ if (sock->link && sock->link->fromsock && sock->link->fromsock->stack_index >= 0) {
sock->stack_index = sock->link->fromsock->stack_index;
}
else {
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 9bd43f331fb..5bc97f13b41 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -142,28 +142,40 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
{
memset(gs, 0, sizeof(*gs));
- nodestack_get_vec(gs->vec, type, ns);
- gs->link = ns->data;
-
- if (type == SOCK_FLOAT)
- gs->type = GPU_FLOAT;
- else if (type == SOCK_VECTOR)
- gs->type = GPU_VEC3;
- else if (type == SOCK_RGBA)
- gs->type = GPU_VEC4;
- else if (type == SOCK_SHADER)
- gs->type = GPU_VEC4;
- else
+ if (ns == NULL) {
+ /* node_get_stack() will generate NULL bNodeStack pointers for unknown/unsuported types of sockets... */
+ zero_v4(gs->vec);
+ gs->link = NULL;
gs->type = GPU_NONE;
+ gs->name = "";
+ gs->hasinput = false;
+ gs->hasoutput = false;
+ gs->sockettype = type;
+ }
+ else {
+ nodestack_get_vec(gs->vec, type, ns);
+ gs->link = ns->data;
- gs->name = "";
- gs->hasinput = ns->hasinput && ns->data;
- /* XXX Commented out the ns->data check here, as it seems it's not always set,
- * even though there *is* a valid connection/output... But that might need
- * further investigation.
- */
- gs->hasoutput = ns->hasoutput /*&& ns->data*/;
- gs->sockettype = ns->sockettype;
+ if (type == SOCK_FLOAT)
+ gs->type = GPU_FLOAT;
+ else if (type == SOCK_VECTOR)
+ gs->type = GPU_VEC3;
+ else if (type == SOCK_RGBA)
+ gs->type = GPU_VEC4;
+ else if (type == SOCK_SHADER)
+ gs->type = GPU_VEC4;
+ else
+ gs->type = GPU_NONE;
+
+ gs->name = "";
+ gs->hasinput = ns->hasinput && ns->data;
+ /* XXX Commented out the ns->data check here, as it seems it's not always set,
+ * even though there *is* a valid connection/output... But that might need
+ * further investigation.
+ */
+ gs->hasoutput = ns->hasoutput /*&& ns->data*/;
+ gs->sockettype = ns->sockettype;
+ }
}
void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs)
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
new file mode 100644
index 00000000000..e0330d110ca
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -0,0 +1,114 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 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_principled_in[] = {
+ { SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Subsurface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_VECTOR, 1, N_("Subsurface Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f},
+ { SOCK_RGBA, 1, N_("Subsurface Color"), 0.7f, 0.1f, 0.1f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Specular Tint"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Anisotropic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Anisotropic Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Sheen"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Sheen Tint"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Clearcoat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Clearcoat Roughness"), 0.03f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_FLOAT, 1, N_("Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Transmission Roughness"),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},
+ { SOCK_VECTOR, 1, N_("Clearcoat Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { SOCK_VECTOR, 1, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_bsdf_principled_out[] = {
+ { SOCK_SHADER, 0, N_("BSDF")},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ node->custom1 = SHD_GLOSSY_MULTI_GGX;
+}
+
+static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ // normal
+ if (!in[17].link)
+ in[17].link = GPU_builtin(GPU_VIEW_NORMAL);
+ else
+ GPU_link(mat, "direction_transform_m4v3", in[17].link, GPU_builtin(GPU_VIEW_MATRIX), &in[17].link);
+
+ // clearcoat normal
+ if (!in[18].link)
+ in[18].link = GPU_builtin(GPU_VIEW_NORMAL);
+ else
+ GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link);
+
+ return GPU_stack_link(mat, "node_bsdf_principled", in, out, GPU_builtin(GPU_VIEW_POSITION));
+}
+
+static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock;
+ int distribution = node->custom1;
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Transmission Roughness")) {
+ if (distribution == SHD_GLOSSY_GGX)
+ sock->flag &= ~SOCK_UNAVAIL;
+ else
+ sock->flag |= SOCK_UNAVAIL;
+
+ }
+ }
+}
+
+/* node type definition */
+void register_node_type_sh_bsdf_principled(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_bsdf_principled_in, sh_node_bsdf_principled_out);
+ node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
+ node_type_init(&ntype, node_shader_init_principled);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_bsdf_principled);
+ node_type_update(&ntype, node_shader_update_principled, NULL);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index 48d1688c386..36d7522e3e6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -46,8 +46,10 @@ static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = attr;
}
-static void node_shader_exec_normal_map(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
- {
+static void node_shader_exec_normal_map(
+ void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata),
+ bNodeStack **in, bNodeStack **out)
+{
if (data) {
ShadeInput *shi = ((ShaderCallData *)data)->shi;
@@ -63,7 +65,7 @@ static void node_shader_exec_normal_map(void *data, int UNUSED(thread), bNode *n
CLAMP_MIN(strength, 0.0f);
- float *N = shi->vno;
+ float *N = shi->nmapnorm;
int uv_index = 0;
switch (nm->space) {
case SHD_NORMAL_MAP_TANGENT:
diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c
index d1905246fd4..63d3bac88a0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c
@@ -39,7 +39,16 @@ static bNodeSocketTemplate sh_node_object_info_out[] = {
static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_object_info", in, out);
+ return GPU_stack_link(mat, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_OBJECT_INFO));
+}
+
+static void node_shader_exec_object_info(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
+{
+ ShaderCallData *scd = (ShaderCallData *)data;
+ copy_v4_v4(out[0]->vec, RE_object_instance_get_matrix(scd->shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB)[3]);
+ out[1]->vec[0] = RE_object_instance_get_object_pass_index(scd->shi->obi);
+ out[2]->vec[0] = scd->shi->mat->index;
+ out[3]->vec[0] = RE_object_instance_get_random_id(scd->shi->obi) * (1.0f / (float)0xFFFFFFFF);
}
/* node type definition */
@@ -53,6 +62,7 @@ void register_node_type_sh_object_info(void)
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_object_info);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_object_info);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 359395b63c4..b694b6e994d 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -333,19 +333,14 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
return 1;
}
-BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float time)
+BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
{
Cloth *cloth = clmd->clothObject;
ClothSimSettings *parms = clmd->sim_parms;
Implicit_Data *data = cloth->implicit;
- ClothVertex *verts = cloth->verts;
bool no_compress = parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
- zero_v3(s->f);
- zero_m3(s->dfdx);
- zero_m3(s->dfdv);
-
s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
// calculate force of structural + shear springs
@@ -361,31 +356,13 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
if (s->type & CLOTH_SPRING_TYPE_SEWING) {
// TODO: verify, half verified (couldn't see error)
// sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects
- BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing, s->f, s->dfdx, s->dfdv);
+ BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing);
}
else {
- BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f, s->f, s->dfdx, s->dfdv);
+ BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f);
}
#endif
}
- else if (s->type & CLOTH_SPRING_TYPE_GOAL) {
-#ifdef CLOTH_FORCE_SPRING_GOAL
- float goal_x[3], goal_v[3];
- float k, scaling;
-
- s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
- // current_position = xold + t * (newposition - xold)
- /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */
- interp_v3_v3v3(goal_x, verts[s->ij].xold, verts[s->ij].xconst, time / parms->time_scale);
- sub_v3_v3v3(goal_v, verts[s->ij].xconst, verts[s->ij].xold); // distance covered over dt==1
-
- scaling = parms->goalspring + s->stiffness * fabsf(parms->max_struct - parms->goalspring);
- k = verts[s->ij].goal * scaling / (parms->avg_spring_len + FLT_EPSILON);
-
- BPH_mass_spring_force_spring_goal(data, s->ij, goal_x, goal_v, k, parms->goalfrict * 0.01f, s->f, s->dfdx, s->dfdv);
-#endif
- }
else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */
#ifdef CLOTH_FORCE_SPRING_BEND
float kb, cb, scaling;
@@ -398,7 +375,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
// Fix for [#45084] for cloth stiffness must have cb proportional to kb
cb = kb * parms->bending_damping;
- BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb, s->f, s->dfdx, s->dfdv);
+ BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb);
#endif
}
else if (s->type & CLOTH_SPRING_TYPE_BENDING_ANG) {
@@ -474,9 +451,24 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
/* scale gravity force */
mul_v3_v3fl(gravity, clmd->scene->physics_settings.gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity);
}
+
vert = cloth->verts;
for (i = 0; i < cloth->mvert_num; i++, vert++) {
BPH_mass_spring_force_gravity(data, i, vert->mass, gravity);
+
+ /* Vertex goal springs */
+ if ((!(vert->flags & CLOTH_VERT_FLAG_PINNED)) && (vert->goal > FLT_EPSILON)) {
+ float goal_x[3], goal_v[3];
+ float k;
+
+ /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */
+ interp_v3_v3v3(goal_x, vert->xold, vert->xconst, time / clmd->sim_parms->time_scale);
+ sub_v3_v3v3(goal_v, vert->xconst, vert->xold); /* distance covered over dt==1 */
+
+ k = vert->goal * clmd->sim_parms->goalspring / (clmd->sim_parms->avg_spring_len + FLT_EPSILON);
+
+ BPH_mass_spring_force_spring_goal(data, i, goal_x, goal_v, k, clmd->sim_parms->goalfrict * 0.01f);
+ }
}
#endif
@@ -544,8 +536,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
for (LinkNode *link = cloth->springs; link; link = link->next) {
ClothSpring *spring = (ClothSpring *)link->link;
// only handle active springs
- if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
- cloth_calc_spring_force(clmd, spring, time);
+ if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) {
+ cloth_calc_spring_force(clmd, spring);
+ }
}
}
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
index d1a75ca5297..2f62ab98e12 100644
--- a/source/blender/physics/intern/implicit.h
+++ b/source/blender/physics/intern/implicit.h
@@ -114,19 +114,15 @@ void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2,
void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]);
/* Linear spring force between two points */
bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen,
- float stiffness, float damping, bool no_compress, float clamp_force,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+ float stiffness, float damping, bool no_compress, float clamp_force);
/* Bending force, forming a triangle at the base of two structural springs */
-bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen,
- float kb, float cb,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, float kb, float cb);
/* Angular bending force based on local target vectors */
bool BPH_mass_spring_force_spring_bending_angular(struct Implicit_Data *data, int i, int j, int k,
const float target[3], float stiffness, float damping);
/* Global goal spring */
bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
- float stiffness, float damping,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+ float stiffness, float damping);
/* ======== Hair Volumetric Forces ======== */
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index 2ad8ee0547f..16cd335dc0c 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -1579,8 +1579,7 @@ BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3]
}
bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen,
- float stiffness, float damping, bool no_compress, float clamp_force,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+ float stiffness, float damping, bool no_compress, float clamp_force)
{
float extent[3], length, dir[3], vel[3];
@@ -1608,25 +1607,15 @@ bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, floa
apply_spring(data, i, j, f, dfdx, dfdv);
- if (r_f) copy_v3_v3(r_f, f);
- if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
- if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
-
return true;
}
else {
- if (r_f) zero_v3(r_f);
- if (r_dfdx) zero_m3(r_dfdx);
- if (r_dfdv) zero_m3(r_dfdv);
-
return false;
}
}
/* See "Stable but Responsive Cloth" (Choi, Ko 2005) */
-bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen,
- float kb, float cb,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen, float kb, float cb)
{
float extent[3], length, dir[3], vel[3];
@@ -1646,17 +1635,9 @@ bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, flo
apply_spring(data, i, j, f, dfdx, dfdv);
- if (r_f) copy_v3_v3(r_f, f);
- if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
- if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
-
return true;
}
else {
- if (r_f) zero_v3(r_f);
- if (r_dfdx) zero_m3(r_dfdx);
- if (r_dfdv) zero_m3(r_dfdv);
-
return false;
}
}
@@ -1945,8 +1926,7 @@ bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, in
}
bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
- float stiffness, float damping,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+ float stiffness, float damping)
{
float root_goal_x[3], root_goal_v[3], extent[3], length, dir[3], vel[3];
float f[3], dfdx[3][3], dfdv[3][3];
@@ -1973,17 +1953,9 @@ bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float g
add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfdx);
add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, dfdv);
- if (r_f) copy_v3_v3(r_f, f);
- if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
- if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
-
return true;
}
else {
- if (r_f) zero_v3(r_f);
- if (r_dfdx) zero_m3(r_dfdx);
- if (r_dfdv) zero_m3(r_dfdv);
-
return false;
}
}
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 3148dab3c50..b4c36a7c516 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -75,7 +75,8 @@ void BPY_thread_restore(BPy_ThreadStatePtr tstate);
bool BPY_execute_filepath(struct bContext *C, const char *filepath, struct ReportList *reports);
bool BPY_execute_text(struct bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump);
-bool BPY_execute_string_as_number(struct bContext *C, const char *expr, double *value, const bool verbose);
+bool BPY_execute_string_as_number(struct bContext *C, const char *expr, const bool verbose, double *r_value);
+bool BPY_execute_string_as_string(struct bContext *C, const char *expr, const bool verbose, char **r_value);
bool BPY_execute_string_ex(struct bContext *C, const char *expr, bool use_eval);
bool BPY_execute_string(struct bContext *C, const char *expr);
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 2e15b7b1413..5d6a7c578a2 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -43,6 +43,9 @@
#include "python_utildefines.h"
+extern bool pyrna_id_FromPyObject(PyObject *obj, ID **id);
+extern PyObject *pyrna_id_CreatePyObject(ID *id);
+extern bool pyrna_id_CheckPyObject(PyObject *obj);
/*********************** ID Property Main Wrapper Stuff ***************/
@@ -88,6 +91,11 @@ static PyObject *idprop_py_from_idp_group(ID *id, IDProperty *prop, IDProperty *
return (PyObject *)group;
}
+static PyObject *idprop_py_from_idp_id(IDProperty *prop)
+{
+ return pyrna_id_CreatePyObject(prop->data.pointer);
+}
+
static PyObject *idprop_py_from_idp_array(ID *id, IDProperty *prop)
{
BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &BPy_IDArray_Type);
@@ -148,6 +156,7 @@ PyObject *BPy_IDGroup_WrapData(ID *id, IDProperty *prop, IDProperty *parent)
case IDP_GROUP: return idprop_py_from_idp_group(id, prop, parent);
case IDP_ARRAY: return idprop_py_from_idp_array(id, prop);
case IDP_IDPARRAY: return idprop_py_from_idp_idparray(id, prop); /* this could be better a internal type */
+ case IDP_ID: return idprop_py_from_idp_id(prop);
default: Py_RETURN_NONE;
}
}
@@ -335,19 +344,9 @@ static char idp_sequence_type(PyObject *seq_fast)
return type;
}
-/**
- * \note group can be a pointer array or a group.
- * assume we already checked key is a string.
- *
- * \return success.
- */
-bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob)
+static const char *idp_try_read_name(PyObject *name_obj)
{
- IDProperty *prop = NULL;
- IDPropertyTemplate val = {0};
-
- const char *name;
-
+ const char *name = NULL;
if (name_obj) {
Py_ssize_t name_size;
name = _PyUnicode_AsStringAndSize(name_obj, &name_size);
@@ -356,168 +355,307 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
PyErr_Format(PyExc_KeyError,
"invalid id-property key, expected a string, not a %.200s",
Py_TYPE(name_obj)->tp_name);
- return false;
+ return NULL;
}
if (name_size > MAX_IDPROP_NAME) {
PyErr_SetString(PyExc_KeyError, "the length of IDProperty names is limited to 63 characters");
- return false;
+ return NULL;
}
}
else {
name = "";
}
+ return name;
+}
- if (PyFloat_Check(ob)) {
- val.d = PyFloat_AsDouble(ob);
- prop = IDP_New(IDP_DOUBLE, &val, name);
- }
- else if (PyLong_Check(ob)) {
- val.i = _PyLong_AsInt(ob);
- if (val.i == -1 && PyErr_Occurred()) {
- return false;
- }
- prop = IDP_New(IDP_INT, &val, name);
+/* -------------------------------------------------------------------------- */
+
+/**
+ * The 'idp_from_Py*' functions expect that the input type has been checked before
+ * and return NULL if the IDProperty can't be created.
+ */
+
+static IDProperty *idp_from_PyFloat(const char *name, PyObject *ob)
+{
+ IDPropertyTemplate val = {0};
+ val.d = PyFloat_AsDouble(ob);
+ return IDP_New(IDP_DOUBLE, &val, name);
+}
+
+static IDProperty *idp_from_PyLong(const char *name, PyObject *ob)
+{
+ IDPropertyTemplate val = {0};
+ val.i = _PyLong_AsInt(ob);
+ if (val.i == -1 && PyErr_Occurred()) {
+ return NULL;
}
- else if (PyUnicode_Check(ob)) {
+ return IDP_New(IDP_INT, &val, name);
+}
+
+static IDProperty *idp_from_PyUnicode(const char *name, PyObject *ob)
+{
+ IDProperty *prop;
+ IDPropertyTemplate val = {0};
#ifdef USE_STRING_COERCE
- Py_ssize_t value_size;
- PyObject *value_coerce = NULL;
- val.string.str = PyC_UnicodeAsByteAndSize(ob, &value_size, &value_coerce);
- val.string.len = (int)value_size + 1;
- val.string.subtype = IDP_STRING_SUB_UTF8;
- prop = IDP_New(IDP_STRING, &val, name);
- Py_XDECREF(value_coerce);
+ Py_ssize_t value_size;
+ PyObject *value_coerce = NULL;
+ val.string.str = PyC_UnicodeAsByteAndSize(ob, &value_size, &value_coerce);
+ val.string.len = (int)value_size + 1;
+ val.string.subtype = IDP_STRING_SUB_UTF8;
+ prop = IDP_New(IDP_STRING, &val, name);
+ Py_XDECREF(value_coerce);
#else
- val.str = _PyUnicode_AsString(ob);
- prop = IDP_New(IDP_STRING, val, name);
+ val.str = _PyUnicode_AsString(ob);
+ prop = IDP_New(IDP_STRING, val, name);
#endif
- }
- else if (PyBytes_Check(ob)) {
- val.string.str = PyBytes_AS_STRING(ob);
- val.string.len = PyBytes_GET_SIZE(ob);
- val.string.subtype = IDP_STRING_SUB_BYTE;
+ return prop;
+}
+
+static IDProperty *idp_from_PyBytes(const char *name, PyObject *ob)
+{
+ IDPropertyTemplate val = {0};
+ val.string.str = PyBytes_AS_STRING(ob);
+ val.string.len = PyBytes_GET_SIZE(ob);
+ val.string.subtype = IDP_STRING_SUB_BYTE;
+ return IDP_New(IDP_STRING, &val, name);
+}
- prop = IDP_New(IDP_STRING, &val, name);
- //prop = IDP_NewString(PyBytes_AS_STRING(ob), name, PyBytes_GET_SIZE(ob));
- //prop->subtype = IDP_STRING_SUB_BYTE;
+static int idp_array_type_from_format_char(char format)
+{
+ if (format == 'i') return IDP_INT;
+ if (format == 'f') return IDP_FLOAT;
+ if (format == 'd') return IDP_DOUBLE;
+ return -1;
+}
+
+static const char *idp_format_from_array_type(int type)
+{
+ if (type == IDP_INT) return "i";
+ if (type == IDP_FLOAT) return "f";
+ if (type == IDP_DOUBLE) return "d";
+ return NULL;
+}
+
+static IDProperty *idp_from_PySequence_Buffer(const char *name, Py_buffer *buffer)
+{
+ IDProperty *prop;
+ IDPropertyTemplate val = {0};
+
+ int format = idp_array_type_from_format_char(*buffer->format);
+ if (format == -1) {
+ /* should never happen as the type has been checked before */
+ return NULL;
}
- else if (PySequence_Check(ob)) {
- PyObject *ob_seq_fast;
- PyObject **ob_seq_fast_items;
- PyObject *item;
- int i;
+ else {
+ val.array.type = format;
+ val.array.len = buffer->len / buffer->itemsize;
+ }
+ prop = IDP_New(IDP_ARRAY, &val, name);
+ memcpy(IDP_Array(prop), buffer->buf, buffer->len);
+ return prop;
+}
- if (!(ob_seq_fast = PySequence_Fast(ob, "py -> idprop"))) {
- return false;
- }
+static IDProperty *idp_from_PySequence_Fast(const char *name, PyObject *ob)
+{
+ IDProperty *prop;
+ IDPropertyTemplate val = {0};
- ob_seq_fast_items = PySequence_Fast_ITEMS(ob_seq_fast);
+ PyObject **ob_seq_fast_items;
+ PyObject *item;
+ int i;
- if ((val.array.type = idp_sequence_type(ob_seq_fast)) == (char)-1) {
- Py_DECREF(ob_seq_fast);
- PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays");
- return false;
- }
+ ob_seq_fast_items = PySequence_Fast_ITEMS(ob);
- /* validate sequence and derive type.
- * we assume IDP_INT unless we hit a float
- * number; then we assume it's */
+ if ((val.array.type = idp_sequence_type(ob)) == (char)-1) {
+ PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays");
+ return NULL;
+ }
- val.array.len = PySequence_Fast_GET_SIZE(ob_seq_fast);
+ /* validate sequence and derive type.
+ * we assume IDP_INT unless we hit a float
+ * number; then we assume it's */
- switch (val.array.type) {
- case IDP_DOUBLE:
- {
- double *prop_data;
-
- prop = IDP_New(IDP_ARRAY, &val, name);
- prop_data = IDP_Array(prop);
- for (i = 0; i < val.array.len; i++) {
- item = ob_seq_fast_items[i];
- if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) {
- Py_DECREF(ob_seq_fast);
- return false;
- }
+ val.array.len = PySequence_Fast_GET_SIZE(ob);
+
+ switch (val.array.type) {
+ case IDP_DOUBLE:
+ {
+ double *prop_data;
+ prop = IDP_New(IDP_ARRAY, &val, name);
+ prop_data = IDP_Array(prop);
+ for (i = 0; i < val.array.len; i++) {
+ item = ob_seq_fast_items[i];
+ if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) {
+ return NULL;
}
- break;
}
- case IDP_INT:
- {
- int *prop_data;
- prop = IDP_New(IDP_ARRAY, &val, name);
- prop_data = IDP_Array(prop);
- for (i = 0; i < val.array.len; i++) {
- item = ob_seq_fast_items[i];
- if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) {
- Py_DECREF(ob_seq_fast);
- return false;
- }
+ break;
+ }
+ case IDP_INT:
+ {
+ int *prop_data;
+ prop = IDP_New(IDP_ARRAY, &val, name);
+ prop_data = IDP_Array(prop);
+ for (i = 0; i < val.array.len; i++) {
+ item = ob_seq_fast_items[i];
+ if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) {
+ return NULL;
}
- break;
}
- case IDP_IDPARRAY:
- {
- prop = IDP_NewIDPArray(name);
- for (i = 0; i < val.array.len; i++) {
- item = ob_seq_fast_items[i];
-
- if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) {
- Py_DECREF(ob_seq_fast);
- return false;
- }
+ break;
+ }
+ case IDP_IDPARRAY:
+ {
+ prop = IDP_NewIDPArray(name);
+ for (i = 0; i < val.array.len; i++) {
+ item = ob_seq_fast_items[i];
+ if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) {
+ return NULL;
}
- break;
}
- default:
- /* should never happen */
- Py_DECREF(ob_seq_fast);
- PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type");
- return false;
+ break;
}
+ default:
+ /* should never happen */
+ PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type");
+ return NULL;
+ }
+ return prop;
+}
- Py_DECREF(ob_seq_fast);
+
+static IDProperty *idp_from_PySequence(const char *name, PyObject *ob)
+{
+ Py_buffer buffer;
+ bool use_buffer = false;
+
+ if (PyObject_CheckBuffer(ob)) {
+ PyObject_GetBuffer(ob, &buffer, PyBUF_SIMPLE | PyBUF_FORMAT);
+ char format = *buffer.format;
+ if (ELEM(format, 'i', 'f', 'd')) {
+ use_buffer = true;
+ }
+ else {
+ PyBuffer_Release(&buffer);
+ }
}
- else if (PyMapping_Check(ob)) {
- PyObject *keys, *vals, *key, *pval;
- int i, len;
- /*yay! we get into recursive stuff now!*/
- keys = PyMapping_Keys(ob);
- vals = PyMapping_Values(ob);
-
- /* we allocate the group first; if we hit any invalid data,
- * we can delete it easily enough.*/
- prop = IDP_New(IDP_GROUP, &val, name);
- len = PyMapping_Length(ob);
- for (i = 0; i < len; i++) {
- key = PySequence_GetItem(keys, i);
- pval = PySequence_GetItem(vals, i);
- if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) {
- IDP_FreeProperty(prop);
- MEM_freeN(prop);
- Py_XDECREF(keys);
- Py_XDECREF(vals);
- Py_XDECREF(key);
- Py_XDECREF(pval);
- /* error is already set */
- return false;
- }
+
+ if (use_buffer) {
+ IDProperty *prop = idp_from_PySequence_Buffer(name, &buffer);
+ PyBuffer_Release(&buffer);
+ return prop;
+ }
+ else {
+ PyObject *ob_seq_fast = PySequence_Fast(ob, "py -> idprop");
+ if (ob_seq_fast != NULL) {
+ IDProperty *prop = idp_from_PySequence_Fast(name, ob_seq_fast);
+ Py_DECREF(ob_seq_fast);
+ return prop;
+ }
+ else {
+ return NULL;
+ }
+ }
+}
+
+static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob)
+{
+ IDProperty *prop;
+ IDPropertyTemplate val = {0};
+
+ PyObject *keys, *vals, *key, *pval;
+ int i, len;
+ /* yay! we get into recursive stuff now! */
+ keys = PyMapping_Keys(ob);
+ vals = PyMapping_Values(ob);
+
+ /* we allocate the group first; if we hit any invalid data,
+ * we can delete it easily enough.*/
+ prop = IDP_New(IDP_GROUP, &val, name);
+ len = PyMapping_Length(ob);
+ for (i = 0; i < len; i++) {
+ key = PySequence_GetItem(keys, i);
+ pval = PySequence_GetItem(vals, i);
+ if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) {
+ IDP_FreeProperty(prop);
+ MEM_freeN(prop);
+ Py_XDECREF(keys);
+ Py_XDECREF(vals);
Py_XDECREF(key);
Py_XDECREF(pval);
+ /* error is already set */
+ return NULL;
}
- Py_XDECREF(keys);
- Py_XDECREF(vals);
+ Py_XDECREF(key);
+ Py_XDECREF(pval);
+ }
+ Py_XDECREF(keys);
+ Py_XDECREF(vals);
+ return prop;
+}
+
+static IDProperty *idp_from_DatablockPointer(const char *name, PyObject *ob, IDPropertyTemplate *val)
+{
+ pyrna_id_FromPyObject(ob, &val->id);
+ return IDP_New(IDP_ID, val, name);
+}
+
+static IDProperty *idp_from_PyObject(PyObject *name_obj, PyObject *ob)
+{
+ IDPropertyTemplate val = {0};
+ const char *name = idp_try_read_name(name_obj);
+ if (name == NULL) {
+ return NULL;
+ }
+
+ if (PyFloat_Check(ob)) {
+ return idp_from_PyFloat(name, ob);
+ }
+ else if (PyLong_Check(ob)) {
+ return idp_from_PyLong(name, ob);
+ }
+ else if (PyUnicode_Check(ob)) {
+ return idp_from_PyUnicode(name, ob);
+ }
+ else if (PyBytes_Check(ob)) {
+ return idp_from_PyBytes(name, ob);
+ }
+ else if (PySequence_Check(ob)) {
+ return idp_from_PySequence(name, ob);
+ }
+ else if (ob == Py_None || pyrna_id_CheckPyObject(ob)) {
+ return idp_from_DatablockPointer(name, ob, &val);
+ }
+ else if (PyMapping_Check(ob)) {
+ return idp_from_PyMapping(name, ob);
}
else {
PyErr_Format(PyExc_TypeError,
"invalid id-property type %.200s not supported",
Py_TYPE(ob)->tp_name);
+ return NULL;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * \note group can be a pointer array or a group.
+ * assume we already checked key is a string.
+ *
+ * \return success.
+ */
+bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob)
+{
+ IDProperty *prop = idp_from_PyObject(name_obj, ob);
+ if (prop == NULL) {
return false;
}
if (group->type == IDP_IDPARRAY) {
IDP_AppendArray(group, prop);
- // IDP_FreeProperty(item); /* IDP_AppendArray does a shallow copy (memcpy), only free memory */
+ /* IDP_AppendArray does a shallow copy (memcpy), only free memory */
MEM_freeN(prop);
}
else {
@@ -613,6 +751,8 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
return idprop_py_from_idp_float(prop);
case IDP_DOUBLE:
return idprop_py_from_idp_double(prop);
+ case IDP_ID:
+ return idprop_py_from_idp_id(prop);
case IDP_ARRAY:
{
PyObject *seq = PyList_New(prop->len);
@@ -1371,6 +1511,44 @@ static PyMappingMethods BPy_IDArray_AsMapping = {
(objobjargproc)BPy_IDArray_ass_subscript
};
+static int itemsize_by_idarray_type(int array_type)
+{
+ if (array_type == IDP_INT) return sizeof(int);
+ if (array_type == IDP_FLOAT) return sizeof(float);
+ if (array_type == IDP_DOUBLE) return sizeof(double);
+ return -1; /* should never happen */
+}
+
+static int BPy_IDArray_getbuffer(BPy_IDArray *self, Py_buffer *view, int flags)
+{
+ IDProperty *prop = self->prop;
+ int itemsize = itemsize_by_idarray_type(prop->subtype);
+ int length = itemsize * prop->len;
+
+ if (PyBuffer_FillInfo(view, (PyObject *)self, IDP_Array(prop), length, false, flags) == -1) {
+ return -1;
+ }
+
+ view->itemsize = itemsize;
+ view->format = (char *)idp_format_from_array_type(prop->subtype);
+
+ Py_ssize_t *shape = MEM_mallocN(sizeof(Py_ssize_t), __func__);
+ shape[0] = prop->len;
+ view->shape = shape;
+
+ return 0;
+}
+
+static void BPy_IDArray_releasebuffer(BPy_IDArray *UNUSED(self), Py_buffer *view)
+{
+ MEM_freeN(view->shape);
+}
+
+static PyBufferProcs BPy_IDArray_Buffer = {
+ (getbufferproc)BPy_IDArray_getbuffer,
+ (releasebufferproc)BPy_IDArray_releasebuffer,
+};
+
PyTypeObject BPy_IDArray_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -1403,7 +1581,7 @@ PyTypeObject BPy_IDArray_Type = {
NULL, /* setattrofunc tp_setattro; */
/* Functions to access object as input/output buffer */
- NULL, /* PyBufferProcs *tp_as_buffer; */
+ &BPy_IDArray_Buffer, /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 7b2d58a1268..2e789d6d4b3 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -918,11 +918,11 @@ char *PyC_FlagSet_AsString(PyC_FlagSet *item)
return cstring;
}
-int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value)
+int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value)
{
for ( ; item->identifier; item++) {
if (STREQ(item->identifier, identifier)) {
- *value = item->value;
+ *r_value = item->value;
return 1;
}
}
@@ -930,9 +930,9 @@ int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *
return 0;
}
-int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *value, const char *error_prefix)
+int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix)
{
- if (PyC_FlagSet_ValueFromID_int(item, identifier, value) == 0) {
+ if (PyC_FlagSet_ValueFromID_int(item, identifier, r_value) == 0) {
const char *enum_str = PyC_FlagSet_AsString(item);
PyErr_Format(PyExc_ValueError,
"%s: '%.200s' not found in (%s)",
@@ -1006,7 +1006,7 @@ PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag)
*
* \note it is caller's responsibility to acquire & release GIL!
*/
-bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename)
+bool PyC_RunString_AsNumber(const char *expr, const char *filename, double *r_value)
{
PyObject *py_dict, *mod, *retval;
bool ok = true;
@@ -1058,10 +1058,10 @@ bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filenam
ok = false;
}
else if (!isfinite(val)) {
- *value = 0.0;
+ *r_value = 0.0;
}
else {
- *value = val;
+ *r_value = val;
}
}
@@ -1070,4 +1070,41 @@ bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filenam
return ok;
}
+bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_value)
+{
+ PyObject *py_dict, *retval;
+ bool ok = true;
+ PyObject *main_mod = NULL;
+
+ PyC_MainModule_Backup(&main_mod);
+
+ py_dict = PyC_DefaultNameSpace(filename);
+
+ retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
+
+ if (retval == NULL) {
+ ok = false;
+ }
+ else {
+ const char *val;
+ Py_ssize_t val_len;
+
+ val = _PyUnicode_AsStringAndSize(retval, &val_len);
+ if (val == NULL && PyErr_Occurred()) {
+ ok = false;
+ }
+ else {
+ char *val_alloc = MEM_mallocN(val_len + 1, __func__);
+ memcpy(val_alloc, val, val_len + 1);
+ *r_value = val_alloc;
+ }
+
+ Py_DECREF(retval);
+ }
+
+ PyC_MainModule_Restore(main_mod);
+
+ return ok;
+}
+
#endif /* #ifndef MATH_STANDALONE */
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 04cfc8801eb..3f89e1d82a0 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -75,12 +75,13 @@ typedef struct PyC_FlagSet {
} PyC_FlagSet;
char *PyC_FlagSet_AsString(PyC_FlagSet *item);
-int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value);
-int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *value, const char *error_prefix);
+int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value);
+int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix);
int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix);
PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag);
-bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename);
+bool PyC_RunString_AsNumber(const char *expr, const char *filename, double *r_value);
+bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_value);
int PyC_ParseBool(PyObject *o, void *p);
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 038c1e7eb10..be4db6477fe 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -55,6 +55,7 @@ set(SRC
bpy_app_handlers.c
bpy_app_ocio.c
bpy_app_oiio.c
+ bpy_app_opensubdiv.c
bpy_app_openvdb.c
bpy_app_sdl.c
bpy_app_translations.c
@@ -89,6 +90,7 @@ set(SRC
bpy_app_handlers.h
bpy_app_ocio.h
bpy_app_oiio.h
+ bpy_app_opensubdiv.h
bpy_app_openvdb.h
bpy_app_sdl.h
bpy_app_translations.h
@@ -295,6 +297,13 @@ if(WITH_OPENIMAGEIO)
)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+ list(APPEND INC
+ ../../../../intern/opensubdiv
+ )
+endif()
+
if(WITH_PLAYER)
add_definitions(-DWITH_PLAYER)
endif()
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index ed7cec2f2d5..8b3464173d2 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -37,6 +37,7 @@
#include "bpy_app_ffmpeg.h"
#include "bpy_app_ocio.h"
#include "bpy_app_oiio.h"
+#include "bpy_app_opensubdiv.h"
#include "bpy_app_openvdb.h"
#include "bpy_app_sdl.h"
#include "bpy_app_build_options.h"
@@ -109,6 +110,7 @@ static PyStructSequence_Field app_info_fields[] = {
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
{(char *)"ocio", (char *)"OpenColorIO library information backend"},
{(char *)"oiio", (char *)"OpenImageIO library information backend"},
+ {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"},
{(char *)"openvdb", (char *)"OpenVDB library information backend"},
{(char *)"sdl", (char *)"SDL library information backend"},
{(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
@@ -117,9 +119,21 @@ static PyStructSequence_Field app_info_fields[] = {
{NULL},
};
+PyDoc_STRVAR(bpy_app_doc,
+"This module contains application values that remain unchanged during runtime.\n"
+"\n"
+"Submodules:\n"
+"\n"
+".. toctree::\n"
+" :maxdepth: 1\n"
+"\n"
+" bpy.app.handlers.rst\n"
+" bpy.app.translations.rst\n"
+);
+
static PyStructSequence_Desc app_info_desc = {
(char *)"bpy.app", /* name */
- (char *)"This module contains application values that remain unchanged during runtime.", /* doc */
+ bpy_app_doc, /* doc */
app_info_fields, /* fields */
ARRAY_SIZE(app_info_fields) - 1
};
@@ -188,6 +202,7 @@ static PyObject *make_app_info(void)
SetObjItem(BPY_app_ffmpeg_struct());
SetObjItem(BPY_app_ocio_struct());
SetObjItem(BPY_app_oiio_struct());
+ SetObjItem(BPY_app_opensubdiv_struct());
SetObjItem(BPY_app_openvdb_struct());
SetObjItem(BPY_app_sdl_struct());
SetObjItem(BPY_app_build_options_struct());
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 1cc2d6f1307..fdc2371c259 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -126,7 +126,7 @@ static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), PyO
/* dummy type because decorators can't be PyCFunctions */
static PyTypeObject BPyPersistent_Type = {
-#if defined(_MSC_VER) || defined(FREE_WINDOWS)
+#if defined(_MSC_VER)
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyVarObject_HEAD_INIT(&PyType_Type, 0)
@@ -206,7 +206,7 @@ PyObject *BPY_app_handlers_struct(void)
{
PyObject *ret;
-#if defined(_MSC_VER) || defined(FREE_WINDOWS)
+#if defined(_MSC_VER)
BPyPersistent_Type.ob_base.ob_base.ob_type = &PyType_Type;
#endif
diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c
new file mode 100644
index 00000000000..7f269baf2b0
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_opensubdiv.c
@@ -0,0 +1,109 @@
+/*
+ * ***** 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): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_opensubdiv.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+
+#include "bpy_app_opensubdiv.h"
+
+#ifdef WITH_OPENSUBDIV
+# include "opensubdiv_capi.h"
+#endif
+
+static PyTypeObject BlenderAppOpenSubdivType;
+
+static PyStructSequence_Field app_opensubdiv_info_fields[] = {
+ {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenSubdiv support")},
+ {(char *)("version"), (char *)("The OpenSubdiv version as a tuple of 3 numbers")},
+ {(char *)("version_string"), (char *)("The OpenSubdiv version formatted as a string")},
+ {NULL}
+};
+
+static PyStructSequence_Desc app_opensubdiv_info_desc = {
+ (char *)"bpy.app.opensubdiv", /* name */
+ (char *)"This module contains information about OpenSubdiv blender is linked against", /* doc */
+ app_opensubdiv_info_fields, /* fields */
+ ARRAY_SIZE(app_opensubdiv_info_fields) - 1
+};
+
+static PyObject *make_opensubdiv_info(void)
+{
+ PyObject *opensubdiv_info;
+ int pos = 0;
+
+ opensubdiv_info = PyStructSequence_New(&BlenderAppOpenSubdivType);
+ if (opensubdiv_info == NULL) {
+ return NULL;
+ }
+
+#ifndef WITH_OPENSUBDIV
+#define SetStrItem(str) \
+ PyStructSequence_SET_ITEM(opensubdiv_info, pos++, PyUnicode_FromString(str))
+#endif
+
+#define SetObjItem(obj) \
+ PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj)
+
+#ifdef WITH_OPENSUBDIV
+ int curversion = openSubdiv_getVersionHex();
+ SetObjItem(PyBool_FromLong(1));
+ SetObjItem(Py_BuildValue("(iii)",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
+ curversion / 10000, (curversion / 100) % 100, curversion % 100));
+#else
+ SetObjItem(PyBool_FromLong(0));
+ SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetStrItem("Unknown");
+#endif
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(opensubdiv_info);
+ return NULL;
+ }
+
+#undef SetStrItem
+#undef SetObjItem
+
+ return opensubdiv_info;
+}
+
+PyObject *BPY_app_opensubdiv_struct(void)
+{
+ PyObject *ret;
+
+ PyStructSequence_InitType(&BlenderAppOpenSubdivType, &app_opensubdiv_info_desc);
+
+ ret = make_opensubdiv_info();
+
+ /* prevent user from creating new instances */
+ BlenderAppOpenSubdivType.tp_init = NULL;
+ BlenderAppOpenSubdivType.tp_new = NULL;
+ /* without this we can't do set(sys.modules) [#29635] */
+ BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer;
+
+ return ret;
+}
diff --git a/source/blender/depsgraph/util/deg_util_hash.h b/source/blender/python/intern/bpy_app_opensubdiv.h
index e490be1a7a1..b1da218b168 100644
--- a/source/blender/depsgraph/util/deg_util_hash.h
+++ b/source/blender/python/intern/bpy_app_opensubdiv.h
@@ -15,27 +15,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Brecht van Lommel
- * Contributor(s): Lukas Toenne
+ * Contributor(s): Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/deg_util_hash.h
- * \ingroup depsgraph
+/** \file blender/python/intern/bpy_app_opensubdiv.h
+ * \ingroup pythonintern
*/
-#pragma once
-
-#include "BLI_utildefines.h"
+#ifndef __BPY_APP_OPENSUBDIV_H__
+#define __BPY_APP_OPENSUBDIV_H__
-#include "BLI_ghash.h"
+PyObject *BPY_app_opensubdiv_struct(void);
-/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */
-BLI_INLINE size_t hash_combine(size_t hash_a, size_t hash_b)
-{
- return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
-}
+#endif /* __BPY_APP_OPENSUBDIV_H__ */
diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c
index 2f4d8e6c325..76dab775953 100644
--- a/source/blender/python/intern/bpy_app_sdl.c
+++ b/source/blender/python/intern/bpy_app_sdl.c
@@ -56,7 +56,7 @@ static PyStructSequence_Field app_sdl_info_fields[] = {
{(char *)"available", (char *)("Boolean, True when SDL is available. This is False when "
"either *supported* is False, or *dynload* is True and "
"Blender cannot find the correct library.")},
- {NULL}
+ {NULL}
};
static PyStructSequence_Desc app_sdl_info_desc = {
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 311f621e13b..7b0daa91523 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -480,11 +480,20 @@ static bool python_script_exec(
* object, but as written in the Python/C API Ref Manual, chapter 2,
* 'FILE structs for different C libraries can be different and
* incompatible'.
- * So now we load the script file data to a buffer */
+ * So now we load the script file data to a buffer.
+ *
+ * Note on use of 'globals()', it's important not copy the dictionary because
+ * tools may inspect 'sys.modules["__main__"]' for variables defined in the code
+ * where using a copy of 'globals()' causes code execution
+ * to leave the main namespace untouched. see: T51444
+ *
+ * This leaves us with the problem of variables being included,
+ * currently this is worked around using 'dict.__del__' it's ugly but works.
+ */
{
const char *pystring =
- "ns = globals().copy()\n"
- "with open(__file__, 'rb') as f: exec(compile(f.read(), __file__, 'exec'), ns)";
+ "with open(__file__, 'rb') as f:"
+ "exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())";
fclose(fp);
@@ -572,21 +581,58 @@ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
/**
* \return success
*/
-bool BPY_execute_string_as_number(bContext *C, const char *expr, double *value, const bool verbose)
+bool BPY_execute_string_as_number(bContext *C, const char *expr, const bool verbose, double *r_value)
{
PyGILState_STATE gilstate;
bool ok = true;
- if (!value || !expr) return -1;
+ if (!r_value || !expr) {
+ return -1;
+ }
+
+ if (expr[0] == '\0') {
+ *r_value = 0.0;
+ return ok;
+ }
+
+ bpy_context_set(C, &gilstate);
+
+ ok = PyC_RunString_AsNumber(expr, "<blender button>", r_value);
+
+ if (ok == false) {
+ if (verbose) {
+ BPy_errors_to_report_ex(CTX_wm_reports(C), false, false);
+ }
+ else {
+ PyErr_Clear();
+ }
+ }
+
+ bpy_context_clear(C, &gilstate);
+
+ return ok;
+}
+
+/**
+ * \return success
+ */
+bool BPY_execute_string_as_string(bContext *C, const char *expr, const bool verbose, char **r_value)
+{
+ PyGILState_STATE gilstate;
+ bool ok = true;
+
+ if (!r_value || !expr) {
+ return -1;
+ }
if (expr[0] == '\0') {
- *value = 0.0;
+ *r_value = NULL;
return ok;
}
bpy_context_set(C, &gilstate);
- ok = PyC_RunString_AsNumber(expr, value, "<blender button>");
+ ok = PyC_RunString_AsString(expr, "<blender button>", r_value);
if (ok == false) {
if (verbose) {
@@ -602,6 +648,7 @@ bool BPY_execute_string_as_number(bContext *C, const char *expr, double *value,
return ok;
}
+
bool BPY_execute_string_ex(bContext *C, const char *expr, bool use_eval)
{
PyGILState_STATE gilstate;
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index 11e27ca3e3c..90719905a79 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -118,7 +118,7 @@ static void operator_properties_init(wmOperatorType *ot)
}
-void operator_wrapper(wmOperatorType *ot, void *userdata)
+void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata)
{
/* take care not to overwrite anything set in
* WM_operatortype_append_ptr before opfunc() is called */
@@ -134,7 +134,7 @@ void operator_wrapper(wmOperatorType *ot, void *userdata)
operator_properties_init(ot);
}
-void macro_wrapper(wmOperatorType *ot, void *userdata)
+void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata)
{
wmOperatorType *data = (wmOperatorType *)userdata;
diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h
index 05a566a1485..0828c58e2bd 100644
--- a/source/blender/python/intern/bpy_operator_wrap.h
+++ b/source/blender/python/intern/bpy_operator_wrap.h
@@ -33,7 +33,7 @@ struct wmOperatorType;
PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args);
/* exposed to rna/wm api */
-void operator_wrapper(struct wmOperatorType *ot, void *userdata);
-void macro_wrapper(struct wmOperatorType *ot, void *userdata);
+void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata);
+void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata);
#endif
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index e61018865ab..c7787ba9682 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -50,11 +50,13 @@
#include "../generic/py_capi_utils.h"
/* initial definition of callback slots we'll probably have more than 1 */
-#define BPY_DATA_CB_SLOT_SIZE 3
-
-#define BPY_DATA_CB_SLOT_UPDATE 0
-#define BPY_DATA_CB_SLOT_GET 1
-#define BPY_DATA_CB_SLOT_SET 2
+enum {
+ BPY_DATA_CB_SLOT_UPDATE = 0,
+ BPY_DATA_CB_SLOT_GET = 1,
+ BPY_DATA_CB_SLOT_SET = 2,
+ BPY_DATA_CB_SLOT_POLL = 3,
+ BPY_DATA_CB_SLOT_SIZE = 4,
+};
extern BPy_StructRNA *bpy_context_module;
@@ -71,6 +73,9 @@ static EnumPropertyItem property_flag_items[] = {
" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', 'PROPORTIONAL'," \
"'TEXTEDIT_UPDATE'].\n" \
" :type options: set\n" \
+" :arg poll: function to be called to determine whether an item is valid for this property.\n" \
+" The function must take 2 values (self,object) and return Bool.\n" \
+" :type poll: function\n" \
static EnumPropertyItem property_flag_enum_items[] = {
{PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""},
@@ -230,7 +235,7 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw)
static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop)
{
PyGILState_STATE gilstate;
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -279,7 +284,7 @@ static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struc
static int bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -337,7 +342,7 @@ static int bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p
static void bpy_prop_boolean_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -389,9 +394,54 @@ static void bpy_prop_boolean_set_cb(struct PointerRNA *ptr, struct PropertyRNA *
}
}
+static int bpy_prop_poll_cb(struct PointerRNA *self, PointerRNA candidate, struct PropertyRNA *prop)
+{
+ PyObject *py_self;
+ PyObject *py_candidate;
+ PyObject *py_func;
+ PyObject **py_data = RNA_property_py_data_get(prop);
+ PyObject *args;
+ PyObject *ret;
+ bool result;
+ const int is_write_ok = pyrna_write_check();
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ BLI_assert(self != NULL);
+
+ py_self = pyrna_struct_as_instance(self);
+ py_candidate = pyrna_struct_as_instance(&candidate);
+ py_func = py_data[BPY_DATA_CB_SLOT_POLL];
+
+ if (!is_write_ok)
+ pyrna_write_set(true);
+
+ args = PyTuple_New(2);
+ PyTuple_SET_ITEM(args, 0, py_self);
+ PyTuple_SET_ITEM(args, 1, py_candidate);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ result = false;
+ }
+ else {
+ result = PyObject_IsTrue(ret);
+ Py_DECREF(ret);
+ }
+
+ PyGILState_Release(gilstate);
+ if (!is_write_ok)
+ pyrna_write_set(false);
+
+ return result;
+}
+
static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -452,7 +502,7 @@ static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, struct Propert
static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -513,7 +563,7 @@ static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct Propert
static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -571,7 +621,7 @@ static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
static void bpy_prop_int_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -625,7 +675,7 @@ static void bpy_prop_int_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop
static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -686,7 +736,7 @@ static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA
static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -747,7 +797,7 @@ static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA
static float bpy_prop_float_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -805,7 +855,7 @@ static float bpy_prop_float_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p
static void bpy_prop_float_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float value)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -859,7 +909,7 @@ static void bpy_prop_float_set_cb(struct PointerRNA *ptr, struct PropertyRNA *pr
static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float *values)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -920,7 +970,7 @@ static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, struct PropertyR
static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const float *values)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -981,7 +1031,7 @@ static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyR
static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, char *value)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -1040,7 +1090,7 @@ static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p
static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -1102,7 +1152,7 @@ static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA
static void bpy_prop_string_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const char *value)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -1163,7 +1213,7 @@ static void bpy_prop_string_set_cb(struct PointerRNA *ptr, struct PropertyRNA *p
static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -1221,7 +1271,7 @@ static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop
static void bpy_prop_enum_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value)
{
- PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject **py_data = RNA_property_py_data_get(prop);
PyObject *py_func;
PyObject *args;
PyObject *self;
@@ -1598,6 +1648,16 @@ static void bpy_prop_callback_assign_update(struct PropertyRNA *prop, PyObject *
}
}
+static void bpy_prop_callback_assign_pointer(struct PropertyRNA *prop, PyObject *poll_cb)
+{
+ if (poll_cb && poll_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ RNA_def_property_poll_runtime(prop, (void *) bpy_prop_poll_cb);
+ py_data[BPY_DATA_CB_SLOT_POLL] = poll_cb;
+ }
+}
+
static void bpy_prop_callback_assign_boolean(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
{
BooleanPropertyGetFunc rna_get_cb = NULL;
@@ -1904,7 +1964,7 @@ static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop, PyObject *ge
" :type set: function\n" \
#define BPY_PROPDEF_TYPE_DOC \
-" :arg type: A subclass of :class:`bpy.types.PropertyGroup`.\n" \
+" :arg type: A subclass of :class:`bpy.types.PropertyGroup` or :class:`bpy.types.ID`.\n" \
" :type type: class\n" \
#if 0
@@ -2772,7 +2832,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
Py_RETURN_NONE;
}
-static StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix)
+StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix)
{
StructRNA *srna;
@@ -2782,25 +2842,18 @@ static StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix
PyObject *msg = PyC_ExceptionBuffer();
const char *msg_char = _PyUnicode_AsString(msg);
PyErr_Format(PyExc_TypeError,
- "%.200s expected an RNA type derived from PropertyGroup, failed with: %s",
+ "%.200s expected an RNA type, failed with: %s",
error_prefix, msg_char);
Py_DECREF(msg);
}
else {
PyErr_Format(PyExc_TypeError,
- "%.200s expected an RNA type derived from PropertyGroup, failed with type '%s'",
+ "%.200s expected an RNA type, failed with type '%s'",
error_prefix, Py_TYPE(value)->tp_name);
}
return NULL;
}
- if (!RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s expected an RNA type derived from PropertyGroup",
- error_prefix);
- return NULL;
- }
-
return srna;
}
@@ -2809,6 +2862,7 @@ PyDoc_STRVAR(BPy_PointerProperty_doc,
"name=\"\", "
"description=\"\", "
"options={'ANIMATABLE'}, "
+ "poll=None, "
"update=None)\n"
"\n"
" Returns a new pointer property definition.\n"
@@ -2819,14 +2873,14 @@ BPY_PROPDEF_DESC_DOC
BPY_PROPDEF_OPTIONS_DOC
BPY_PROPDEF_UPDATE_DOC
);
-static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
+PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
BPY_PROPDEF_HEAD(PointerProperty);
if (srna) {
- static const char *kwlist[] = {"attr", "type", "name", "description", "options", "update", NULL};
+ static const char *kwlist[] = {"attr", "type", "name", "description", "options", "poll", "update", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
PropertyRNA *prop;
@@ -2834,33 +2888,47 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k
PyObject *type = Py_None;
PyObject *pyopts = NULL;
int opts = 0;
- PyObject *update_cb = NULL;
+ PyObject *update_cb = NULL, *poll_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#O|ssO!O:PointerProperty",
+ "s#O|ssO!OOO:PointerProperty",
(char **)kwlist, &id, &id_len,
&type, &name, &description,
&PySet_Type, &pyopts,
- &update_cb))
+ &poll_cb, &update_cb))
{
return NULL;
}
BPY_PROPDEF_CHECK(PointerProperty, property_flag_items);
- ptype = pointer_type_from_py(type, "PointerProperty(...):");
+ ptype = pointer_type_from_py(type, "PointerProperty(...)");
if (!ptype)
return NULL;
-
+ if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup) && !RNA_struct_is_ID(ptype)) {
+ PyErr_Format(PyExc_TypeError,
+ "PointerProperty(...) expected an RNA type derived from %.200s or %.200s",
+ RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup));
+ return NULL;
+ }
if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
return NULL;
}
-
+ if (bpy_prop_callback_check(poll_cb, "poll", 2) == -1) {
+ return NULL;
+ }
prop = RNA_def_pointer_runtime(srna, id, ptype, name ? name : id, description);
if (pyopts) {
bpy_prop_assign_flag(prop, opts);
}
+
+ if (RNA_struct_idprops_contains_datablock(ptype)) {
+ if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
+ RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES);
+ }
+ }
bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_pointer(prop, poll_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
@@ -2879,7 +2947,7 @@ BPY_PROPDEF_NAME_DOC
BPY_PROPDEF_DESC_DOC
BPY_PROPDEF_OPTIONS_DOC
);
-static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
+PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
@@ -2910,17 +2978,30 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject
if (!ptype)
return NULL;
+ if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) {
+ PyErr_Format(PyExc_TypeError,
+ "CollectionProperty(...) expected an RNA type derived from %.200s",
+ RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup));
+ return NULL;
+ }
+
prop = RNA_def_collection_runtime(srna, id, ptype, name ? name : id, description);
if (pyopts) {
bpy_prop_assign_flag(prop, opts);
}
+
+ if (RNA_struct_idprops_contains_datablock(ptype)) {
+ if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
+ RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES);
+ }
+ }
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(BPy_RemoveProperty_doc,
-".. function:: RemoveProperty(cls, attr="")\n"
+".. function:: RemoveProperty(cls, attr)\n"
"\n"
" Removes a dynamically defined property.\n"
"\n"
diff --git a/source/blender/python/intern/bpy_props.h b/source/blender/python/intern/bpy_props.h
index c9934ca0cf3..614c1b4b708 100644
--- a/source/blender/python/intern/bpy_props.h
+++ b/source/blender/python/intern/bpy_props.h
@@ -30,6 +30,10 @@
PyObject *BPY_rna_props(void);
+PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw);
+PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw);
+StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix);
+
#define PYRNA_STACK_ARRAY 32
#endif
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 2fd46ab94f0..eda880d4dce 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -806,7 +806,7 @@ static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op)
switch (op) {
case Py_NE:
ok = !ok;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
@@ -836,7 +836,7 @@ static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op)
switch (op) {
case Py_NE:
ok = !ok;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
@@ -1934,16 +1934,10 @@ static int pyrna_py_to_prop(
}
else {
/* data == NULL, assign to RNA */
- if (value == Py_None) {
- PointerRNA valueptr = {{NULL}};
- RNA_property_pointer_set(ptr, prop, valueptr);
- }
- else if (RNA_struct_is_a(param->ptr.type, ptr_type)) {
- RNA_property_pointer_set(ptr, prop, param->ptr);
- }
- else {
+ if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type))
+ RNA_property_pointer_set(ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr);
+ else
raise_error = true;
- }
}
if (raise_error) {
@@ -3277,6 +3271,20 @@ static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObje
return -1;
}
+ if (value && BPy_StructRNA_Check(value)) {
+ BPy_StructRNA *val = (BPy_StructRNA *)value;
+ if (val && self->ptr.type && val->ptr.type) {
+ if (!RNA_struct_idprops_datablock_allowed(self->ptr.type) &&
+ RNA_struct_idprops_contains_datablock(val->ptr.type))
+ {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "bpy_struct[key] = val: datablock id properties not supported for this type");
+ return -1;
+ }
+ }
+ }
+
return BPy_Wrap_SetMapItem(group, key, value);
}
@@ -5160,7 +5168,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
ret = Matrix_CreatePyObject(data, 3, 3, NULL);
break;
}
- /* fall-through */
+ ATTR_FALLTHROUGH;
#endif
default:
ret = PyTuple_New(len);
@@ -5684,7 +5692,7 @@ PyTypeObject pyrna_struct_meta_idprop_Type = {
NULL, /* struct PyMethodDef *tp_methods; */
NULL, /* struct PyMemberDef *tp_members; */
NULL, /* struct PyGetSetDef *tp_getset; */
-#if defined(_MSC_VER) || defined(FREE_WINDOWS)
+#if defined(_MSC_VER)
NULL, /* defer assignment */
#else
&PyType_Type, /* struct _typeobject *tp_base; */
@@ -6259,7 +6267,7 @@ static PyTypeObject pyrna_prop_collection_iter_Type = {
NULL, /* reprfunc tp_str; */
/* will only use these if this is a subtype of a py class */
-#if defined(_MSC_VER) || defined(FREE_WINDOWS)
+#if defined(_MSC_VER)
NULL, /* defer assignment */
#else
PyObject_GenericGetAttr, /* getattrofunc tp_getattro; */
@@ -6292,7 +6300,7 @@ static PyTypeObject pyrna_prop_collection_iter_Type = {
#endif
/*** Added in release 2.2 ***/
/* Iterators */
-#if defined(_MSC_VER) || defined(FREE_WINDOWS)
+#if defined(_MSC_VER)
NULL, /* defer assignment */
#else
PyObject_SelfIter, /* getiterfunc tp_iter; */
@@ -6745,7 +6753,7 @@ PyObject *pyrna_id_CreatePyObject(ID *id)
bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
{
- if (BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *)obj)->ptr.type))) {
+ if (pyrna_id_CheckPyObject(obj)) {
*id = ((BPy_StructRNA *)obj)->ptr.id.data;
return true;
}
@@ -6755,6 +6763,11 @@ bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
}
}
+bool pyrna_id_CheckPyObject(PyObject *obj)
+{
+ return BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *) obj)->ptr.type));
+}
+
void BPY_rna_init(void)
{
#ifdef USE_MATHUTILS /* register mathutils callbacks, ok to run more than once. */
@@ -6763,7 +6776,7 @@ void BPY_rna_init(void)
#endif
/* for some reason MSVC complains of these */
-#if defined(_MSC_VER) || defined(FREE_WINDOWS)
+#if defined(_MSC_VER)
pyrna_struct_meta_idprop_Type.tp_base = &PyType_Type;
pyrna_prop_collection_iter_Type.tp_iter = PyObject_SelfIter;
@@ -7089,6 +7102,21 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item
args_fake = PyTuple_New(1);
PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject);
+ PyObject *type = PyDict_GetItemString(py_kw, "type");
+ StructRNA *type_srna = srna_from_self(type, "");
+ if (type_srna) {
+ if (!RNA_struct_idprops_datablock_allowed(srna) &&
+ (*(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_PointerProperty ||
+ *(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_CollectionProperty) &&
+ RNA_struct_idprops_contains_datablock(type_srna))
+ {
+ PyErr_Format(PyExc_ValueError,
+ "bpy_struct \"%.200s\" doesn't support datablock properties \n",
+ RNA_struct_identifier(srna));
+ return -1;
+ }
+ }
+
py_ret = PyObject_Call(py_func, args_fake, py_kw);
if (py_ret) {
@@ -7237,15 +7265,12 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
{
const ListBase *lb;
Link *link;
- FunctionRNA *func;
- PropertyRNA *prop;
const char *class_type = RNA_struct_identifier(srna);
StructRNA *srna_base = RNA_struct_base(srna);
PyObject *py_class = (PyObject *)py_data;
PyObject *base_class = RNA_struct_py_type_get(srna);
PyObject *item;
- int i, flag, arg_count, func_arg_count, func_arg_min_count = 0;
- bool is_staticmethod;
+ int i, arg_count, func_arg_count, func_arg_min_count = 0;
const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */
if (srna_base) {
@@ -7266,9 +7291,12 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
lb = RNA_struct_type_functions(srna);
i = 0;
for (link = lb->first; link; link = link->next) {
- func = (FunctionRNA *)link;
- flag = RNA_function_flag(func);
- is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
+ FunctionRNA *func = (FunctionRNA *)link;
+ const int flag = RNA_function_flag(func);
+ /* TODO(campbell): this is used for classmethod's too,
+ * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg.
+ * Keep this as-is since its working but we should be using 'FUNC_USE_SELF_TYPE' for many functions. */
+ const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
if (!(flag & FUNC_REGISTER))
continue;
@@ -7294,7 +7322,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
if (is_staticmethod) {
if (PyMethod_Check(item) == 0) {
PyErr_Format(PyExc_TypeError,
- "expected %.200s, %.200s class \"%.200s\" attribute to be a method, not a %.200s",
+ "expected %.200s, %.200s class \"%.200s\" "
+ "attribute to be a static/class method, not a %.200s",
class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name);
return -1;
}
@@ -7303,7 +7332,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
else {
if (PyFunction_Check(item) == 0) {
PyErr_Format(PyExc_TypeError,
- "expected %.200s, %.200s class \"%.200s\" attribute to be a function, not a %.200s",
+ "expected %.200s, %.200s class \"%.200s\" "
+ "attribute to be a function, not a %.200s",
class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name);
return -1;
}
@@ -7315,7 +7345,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
/* note, the number of args we check for and the number of args we give to
- * @staticmethods are different (quirk of python),
+ * '@staticmethods' are different (quirk of python),
* this is why rna_function_arg_count() doesn't return the value -1*/
if (is_staticmethod) {
func_arg_count++;
@@ -7346,8 +7376,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
lb = RNA_struct_type_properties(srna);
for (link = lb->first; link; link = link->next) {
const char *identifier;
- prop = (PropertyRNA *)link;
- flag = RNA_property_flag(prop);
+ PropertyRNA *prop = (PropertyRNA *)link;
+ const int flag = RNA_property_flag(prop);
if (!(flag & PROP_REGISTER))
continue;
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index e38d4f095d6..605f79b1ad8 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -179,6 +179,7 @@ PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop);
/* extern'd by other modules which don't deal closely with RNA */
PyObject *pyrna_id_CreatePyObject(struct ID *id);
bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id);
+bool pyrna_id_CheckPyObject(PyObject *obj);
/* operators also need this to set args */
int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const bool all_args, const char *error_prefix);
diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c
index 974d7c5549c..e0c70483e3c 100644
--- a/source/blender/python/intern/bpy_utils_units.c
+++ b/source/blender/python/intern/bpy_utils_units.c
@@ -201,7 +201,7 @@ static PyObject *bpyunits_to_value(PyObject *UNUSED(self), PyObject *args, PyObj
bUnit_ReplaceString(str, (int)str_len, uref, scale, usys, ucat);
- if (!PyC_RunString_AsNumber(str, &result, "<bpy_units_api>")) {
+ if (!PyC_RunString_AsNumber(str, "<bpy_units_api>", &result)) {
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 5c505247a97..1afb1d7be90 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -1,4 +1,4 @@
-/*
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -38,18 +38,31 @@
#endif
PyDoc_STRVAR(M_Mathutils_doc,
-"This module provides access to the math classes:\n"
+"This module provides access to math operations.\n"
+"\n"
+".. note::\n"
+"\n"
+" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
+" such as tuples, lists."
+"\n\n"
+"Submodules:\n"
+"\n"
+".. toctree::\n"
+" :maxdepth: 1\n"
+"\n"
+" mathutils.geometry.rst\n"
+" mathutils.bvhtree.rst\n"
+" mathutils.kdtree.rst\n"
+" mathutils.interpolate.rst\n"
+" mathutils.noise.rst\n"
+"\n"
+"The :mod:`mathutils` module provides the following classes:\n"
"\n"
"- :class:`Color`,\n"
"- :class:`Euler`,\n"
"- :class:`Matrix`,\n"
"- :class:`Quaternion`,\n"
"- :class:`Vector`,\n"
-"\n"
-".. note::\n"
-"\n"
-" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
-" such as tuples, lists."
);
static int mathutils_array_parse_fast(float *array,
int size,
@@ -219,7 +232,7 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
error_prefix, size, array_min);
return -1;
}
-
+
*array = PyMem_Malloc(size * sizeof(float));
memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float));
return size;
@@ -422,7 +435,7 @@ static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb)
{
unsigned char i;
-
+
/* find the first free slot */
for (i = 0; mathutils_callbacks[i]; i++) {
if (mathutils_callbacks[i] == cb) /* already registered? */
@@ -625,14 +638,14 @@ PyMODINIT_FUNC PyInit_mathutils(void)
return NULL;
mod = PyModule_Create(&M_Mathutils_module_def);
-
+
/* each type has its own new() function */
PyModule_AddObject(mod, vector_Type.tp_name, (PyObject *)&vector_Type);
PyModule_AddObject(mod, matrix_Type.tp_name, (PyObject *)&matrix_Type);
PyModule_AddObject(mod, euler_Type.tp_name, (PyObject *)&euler_Type);
PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type);
PyModule_AddObject(mod, color_Type.tp_name, (PyObject *)&color_Type);
-
+
/* submodule */
PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry()));
/* XXX, python doesnt do imports with this usefully yet
diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c
index add8c2451ff..9997cd9c1f5 100644
--- a/source/blender/python/mathutils/mathutils_Color.c
+++ b/source/blender/python/mathutils/mathutils_Color.c
@@ -173,7 +173,7 @@ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op)
switch (op) {
case Py_NE:
ok = !ok;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index 54adc826af7..9492b6d67f3 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -65,7 +65,7 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
case 2:
if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1)
return NULL;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case 1:
if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1)
return NULL;
@@ -370,7 +370,7 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
switch (op) {
case Py_NE:
ok = !ok;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 4e980e4c0e6..e368e8871f3 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -1301,7 +1301,7 @@ PyDoc_STRVAR(Matrix_to_scale_doc,
" :return: Return the scale of a matrix.\n"
" :rtype: :class:`Vector`\n"
"\n"
-" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
+" .. note:: This method does not return a negative scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
);
static PyObject *Matrix_to_scale(MatrixObject *self)
{
@@ -1390,11 +1390,11 @@ PyDoc_STRVAR(Matrix_invert_doc,
"\n"
" Set the matrix to its inverse.\n"
"\n"
-" :arg fallback: Set the matrix to this value when the inverse can't be calculated\n"
+" :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n"
" (instead of raising a :exc:`ValueError` exception).\n"
" :type fallback: :class:`Matrix`\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n"
+" .. seealso:: `Inverse matrix <https://en.wikipedia.org/wiki/Inverse_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_invert(MatrixObject *self, PyObject *args)
{
@@ -1505,7 +1505,7 @@ PyDoc_STRVAR(Matrix_invert_safe_doc,
" If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n"
" If tweaked matrix is still degenerated, set to the identity matrix instead.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n"
+" .. seealso:: `Inverse Matrix <https://en.wikipedia.org/wiki/Inverse_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_invert_safe(MatrixObject *self)
{
@@ -1554,9 +1554,9 @@ PyDoc_STRVAR(Matrix_adjugate_doc,
"\n"
" Set the matrix to its adjugate.\n"
"\n"
-" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n"
+" .. note:: When the matrix cannot be adjugated a :exc:`ValueError` exception is raised.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Adjugate_matrix>\n"
+" .. seealso:: `Adjugate matrix <https://en.wikipedia.org/wiki/Adjugate_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_adjugate(MatrixObject *self)
{
@@ -1641,9 +1641,9 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
PyDoc_STRVAR(Matrix_decompose_doc,
".. method:: decompose()\n"
"\n"
-" Return the location, rotation and scale components of this matrix.\n"
+" Return the translation, rotation and scale components of this matrix.\n"
"\n"
-" :return: loc, rot, scale triple.\n"
+" :return: trans, rot, scale triple.\n"
" :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)"
);
static PyObject *Matrix_decompose(MatrixObject *self)
@@ -1709,10 +1709,10 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
/* TODO, different sized matrix */
if (self->num_col == 4 && self->num_row == 4) {
- blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac);
+ interp_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac);
}
else if (self->num_col == 3 && self->num_row == 3) {
- blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac);
+ interp_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac);
}
else {
PyErr_SetString(PyExc_ValueError,
@@ -1733,7 +1733,7 @@ PyDoc_STRVAR(Matrix_determinant_doc,
" :return: Return the determinant of a matrix.\n"
" :rtype: float\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Determinant>\n"
+" .. seealso:: `Determinant <https://en.wikipedia.org/wiki/Determinant>` on Wikipedia.\n"
);
static PyObject *Matrix_determinant(MatrixObject *self)
{
@@ -1755,7 +1755,7 @@ PyDoc_STRVAR(Matrix_transpose_doc,
"\n"
" Set the matrix to its transpose.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Transpose>\n"
+" .. seealso:: `Transpose <https://en.wikipedia.org/wiki/Transpose>` on Wikipedia.\n"
);
static PyObject *Matrix_transpose(MatrixObject *self)
{
@@ -1887,10 +1887,10 @@ PyDoc_STRVAR(Matrix_identity_doc,
"\n"
" Set the matrix to the identity matrix.\n"
"\n"
-" .. note:: An object with zero location and rotation, a scale of one,\n"
+" .. note:: An object with a location and rotation of zero, and a scale of one\n"
" will have an identity matrix.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Identity_matrix>\n"
+" .. seealso:: `Identity matrix <https://en.wikipedia.org/wiki/Identity_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_identity(MatrixObject *self)
{
@@ -2034,7 +2034,7 @@ static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op)
switch (op) {
case Py_NE:
ok = !ok;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 71b3cf8ddac..d283c717a46 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -552,7 +552,7 @@ static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op)
switch (op) {
case Py_NE:
ok = !ok;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case Py_EQ:
res = ok ? Py_False : Py_True;
break;
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 569b207c966..a12bdd910c3 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
../depsgraph
../makesdna
../makesrna
+ ../nodes
../physics
../../../intern/atomic
../../../intern/guardedalloc
@@ -165,10 +166,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_CYCLES AND WITH_CYCLES_DEBUG)
- add_definitions(-DWITH_CYCLES_DEBUG)
-endif()
-
if(APPLE)
# SSE math is enabled by default on x86_64
if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index f83a210275f..52491673612 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -96,6 +96,7 @@ typedef struct RenderEngineType {
void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
+ void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl);
/* RNA integration */
ExtensionRNA ext;
@@ -139,7 +140,8 @@ void RE_result_load_from_file(struct RenderResult *result, struct ReportList *re
struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname);
void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result);
-void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results);
+void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername);
+void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int highlight, int merge_results);
const char *RE_engine_active_view_get(RenderEngine *engine);
void RE_engine_active_view_set(RenderEngine *engine, const char *viewname);
@@ -160,6 +162,9 @@ bool RE_engine_is_external(struct Render *re);
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe);
+void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
+ const char *name, int channels, const char *chanid, int type);
+
/* Engine Types */
void RE_engines_init(void);
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index f535aa5aa71..0d2e29ba4c8 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -83,25 +83,19 @@ typedef struct RenderView {
typedef struct RenderPass {
struct RenderPass *next, *prev;
- int passtype, channels;
+ int channels;
char name[64]; /* amount defined in openexr_multi.h */
char chan_id[8]; /* amount defined in openexr_multi.h */
float *rect;
int rectx, recty;
- char internal_name[64]; /* EXR_PASS_MAXNAME */
+ char fullname[64]; /* EXR_PASS_MAXNAME */
char view[64]; /* EXR_VIEW_MAXNAME */
int view_id; /* quick lookup */
- int debug_type;
+ int pad;
} RenderPass;
-enum {
- RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES = 0,
- RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1,
- RENDER_PASS_DEBUG_RAY_BOUNCES = 2,
- RENDER_PASS_DEBUG_BVH_INTERSECTIONS = 3,
-};
/* a renderlayer is a full image, but with all passes and samples */
/* size of the rects is defined in RenderResult */
@@ -236,7 +230,7 @@ void RE_render_result_rect_from_ibuf(
struct ImBuf *ibuf, const int view_id);
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
-float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname);
+float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname);
/* add passes for grease pencil */
struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layername, const char *viewname);
@@ -345,6 +339,7 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd);
bool RE_layers_have_name(struct RenderResult *result);
+struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname);
struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname);
/* shaded view or baking options */
@@ -381,7 +376,7 @@ bool RE_allow_render_generic_object(struct Object *ob);
/* RE_updateRenderInstances flag */
enum {
RE_OBJECT_INSTANCES_UPDATE_VIEW = (1 << 0),
- RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1),
+ RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1)
};
void RE_updateRenderInstances(Render *re, int flag);
@@ -394,13 +389,5 @@ struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *
RenderResult *RE_DuplicateRenderResult(RenderResult *rr);
-/******* Debug pass helper functions *********/
-
-#ifdef WITH_CYCLES_DEBUG
-int RE_debug_pass_num_channels_get(int pass_type);
-const char *RE_debug_pass_name_get(int pass_type);
-int RE_debug_pass_type_get(struct Render *re);
-#endif
-
#endif /* __RE_PIPELINE_H__ */
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index ae389fdfd2e..b64c0c8fc52 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -178,6 +178,7 @@ typedef struct ShadeInput {
unsigned int lay;
int layflag, passflag, combinedflag;
+ short object_pass_index;
struct Group *light_override;
struct Material *mat_override;
@@ -241,6 +242,9 @@ enum {
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4];
+float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi);
+float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi);
+
enum {
RE_VIEW_MATRIX,
RE_VIEWINV_MATRIX,
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 0c4f4e20325..4057d8c1052 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -67,6 +67,11 @@ void render_result_views_new(struct RenderResult *rr, struct RenderData *rd);
void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart);
+/* Add Passes */
+
+void render_result_clone_passes(struct Render *re, struct RenderResult *rr, const char *viewname);
+void render_result_add_pass(struct RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname);
+
/* Free */
void render_result_free(struct RenderResult *rr);
@@ -84,7 +89,7 @@ void render_result_exr_file_begin(struct Render *re);
void render_result_exr_file_end(struct Render *re);
/* render pass wrapper for gpencil */
-struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, int passtype, const char *viewname);
+struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, const char *name, const char *viewname);
void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname);
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index b3a5ccdae17..f0323340899 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -382,6 +382,8 @@ typedef struct ObjectInstanceRen {
float part_co[3];
float part_vel[3];
float part_avel[3];
+
+ unsigned int random_id;
} ObjectInstanceRen;
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 7254fd25ee6..f4c4a50ac27 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -34,6 +34,12 @@
#include "render_types.h"
+#include "RE_engine.h"
+
+#include "DNA_node_types.h"
+
+#include "NOD_composite.h"
+
struct ShadeInput;
struct ShadeResult;
struct World;
@@ -77,6 +83,8 @@ void zbufshade_sss_tile(struct RenderPart *pa);
int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp);
+void render_internal_update_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl);
+
/* -------- ray.c ------- */
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 73424a4e846..588c327ab91 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -684,6 +684,10 @@ void RE_bake_pixels_populate(
int mat_nr = mp->mat_nr;
int image_id = bake_images->lookup[mat_nr];
+ if (image_id < 0) {
+ continue;
+ }
+
bd.bk_image = &bake_images->data[image_id];
bd.primitive_id = ++p_id;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 263ea3d4ef2..41ff8e046e7 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -4701,6 +4701,12 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
if (ob->particlesystem.first) {
psysindex= 1;
for (psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) {
+ /* It seems that we may generate psys->renderdata recursively in some nasty intricated cases of
+ * several levels of bupliobject (see T51524).
+ * For now, basic rule is, do not restore psys if it was already in 'render state'.
+ * Another, more robust solution could be to add some reference counting to that renderdata... */
+ const bool psys_has_renderdata = (psys->renderdata != NULL);
+
if (!psys_check_enabled(ob, psys, G.is_rendering))
continue;
@@ -4712,8 +4718,9 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
if (dob)
psys->flag |= PSYS_USE_IMAT;
init_render_object_data(re, obr, timeoffset);
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
+ if (!(re->r.scemode & R_VIEWPORT_PREVIEW) && !psys_has_renderdata) {
psys_render_restore(ob, psys);
+ }
psys->flag &= ~PSYS_USE_IMAT;
/* only add instance for objects that have not been used for dupli */
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index d97e18d6511..156b4215992 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -61,6 +61,7 @@
#include "renderpipeline.h"
#include "texture.h"
#include "zbuf.h"
+#include "render_result.h"
/* ------------------------------------------------------------------------- */
@@ -142,8 +143,8 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
/* set up renderdata */
render_copy_renderdata(&envre->r, &re->r);
envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
- BLI_listbase_clear(&envre->r.layers);
- BLI_listbase_clear(&envre->r.views);
+ BLI_freelistN(&envre->r.layers);
+ BLI_freelistN(&envre->r.views);
envre->r.filtertype = 0;
envre->r.tilex = envre->r.xsch / 2;
envre->r.tiley = envre->r.ysch / 2;
@@ -493,13 +494,20 @@ static void render_envmap(Render *re, EnvMap *env)
env_rotate_scene(envre, tmat, 0);
if (re->test_break(re->tbh) == 0) {
- RenderLayer *rl = envre->result->layers.first;
int y;
float *alpha;
float *rect;
+ if (envre->result->do_exr_tile) {
+ BLI_rw_mutex_lock(&envre->resultmutex, THREAD_LOCK_WRITE);
+ render_result_exr_file_end(envre);
+ BLI_rw_mutex_unlock(&envre->resultmutex);
+ }
+
+ RenderLayer *rl = envre->result->layers.first;
+
/* envmap is rendered independently of multiview */
- rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, "");
+ rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, "");
ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat);
memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index fd9d95c63b6..a581f7bd198 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -62,13 +62,14 @@
#include "renderpipeline.h"
#include "render_types.h"
#include "render_result.h"
+#include "rendercore.h"
/* Render Engine Types */
static RenderEngineType internal_render_type = {
NULL, NULL,
"BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes,
{NULL, NULL, NULL}
};
@@ -77,7 +78,7 @@ static RenderEngineType internal_render_type = {
static RenderEngineType internal_game_type = {
NULL, NULL,
"BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -212,6 +213,8 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w,
/* can be NULL if we CLAMP the width or height to 0 */
if (result) {
+ render_result_clone_passes(re, result, viewname);
+
RenderPart *pa;
/* Copy EXR tile settings, so pipeline knows whether this is a result
@@ -245,7 +248,18 @@ void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
}
}
-void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int merge_results)
+void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername)
+{
+ Render *re = engine->re;
+
+ if (!re || !re->result) {
+ return;
+ }
+
+ render_result_add_pass(re->result, name, channels, chan_id, layername, NULL);
+}
+
+void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int highlight, int merge_results)
{
Render *re = engine->re;
@@ -254,7 +268,7 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel
}
/* merge. on break, don't merge in result for preview renders, looks nicer */
- if (!cancel) {
+ if (!highlight) {
/* for exr tile render, detect tiles that are done */
RenderPart *pa = get_part_from_result(re, result);
@@ -760,3 +774,22 @@ int RE_engine_render(Render *re, int do_all)
return 1;
}
+void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
+ const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type)
+{
+ /* The channel information is currently not used, but is part of the API in case it's needed in the future. */
+
+ if (!(scene && srl && engine)) {
+ return;
+ }
+
+ /* Register the pass in all scenes that have a render layer node for this layer.
+ * Since multiple scenes can be used in the compositor, the code must loop over all scenes
+ * and check whether their nodetree has a node that needs to be updated. */
+ Scene *sce;
+ for (sce = G.main->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree) {
+ ntreeCompositRegisterPass(sce->nodetree, scene, srl, name, type);
+ }
+ }
+}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 52eca5f7005..929eae495cf 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -239,9 +239,9 @@ void RE_FreeRenderResult(RenderResult *res)
render_result_free(res);
}
-float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname)
+float *RE_RenderLayerGetPass(volatile RenderLayer *rl, const char *name, const char *viewname)
{
- RenderPass *rpass = RE_pass_find_by_type(rl, passtype, viewname);
+ RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname);
return rpass ? rpass->rect : NULL;
}
@@ -382,13 +382,13 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
if (rl) {
if (rv->rectf == NULL) {
for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
- rview->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rview->name);
+ rview->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rview->name);
}
}
if (rv->rectz == NULL) {
for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) {
- rview->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rview->name);
+ rview->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rview->name);
}
}
}
@@ -442,10 +442,10 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
if (rl) {
if (rv->rectf == NULL)
- rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name);
+ rr->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rv->name);
if (rv->rectz == NULL)
- rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name);
+ rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name);
}
rr->have_combined = (rv->rectf != NULL);
@@ -842,7 +842,7 @@ static void render_result_rescale(Render *re)
if (src_rectf == NULL) {
RenderLayer *rl = render_get_active_layer(re, re->result);
if (rl != NULL) {
- src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL);
+ src_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
}
}
@@ -861,7 +861,7 @@ static void render_result_rescale(Render *re)
RenderLayer *rl;
rl = render_get_active_layer(re, re->result);
if (rl != NULL) {
- dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL);
+ dst_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL);
}
}
@@ -1655,7 +1655,7 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b
/* passes are allocated in sync */
rpass1 = rl1->passes.first;
for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) {
- if ((rpass->passtype & SCE_PASS_COMBINED) && key_alpha)
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && key_alpha)
addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac);
else
addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
@@ -1855,6 +1855,8 @@ static void render_result_uncrop(Render *re)
rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ render_result_clone_passes(re, rres, NULL);
+
render_result_merge(rres, re->result);
render_result_free(re->result);
re->result = rres;
@@ -3887,7 +3889,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char
/* multiview: since the API takes no 'view', we use the first combined pass found */
for (rpass = layer->passes.first; rpass; rpass = rpass->next)
- if (rpass->passtype == SCE_PASS_COMBINED)
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED))
break;
if (rpass == NULL)
@@ -4013,13 +4015,12 @@ bool RE_layers_have_name(struct RenderResult *rr)
return false;
}
-RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname)
+RenderPass *RE_pass_find_by_name(volatile RenderLayer *rl, const char *name, const char *viewname)
{
RenderPass *rp = NULL;
for (rp = rl->passes.last; rp; rp = rp->prev) {
- if (rp->passtype == passtype) {
-
+ if (STREQ(rp->name, name)) {
if (viewname == NULL || viewname[0] == '\0')
break;
else if (STREQ(rp->view, viewname))
@@ -4029,6 +4030,50 @@ RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const c
return rp;
}
+/* Only provided for API compatibility, don't use this in new code! */
+RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname)
+{
+#define CHECK_PASS(NAME) \
+ if (passtype == SCE_PASS_ ## NAME) \
+ return RE_pass_find_by_name(rl, RE_PASSNAME_ ## NAME, viewname);
+
+ CHECK_PASS(COMBINED);
+ CHECK_PASS(Z);
+ CHECK_PASS(VECTOR);
+ CHECK_PASS(NORMAL);
+ CHECK_PASS(UV);
+ CHECK_PASS(RGBA);
+ CHECK_PASS(EMIT);
+ CHECK_PASS(DIFFUSE);
+ CHECK_PASS(SPEC);
+ CHECK_PASS(SHADOW);
+ CHECK_PASS(AO);
+ CHECK_PASS(ENVIRONMENT);
+ CHECK_PASS(INDIRECT);
+ CHECK_PASS(REFLECT);
+ CHECK_PASS(REFRACT);
+ CHECK_PASS(INDEXOB);
+ CHECK_PASS(INDEXMA);
+ CHECK_PASS(MIST);
+ CHECK_PASS(RAYHITS);
+ CHECK_PASS(DIFFUSE_DIRECT);
+ CHECK_PASS(DIFFUSE_INDIRECT);
+ CHECK_PASS(DIFFUSE_COLOR);
+ CHECK_PASS(GLOSSY_DIRECT);
+ CHECK_PASS(GLOSSY_INDIRECT);
+ CHECK_PASS(GLOSSY_COLOR);
+ CHECK_PASS(TRANSM_DIRECT);
+ CHECK_PASS(TRANSM_INDIRECT);
+ CHECK_PASS(TRANSM_COLOR);
+ CHECK_PASS(SUBSURFACE_DIRECT);
+ CHECK_PASS(SUBSURFACE_INDIRECT);
+ CHECK_PASS(SUBSURFACE_COLOR);
+
+#undef CHECK_PASS
+
+ return NULL;
+}
+
/* create a renderlayer and renderpass for grease pencil layer */
RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const char *viewname)
{
@@ -4046,7 +4091,7 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha
}
/* clear previous pass if exist or the new image will be over previous one*/
- RenderPass *rp = RE_pass_find_by_type(rl, SCE_PASS_COMBINED, viewname);
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
if (rp) {
if (rp->rect) {
MEM_freeN(rp->rect);
@@ -4054,5 +4099,5 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha
BLI_freelinkN(&rl->passes, rp);
}
/* create a totally new pass */
- return gp_add_pass(rr, rl, 4, SCE_PASS_COMBINED, viewname);
+ return gp_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname);
}
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index f276c01e86a..8e6e6c9bb7d 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -173,363 +173,72 @@ void render_result_views_shallowdelete(RenderResult *rr)
}
}
-static const char *name_from_passtype(int passtype, int channel)
-{
- if (passtype == SCE_PASS_COMBINED) {
- if (channel == -1) return "Combined";
- if (channel == 0) return "Combined.R";
- if (channel == 1) return "Combined.G";
- if (channel == 2) return "Combined.B";
- return "Combined.A";
- }
- if (passtype == SCE_PASS_Z) {
- if (channel == -1) return "Depth";
- return "Depth.Z";
- }
- if (passtype == SCE_PASS_VECTOR) {
- if (channel == -1) return "Vector";
- if (channel == 0) return "Vector.X";
- if (channel == 1) return "Vector.Y";
- if (channel == 2) return "Vector.Z";
- return "Vector.W";
- }
- if (passtype == SCE_PASS_NORMAL) {
- if (channel == -1) return "Normal";
- if (channel == 0) return "Normal.X";
- if (channel == 1) return "Normal.Y";
- return "Normal.Z";
- }
- if (passtype == SCE_PASS_UV) {
- if (channel == -1) return "UV";
- if (channel == 0) return "UV.U";
- if (channel == 1) return "UV.V";
- return "UV.A";
- }
- if (passtype == SCE_PASS_RGBA) {
- if (channel == -1) return "Color";
- if (channel == 0) return "Color.R";
- if (channel == 1) return "Color.G";
- if (channel == 2) return "Color.B";
- return "Color.A";
- }
- if (passtype == SCE_PASS_EMIT) {
- if (channel == -1) return "Emit";
- if (channel == 0) return "Emit.R";
- if (channel == 1) return "Emit.G";
- return "Emit.B";
- }
- if (passtype == SCE_PASS_DIFFUSE) {
- if (channel == -1) return "Diffuse";
- if (channel == 0) return "Diffuse.R";
- if (channel == 1) return "Diffuse.G";
- return "Diffuse.B";
- }
- if (passtype == SCE_PASS_SPEC) {
- if (channel == -1) return "Spec";
- if (channel == 0) return "Spec.R";
- if (channel == 1) return "Spec.G";
- return "Spec.B";
- }
- if (passtype == SCE_PASS_SHADOW) {
- if (channel == -1) return "Shadow";
- if (channel == 0) return "Shadow.R";
- if (channel == 1) return "Shadow.G";
- return "Shadow.B";
- }
- if (passtype == SCE_PASS_AO) {
- if (channel == -1) return "AO";
- if (channel == 0) return "AO.R";
- if (channel == 1) return "AO.G";
- return "AO.B";
- }
- if (passtype == SCE_PASS_ENVIRONMENT) {
- if (channel == -1) return "Env";
- if (channel == 0) return "Env.R";
- if (channel == 1) return "Env.G";
- return "Env.B";
- }
- if (passtype == SCE_PASS_INDIRECT) {
- if (channel == -1) return "Indirect";
- if (channel == 0) return "Indirect.R";
- if (channel == 1) return "Indirect.G";
- return "Indirect.B";
- }
- if (passtype == SCE_PASS_REFLECT) {
- if (channel == -1) return "Reflect";
- if (channel == 0) return "Reflect.R";
- if (channel == 1) return "Reflect.G";
- return "Reflect.B";
- }
- if (passtype == SCE_PASS_REFRACT) {
- if (channel == -1) return "Refract";
- if (channel == 0) return "Refract.R";
- if (channel == 1) return "Refract.G";
- return "Refract.B";
- }
- if (passtype == SCE_PASS_INDEXOB) {
- if (channel == -1) return "IndexOB";
- return "IndexOB.X";
- }
- if (passtype == SCE_PASS_INDEXMA) {
- if (channel == -1) return "IndexMA";
- return "IndexMA.X";
- }
- if (passtype == SCE_PASS_MIST) {
- if (channel == -1) return "Mist";
- return "Mist.Z";
- }
- if (passtype == SCE_PASS_RAYHITS) {
- if (channel == -1) return "Rayhits";
- if (channel == 0) return "Rayhits.R";
- if (channel == 1) return "Rayhits.G";
- return "Rayhits.B";
- }
- if (passtype == SCE_PASS_DIFFUSE_DIRECT) {
- if (channel == -1) return "DiffDir";
- if (channel == 0) return "DiffDir.R";
- if (channel == 1) return "DiffDir.G";
- return "DiffDir.B";
- }
- if (passtype == SCE_PASS_DIFFUSE_INDIRECT) {
- if (channel == -1) return "DiffInd";
- if (channel == 0) return "DiffInd.R";
- if (channel == 1) return "DiffInd.G";
- return "DiffInd.B";
- }
- if (passtype == SCE_PASS_DIFFUSE_COLOR) {
- if (channel == -1) return "DiffCol";
- if (channel == 0) return "DiffCol.R";
- if (channel == 1) return "DiffCol.G";
- return "DiffCol.B";
- }
- if (passtype == SCE_PASS_GLOSSY_DIRECT) {
- if (channel == -1) return "GlossDir";
- if (channel == 0) return "GlossDir.R";
- if (channel == 1) return "GlossDir.G";
- return "GlossDir.B";
- }
- if (passtype == SCE_PASS_GLOSSY_INDIRECT) {
- if (channel == -1) return "GlossInd";
- if (channel == 0) return "GlossInd.R";
- if (channel == 1) return "GlossInd.G";
- return "GlossInd.B";
- }
- if (passtype == SCE_PASS_GLOSSY_COLOR) {
- if (channel == -1) return "GlossCol";
- if (channel == 0) return "GlossCol.R";
- if (channel == 1) return "GlossCol.G";
- return "GlossCol.B";
- }
- if (passtype == SCE_PASS_TRANSM_DIRECT) {
- if (channel == -1) return "TransDir";
- if (channel == 0) return "TransDir.R";
- if (channel == 1) return "TransDir.G";
- return "TransDir.B";
- }
- if (passtype == SCE_PASS_TRANSM_INDIRECT) {
- if (channel == -1) return "TransInd";
- if (channel == 0) return "TransInd.R";
- if (channel == 1) return "TransInd.G";
- return "TransInd.B";
- }
- if (passtype == SCE_PASS_TRANSM_COLOR) {
- if (channel == -1) return "TransCol";
- if (channel == 0) return "TransCol.R";
- if (channel == 1) return "TransCol.G";
- return "TransCol.B";
- }
- if (passtype == SCE_PASS_SUBSURFACE_DIRECT) {
- if (channel == -1) return "SubsurfaceDir";
- if (channel == 0) return "SubsurfaceDir.R";
- if (channel == 1) return "SubsurfaceDir.G";
- return "SubsurfaceDir.B";
- }
- if (passtype == SCE_PASS_SUBSURFACE_INDIRECT) {
- if (channel == -1) return "SubsurfaceInd";
- if (channel == 0) return "SubsurfaceInd.R";
- if (channel == 1) return "SubsurfaceInd.G";
- return "SubsurfaceInd.B";
- }
- if (passtype == SCE_PASS_SUBSURFACE_COLOR) {
- if (channel == -1) return "SubsurfaceCol";
- if (channel == 0) return "SubsurfaceCol.R";
- if (channel == 1) return "SubsurfaceCol.G";
- return "SubsurfaceCol.B";
- }
- return "Unknown";
-}
-static int passtype_from_name(const char *str, int passflag)
+static char* set_pass_name(char *outname, const char *name, int channel, const char *chan_id)
{
- /* We do not really support several pass of the same types, so in case we are opening an EXR file with several pass
- * names detected as same pass type, only return that pass type the first time, and return 'uknown' for the others.
- * See T48466. */
-#define RETURN_PASS(_passtype) return (passflag & (_passtype)) ? 0 : (_passtype)
-
- if (STRPREFIX(str, "Combined"))
- RETURN_PASS(SCE_PASS_COMBINED);
-
- if (STRPREFIX(str, "Depth"))
- RETURN_PASS(SCE_PASS_Z);
-
- if (STRPREFIX(str, "Vector"))
- RETURN_PASS(SCE_PASS_VECTOR);
-
- if (STRPREFIX(str, "Normal"))
- RETURN_PASS(SCE_PASS_NORMAL);
-
- if (STRPREFIX(str, "UV"))
- RETURN_PASS(SCE_PASS_UV);
-
- if (STRPREFIX(str, "Color"))
- RETURN_PASS(SCE_PASS_RGBA);
-
- if (STRPREFIX(str, "Emit"))
- RETURN_PASS(SCE_PASS_EMIT);
-
- if (STRPREFIX(str, "Diffuse"))
- RETURN_PASS(SCE_PASS_DIFFUSE);
-
- if (STRPREFIX(str, "Spec"))
- RETURN_PASS(SCE_PASS_SPEC);
-
- if (STRPREFIX(str, "Shadow"))
- RETURN_PASS(SCE_PASS_SHADOW);
-
- if (STRPREFIX(str, "AO"))
- RETURN_PASS(SCE_PASS_AO);
-
- if (STRPREFIX(str, "Env"))
- RETURN_PASS(SCE_PASS_ENVIRONMENT);
-
- if (STRPREFIX(str, "Indirect"))
- RETURN_PASS(SCE_PASS_INDIRECT);
-
- if (STRPREFIX(str, "Reflect"))
- RETURN_PASS(SCE_PASS_REFLECT);
-
- if (STRPREFIX(str, "Refract"))
- RETURN_PASS(SCE_PASS_REFRACT);
-
- if (STRPREFIX(str, "IndexOB"))
- RETURN_PASS(SCE_PASS_INDEXOB);
-
- if (STRPREFIX(str, "IndexMA"))
- RETURN_PASS(SCE_PASS_INDEXMA);
-
- if (STRPREFIX(str, "Mist"))
- RETURN_PASS(SCE_PASS_MIST);
-
- if (STRPREFIX(str, "RayHits"))
- RETURN_PASS(SCE_PASS_RAYHITS);
-
- if (STRPREFIX(str, "DiffDir"))
- RETURN_PASS(SCE_PASS_DIFFUSE_DIRECT);
-
- if (STRPREFIX(str, "DiffInd"))
- RETURN_PASS(SCE_PASS_DIFFUSE_INDIRECT);
-
- if (STRPREFIX(str, "DiffCol"))
- RETURN_PASS(SCE_PASS_DIFFUSE_COLOR);
-
- if (STRPREFIX(str, "GlossDir"))
- RETURN_PASS(SCE_PASS_GLOSSY_DIRECT);
-
- if (STRPREFIX(str, "GlossInd"))
- RETURN_PASS(SCE_PASS_GLOSSY_INDIRECT);
-
- if (STRPREFIX(str, "GlossCol"))
- RETURN_PASS(SCE_PASS_GLOSSY_COLOR);
-
- if (STRPREFIX(str, "TransDir"))
- RETURN_PASS(SCE_PASS_TRANSM_DIRECT);
-
- if (STRPREFIX(str, "TransInd"))
- RETURN_PASS(SCE_PASS_TRANSM_INDIRECT);
-
- if (STRPREFIX(str, "TransCol"))
- RETURN_PASS(SCE_PASS_TRANSM_COLOR);
-
- if (STRPREFIX(str, "SubsurfaceDir"))
- RETURN_PASS(SCE_PASS_SUBSURFACE_DIRECT);
-
- if (STRPREFIX(str, "SubsurfaceInd"))
- RETURN_PASS(SCE_PASS_SUBSURFACE_INDIRECT);
-
- if (STRPREFIX(str, "SubsurfaceCol"))
- RETURN_PASS(SCE_PASS_SUBSURFACE_COLOR);
-
- return 0;
-
-#undef RETURN_PASS
+ BLI_strncpy(outname, name, EXR_PASS_MAXNAME);
+ if (channel >= 0) {
+ char token[3] = {'.', chan_id[channel], '\0'};
+ strncat(outname, token, EXR_PASS_MAXNAME);
+ }
+ return outname;
}
-
-static void set_pass_name(char *passname, int passtype, int channel, const char *view)
+static void set_pass_full_name(char *fullname, const char *name, int channel, const char *view, const char *chan_id)
{
- const char delims[] = {'.', '\0'};
- const char *sep;
- const char *token;
- size_t len;
-
- const char *passtype_name = name_from_passtype(passtype, channel);
-
- if (view == NULL || view[0] == '\0') {
- BLI_strncpy(passname, passtype_name, EXR_PASS_MAXNAME);
- return;
- }
-
- len = BLI_str_rpartition(passtype_name, delims, &sep, &token);
-
- if (sep) {
- BLI_snprintf(passname, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passtype_name, view, token);
+ BLI_strncpy(fullname, name, EXR_PASS_MAXNAME);
+ if (view && view[0]) {
+ strncat(fullname, ".", EXR_PASS_MAXNAME);
+ strncat(fullname, view, EXR_PASS_MAXNAME);
}
- else {
- BLI_snprintf(passname, EXR_PASS_MAXNAME, "%s.%s", passtype_name, view);
+ if (channel >= 0) {
+ char token[3] = {'.', chan_id[channel], '\0'};
+ strncat(fullname, token, EXR_PASS_MAXNAME);
}
}
/********************************** New **************************************/
-static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname)
+static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id)
{
const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
- const char *typestr = name_from_passtype(passtype, -1);
- RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr);
+ RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name);
size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
- rpass->passtype = passtype;
rpass->channels = channels;
rpass->rectx = rl->rectx;
rpass->recty = rl->recty;
rpass->view_id = view_id;
- set_pass_name(rpass->name, rpass->passtype, -1, viewname);
- BLI_strncpy(rpass->internal_name, typestr, sizeof(rpass->internal_name));
+ BLI_strncpy(rpass->name, name, sizeof(rpass->name));
+ BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
BLI_strncpy(rpass->view, viewname, sizeof(rpass->view));
+ set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
if (rl->exrhandle) {
int a;
- for (a = 0; a < channels; a++)
- IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(passtype, a), viewname, 0, 0, NULL, false);
+ for (a = 0; a < channels; a++) {
+ char passname[EXR_PASS_MAXNAME];
+ IMB_exr_add_channel(rl->exrhandle, rl->name, set_pass_name(passname, rpass->name, a, rpass->chan_id), viewname, 0, 0, NULL, false);
+ }
}
else {
float *rect;
int x;
- rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, typestr);
+ rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, name);
if (rpass->rect == NULL) {
MEM_freeN(rpass);
return NULL;
}
- if (passtype == SCE_PASS_VECTOR) {
+ if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
/* initialize to max speed */
rect = rpass->rect;
for (x = rectsize - 1; x >= 0; x--)
rect[x] = PASS_VECTOR_MAX;
}
- else if (passtype == SCE_PASS_Z) {
+ else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
rect = rpass->rect;
for (x = rectsize - 1; x >= 0; x--)
rect[x] = 10e10;
@@ -541,58 +250,10 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int
return rpass;
}
/* wrapper called from render_opengl */
-RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname)
-{
- return render_layer_add_pass(rr, rl, channels, passtype, viewname);
-}
-
-#ifdef WITH_CYCLES_DEBUG
-const char *RE_debug_pass_name_get(int debug_type)
-{
- switch (debug_type) {
- case RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES:
- return "BVH Traversed Nodes";
- case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES:
- return "BVH Traversed Instances";
- case RENDER_PASS_DEBUG_BVH_INTERSECTIONS:
- return "BVH Primitive Intersections";
- case RENDER_PASS_DEBUG_RAY_BOUNCES:
- return "Ray Bounces";
- }
- return "Unknown";
-}
-
-int RE_debug_pass_num_channels_get(int UNUSED(debug_type))
-{
- /* Only single case currently, might be handy for further debug passes. */
- return 1;
-}
-
-static RenderPass *render_layer_add_debug_pass(RenderResult *rr,
- RenderLayer *rl,
- int pass_type,
- int debug_type,
- const char *view)
-{
- const char *name = RE_debug_pass_name_get(debug_type);
- int channels = RE_debug_pass_num_channels_get(debug_type);
- RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type, view);
- if (rpass == NULL) {
- return NULL;
- }
- rpass->debug_type = debug_type;
- BLI_strncpy(rpass->name,
- name,
- sizeof(rpass->name));
- BLI_strncpy(rpass->internal_name, rpass->name, sizeof(rpass->internal_name));
- return rpass;
-}
-
-int RE_debug_pass_type_get(Render *re)
+RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname)
{
- return re->r.debug_pass_type;
+ return render_layer_add_pass(rr, rl, channels, name, viewname, "RGBA");
}
-#endif
/* called by main render as well for parts */
/* will read info from Render *re to define layers */
@@ -683,89 +344,77 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
if (rr->do_exr_tile)
IMB_exr_add_view(rl->exrhandle, view);
-#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, passtype, viewname) \
+#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \
do { \
- if (render_layer_add_pass(rr, rl, channels, passtype, viewname) == NULL) { \
+ if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \
render_result_free(rr); \
return NULL; \
} \
} while (false)
/* a renderlayer should always have a Combined pass*/
- render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view);
+ render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA");
if (srl->passflag & SCE_PASS_Z)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_Z, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
if (srl->passflag & SCE_PASS_VECTOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_VECTOR, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
if (srl->passflag & SCE_PASS_NORMAL)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_NORMAL, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
if (srl->passflag & SCE_PASS_UV)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_UV, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
if (srl->passflag & SCE_PASS_RGBA)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_RGBA, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RGBA, view, "RGBA");
if (srl->passflag & SCE_PASS_EMIT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_EMIT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE, view, "RGB");
if (srl->passflag & SCE_PASS_SPEC)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SPEC, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SPEC, view, "RGB");
if (srl->passflag & SCE_PASS_AO)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_AO, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
if (srl->passflag & SCE_PASS_ENVIRONMENT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_ENVIRONMENT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
if (srl->passflag & SCE_PASS_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_INDIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_SHADOW)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SHADOW, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
if (srl->passflag & SCE_PASS_REFLECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFLECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFLECT, view, "RGB");
if (srl->passflag & SCE_PASS_REFRACT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFRACT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFRACT, view, "RGB");
if (srl->passflag & SCE_PASS_INDEXOB)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXOB, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
if (srl->passflag & SCE_PASS_INDEXMA)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXMA, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
if (srl->passflag & SCE_PASS_MIST)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_MIST, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z");
if (rl->passflag & SCE_PASS_RAYHITS)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_RAYHITS, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_DIFFUSE_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
if (srl->passflag & SCE_PASS_GLOSSY_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_GLOSSY_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
if (srl->passflag & SCE_PASS_TRANSM_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_TRANSM_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_TRANSM_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view);
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR)
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view);
-
-#ifdef WITH_CYCLES_DEBUG
- if (BKE_scene_use_new_shading_nodes(re->scene)) {
- if (render_layer_add_debug_pass(rr, rl, SCE_PASS_DEBUG,
- re->r.debug_pass_type, view) == NULL)
- {
- render_result_free(rr);
- return NULL;
- }
- }
-#endif
-
+ RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
#undef RENDER_LAYER_ADD_PASS_SAFE
}
}
@@ -794,7 +443,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
IMB_exr_add_view(rl->exrhandle, view);
/* a renderlayer should always have a Combined pass */
- render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view);
+ render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA");
}
/* note, this has to be in sync with scene.c */
@@ -813,6 +462,60 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
return rr;
}
+void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
+{
+ RenderLayer *rl;
+ RenderPass *main_rp;
+
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ RenderLayer *main_rl = BLI_findstring(&re->result->layers, rl->name, offsetof(RenderLayer, name));
+ if (!main_rl) {
+ continue;
+ }
+
+ for (main_rp = main_rl->passes.first; main_rp; main_rp = main_rp->next) {
+ if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) {
+ continue;
+ }
+
+ /* Compare fullname to make sure that the view also is equal. */
+ RenderPass *rp = BLI_findstring(&rl->passes, main_rp->fullname, offsetof(RenderPass, fullname));
+ if (!rp) {
+ render_layer_add_pass(rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id);
+ }
+ }
+ }
+}
+
+void render_result_add_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname)
+{
+ RenderLayer *rl;
+ RenderPass *rp;
+ RenderView *rv;
+
+ for (rl = rr->layers.first; rl; rl = rl->next) {
+ if (layername && layername[0] && !STREQ(rl->name, layername)) {
+ continue;
+ }
+
+ for (rv = rr->views.first; rv; rv = rv->next) {
+ const char *view = rv->name;
+
+ if (viewname && viewname[0] && !STREQ(view, viewname)) continue;
+
+ /* Ensure that the pass doesn't exist yet. */
+ for (rp = rl->passes.first; rp; rp = rp->next) {
+ if (!STREQ(rp->name, name)) continue;
+ if (!STREQ(rp->view, view)) continue;
+ }
+
+ if (!rp) {
+ render_layer_add_pass(rr, rl, channels, name, view, chan_id);
+ }
+ }
+ }
+}
+
/* allocate osa new results for samples */
RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers, const char *viewname)
{
@@ -830,6 +533,50 @@ RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *part
return lb->first;
}
+static int passtype_from_name(const char *name)
+{
+ const char delim[] = {'.', '\0'};
+ const char *sep, *suf;
+ int len = BLI_str_partition(name, delim, &sep, &suf);
+
+#define CHECK_PASS(NAME) if (STREQLEN(name, RE_PASSNAME_ ## NAME, len)) return SCE_PASS_ ## NAME
+
+ CHECK_PASS(COMBINED);
+ CHECK_PASS(Z);
+ CHECK_PASS(VECTOR);
+ CHECK_PASS(NORMAL);
+ CHECK_PASS(UV);
+ CHECK_PASS(RGBA);
+ CHECK_PASS(EMIT);
+ CHECK_PASS(DIFFUSE);
+ CHECK_PASS(SPEC);
+ CHECK_PASS(SHADOW);
+ CHECK_PASS(AO);
+ CHECK_PASS(ENVIRONMENT);
+ CHECK_PASS(INDIRECT);
+ CHECK_PASS(REFLECT);
+ CHECK_PASS(REFRACT);
+ CHECK_PASS(INDEXOB);
+ CHECK_PASS(INDEXMA);
+ CHECK_PASS(MIST);
+ CHECK_PASS(RAYHITS);
+ CHECK_PASS(DIFFUSE_DIRECT);
+ CHECK_PASS(DIFFUSE_INDIRECT);
+ CHECK_PASS(DIFFUSE_COLOR);
+ CHECK_PASS(GLOSSY_DIRECT);
+ CHECK_PASS(GLOSSY_INDIRECT);
+ CHECK_PASS(GLOSSY_COLOR);
+ CHECK_PASS(TRANSM_DIRECT);
+ CHECK_PASS(TRANSM_INDIRECT);
+ CHECK_PASS(TRANSM_COLOR);
+ CHECK_PASS(SUBSURFACE_DIRECT);
+ CHECK_PASS(SUBSURFACE_INDIRECT);
+ CHECK_PASS(SUBSURFACE_COLOR);
+
+#undef CHECK_PASS
+ return 0;
+}
+
/* callbacks for render_result_new_from_exr */
static void *ml_addlayer_cb(void *base, const char *str)
{
@@ -843,36 +590,30 @@ static void *ml_addlayer_cb(void *base, const char *str)
return rl;
}
-static void ml_addpass_cb(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view)
+static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view)
{
RenderResult *rr = base;
RenderLayer *rl = lay;
RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
- int a;
-
+
BLI_addtail(&rl->passes, rpass);
rpass->channels = totchan;
- rpass->passtype = passtype_from_name(str, rl->passflag);
- if (rpass->passtype == 0)
- printf("unknown pass %s\n", str);
- rl->passflag |= rpass->passtype;
-
+ rl->passflag |= passtype_from_name(name);
+
/* channel id chars */
- for (a = 0; a < totchan; a++)
- rpass->chan_id[a] = chan_id[a];
+ BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
rpass->rect = rect;
+ BLI_strncpy(rpass->name, name, EXR_PASS_MAXNAME);
+ BLI_strncpy(rpass->view, view, sizeof(rpass->view));
+ set_pass_full_name(rpass->fullname, name, -1, view, rpass->chan_id);
+
if (view[0] != '\0') {
- BLI_snprintf(rpass->name, sizeof(rpass->name), "%s.%s", str, view);
rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
}
else {
- BLI_strncpy(rpass->name, str, sizeof(rpass->name));
rpass->view_id = 0;
}
-
- BLI_strncpy(rpass->view, view, sizeof(rpass->view));
- BLI_strncpy(rpass->internal_name, str, sizeof(rpass->internal_name));
}
static void *ml_addview_cb(void *base, const char *str)
@@ -912,12 +653,30 @@ static int order_render_passes(const void *a, const void *b)
// 1 if a is after b
RenderPass *rpa = (RenderPass *) a;
RenderPass *rpb = (RenderPass *) b;
+ unsigned int passtype_a = passtype_from_name(rpa->name);
+ unsigned int passtype_b = passtype_from_name(rpb->name);
- if (rpa->passtype > rpb->passtype)
+ /* Render passes with default type always go first. */
+ if (passtype_b && !passtype_a)
return 1;
- else if (rpa->passtype < rpb->passtype)
+ if (passtype_a && !passtype_b)
return 0;
+ if (passtype_a && passtype_b) {
+ if (passtype_a > passtype_b)
+ return 1;
+ else if (passtype_a < passtype_b)
+ return 0;
+ }
+ else {
+ int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME);
+ if (cmp > 0)
+ return 1;
+ if (cmp < 0)
+ return 0;
+ }
+
+
/* they have the same type */
/* left first */
if (STREQ(rpa->view, STEREO_LEFT_NAME))
@@ -1049,7 +808,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
rpass = rpass->next)
{
/* renderresult have all passes, renderpart only the active view's passes */
- if (strcmp(rpassp->name, rpass->name) != 0)
+ if (strcmp(rpassp->fullname, rpass->fullname) != 0)
continue;
do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
@@ -1061,21 +820,6 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart)
}
}
-/* for passes read from files, these have names stored */
-static char *make_pass_name(RenderPass *rpass, int chan)
-{
- static char name[EXR_PASS_MAXNAME];
- int len;
-
- BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
- len = strlen(name);
- name[len] = '.';
- name[len + 1] = rpass->chan_id[chan];
- name[len + 2] = 0;
-
- return name;
-}
-
/* called from within UI and render pipeline, saves both rendered result as a file-read result
* if multiview is true saves all views in a multiview exr
* else if view is not NULL saves single view
@@ -1136,8 +880,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
IMB_exr_add_view(exrhandle, rview->name);
if (rview->rectf) {
+ char passname[EXR_PASS_MAXNAME];
for (a = 0; a < 4; a++) {
- IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a),
+ set_pass_name(passname, RE_PASSNAME_COMBINED, a, "RGBA");
+ IMB_exr_add_channel(exrhandle, RE_PASSNAME_COMBINED, passname,
chan_view, 4, 4 * width, rview->rectf + a,
use_half_float);
}
@@ -1150,6 +896,7 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
/* passes are allocated in sync */
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
const int xstride = rpass->channels;
+ char passname[EXR_PASS_MAXNAME];
if (is_mono) {
if (!STREQ(view, rpass->view)) {
@@ -1163,16 +910,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil
}
for (a = 0; a < xstride; a++) {
- if (rpass->passtype) {
- IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view,
- xstride, xstride * width, rpass->rect + a,
- rpass->passtype == SCE_PASS_Z ? false : use_half_float);
- }
- else {
- IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view,
- xstride, xstride * width, rpass->rect + a,
- use_half_float);
- }
+ set_pass_name(passname, rpass->name, a, rpass->chan_id);
+ IMB_exr_add_channel(exrhandle, rl->name, passname, chan_view,
+ xstride, xstride * width, rpass->rect + a,
+ STREQ(rpass->name, RE_PASSNAME_Z) ? false : use_half_float);
}
}
}
@@ -1281,12 +1022,12 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons
for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
const int xstride = rpassp->channels;
int a;
- char passname[EXR_PASS_MAXNAME];
+ char fullname[EXR_PASS_MAXNAME];
for (a = 0; a < xstride; a++) {
- set_pass_name(passname, rpassp->passtype, a, rpassp->view);
+ set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id);
- IMB_exr_set_channel(rl->exrhandle, rlp->name, passname,
+ IMB_exr_set_channel(rl->exrhandle, rlp->name, fullname,
xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
}
}
@@ -1449,15 +1190,15 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
const int xstride = rpass->channels;
int a;
- char passname[EXR_PASS_MAXNAME];
+ char fullname[EXR_PASS_MAXNAME];
for (a = 0; a < xstride; a++) {
- set_pass_name(passname, rpass->passtype, a, rpass->view);
- IMB_exr_set_channel(exrhandle, rl->name, passname,
+ set_pass_full_name(fullname, rpass->name, a, rpass->view, rpass->chan_id);
+ IMB_exr_set_channel(exrhandle, rl->name, fullname,
xstride, xstride * rectx, rpass->rect + a);
}
- set_pass_name(rpass->name, rpass->passtype, -1, rpass->view);
+ set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
}
}
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index b4a14f5337d..22dc2b28900 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -1112,14 +1112,15 @@ static int multitex(Tex *tex,
const short which_output,
struct ImagePool *pool,
const bool skip_load_image,
- const bool texnode_preview)
+ const bool texnode_preview,
+ const bool use_nodes)
{
float tmpvec[3];
int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
texres->talpha = false; /* is set when image texture returns alpha (considered premul) */
- if (tex->use_nodes && tex->nodetree) {
+ if (use_nodes && tex->use_nodes && tex->nodetree) {
retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread,
tex, which_output, R.r.cfra, texnode_preview, NULL, NULL);
}
@@ -1239,7 +1240,8 @@ static int multitex_nodes_intern(Tex *tex,
ImagePool *pool,
const bool scene_color_manage,
const bool skip_load_image,
- const bool texnode_preview)
+ const bool texnode_preview,
+ const bool use_nodes)
{
if (tex==NULL) {
memset(texres, 0, sizeof(TexResult));
@@ -1264,7 +1266,8 @@ static int multitex_nodes_intern(Tex *tex,
which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ use_nodes);
if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1311,7 +1314,8 @@ static int multitex_nodes_intern(Tex *tex,
which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ use_nodes);
{
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1341,7 +1345,8 @@ static int multitex_nodes_intern(Tex *tex,
which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ use_nodes);
}
}
@@ -1354,7 +1359,8 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres,
thread, which_output, shi, mtex, pool, R.scene_color_manage,
(R.r.scemode & R_NO_IMAGE_LOAD) != 0,
- (R.r.scemode & R_TEXNODE_PREVIEW) != 0);
+ (R.r.scemode & R_TEXNODE_PREVIEW) != 0,
+ true);
}
/* this is called for surface shading */
@@ -1378,7 +1384,8 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
mtex->which_output,
pool,
skip_load_image,
- (R.r.scemode & R_TEXNODE_PREVIEW) != 0);
+ (R.r.scemode & R_TEXNODE_PREVIEW) != 0,
+ true);
}
}
@@ -1408,7 +1415,8 @@ int multitex_ext(Tex *tex,
pool,
scene_color_manage,
skip_load_image,
- false);
+ false,
+ true);
}
/* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on)\
@@ -1417,13 +1425,19 @@ int multitex_ext(Tex *tex,
*/
int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
{
- int use_nodes= tex->use_nodes, retval;
-
- tex->use_nodes = false;
- retval= multitex_nodes_intern(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image, false);
- tex->use_nodes= use_nodes;
-
- return retval;
+ return multitex_nodes_intern(tex,
+ texvec,
+ NULL, NULL,
+ 0,
+ texres,
+ 0,
+ 0,
+ NULL, NULL,
+ pool,
+ scene_color_manage,
+ skip_load_image,
+ false,
+ false);
}
@@ -1481,6 +1495,7 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa
case MTEX_SUB:
fact= -fact;
+ ATTR_FALLTHROUGH;
case MTEX_ADD:
fact*= facg;
in[0]= (fact*tex[0] + out[0]);
@@ -1595,6 +1610,7 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen
case MTEX_SUB:
fact= -fact;
+ ATTR_FALLTHROUGH;
case MTEX_ADD:
in= fact*tex + out;
break;
@@ -2873,7 +2889,8 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
mtex->which_output,
re->pool,
skip_load_image,
- texnode_preview); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+ texnode_preview,
+ true); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
/* texture output */
@@ -3051,7 +3068,8 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
mtex->which_output,
har->pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3274,7 +3292,8 @@ void do_sky_tex(
mtex->which_output,
R.pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3500,7 +3519,8 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
mtex->which_output,
R.pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3614,7 +3634,8 @@ int externtex(MTex *mtex,
mtex->which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
if (rgb) {
texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 910ea16607e..77f399d08d1 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -180,11 +180,12 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
flarec= 0;
if (fullsample) {
- for (sample=0; sample<totsample; sample++)
+ for (sample=0; sample<totsample; sample++) {
if (ps->mask & (1 << sample)) {
- float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(pass + od*4, col, har->add);
}
+ }
}
else {
fac= ((float)amountm)/(float)R.osa;
@@ -215,11 +216,12 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
}
if (fullsample) {
- for (sample=0; sample<totsample; sample++)
+ for (sample=0; sample<totsample; sample++) {
if (!(mask & (1 << sample))) {
- float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(pass + od*4, col, har->add);
}
+ }
}
else {
col[0]= accol[0];
@@ -228,7 +230,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
col[3]= accol[3];
for (sample=0; sample<totsample; sample++) {
- float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(pass + od*4, col, har->add);
}
}
@@ -312,7 +314,7 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl)
if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) {
if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) {
for (sample=0; sample<totsample; sample++) {
- float * rect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ float * rect= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
addalphaAddfacFloat(rect + od*4, col, har->add);
}
}
@@ -367,7 +369,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
if (fullsample) {
for (sample=0; sample<totsample; sample++) {
if (ps->mask & (1 << sample)) {
- pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
@@ -379,7 +381,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)count)/(float)R.osa;
- pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
@@ -401,7 +403,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
for (sample=0; sample<totsample; sample++) {
if (!(mask & (1 << sample))) {
- pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
@@ -413,7 +415,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
}
else {
fac= ((float)R.osa-totsamp)/(float)R.osa;
- pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= fac*col[0];
pass[1]+= fac*col[1];
@@ -433,7 +435,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
renderspothalo(&shi, col, 1.0f);
for (sample=0; sample<totsample; sample++) {
- pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od * 4;
pass[0]+= col[0];
pass[1]+= col[1];
@@ -462,101 +464,96 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
float *fp, *col= NULL;
int pixsize= 3;
- switch (rpass->passtype) {
- case SCE_PASS_COMBINED:
- add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
- break;
- case SCE_PASS_Z:
- fp= rpass->rect + offset;
- *fp= shr->z;
- break;
- case SCE_PASS_RGBA:
- col= shr->col;
- pixsize= 4;
- break;
- case SCE_PASS_EMIT:
- col= shr->emit;
- break;
- case SCE_PASS_DIFFUSE:
- col= shr->diff;
- break;
- case SCE_PASS_SPEC:
- col= shr->spec;
- break;
- case SCE_PASS_SHADOW:
- col= shr->shad;
- break;
- case SCE_PASS_AO:
- col= shr->ao;
- break;
- case SCE_PASS_ENVIRONMENT:
- col= shr->env;
- break;
- case SCE_PASS_INDIRECT:
- col= shr->indirect;
- break;
- case SCE_PASS_REFLECT:
- col= shr->refl;
- break;
- case SCE_PASS_REFRACT:
- col= shr->refr;
- break;
- case SCE_PASS_NORMAL:
- col= shr->nor;
- break;
- case SCE_PASS_UV:
- /* box filter only, gauss will screwup UV too much */
- if (shi->totuv) {
- float mult= (float)count_mask(curmask)/(float)R.osa;
- fp= rpass->rect + 3*offset;
- fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]);
- fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]);
- fp[2]+= mult;
- }
- break;
- case SCE_PASS_INDEXOB:
- /* no filter */
- if (shi->vlr) {
- fp= rpass->rect + offset;
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
+ add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx);
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
+ fp = rpass->rect + offset;
+ *fp = shr->z;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) {
+ col = shr->col;
+ pixsize = 4;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) {
+ col = shr->emit;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
+ col = shr->diff;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) {
+ col = shr->spec;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) {
+ col = shr->shad;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_AO)) {
+ col = shr->ao;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) {
+ col = shr->env;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) {
+ col = shr->indirect;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) {
+ col = shr->refl;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) {
+ col = shr->refr;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) {
+ col = shr->nor;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_UV)) {
+ /* box filter only, gauss will screwup UV too much */
+ if (shi->totuv) {
+ float mult = (float)count_mask(curmask)/(float)R.osa;
+ fp = rpass->rect + 3*offset;
+ fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]);
+ fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]);
+ fp[2]+= mult;
+ }
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
+ /* no filter */
+ if (shi->vlr) {
+ fp = rpass->rect + offset;
+ if (*fp==0.0f)
+ *fp = (float)shi->obr->ob->index;
+ }
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
+ /* no filter */
+ if (shi->vlr) {
+ fp = rpass->rect + offset;
if (*fp==0.0f)
- *fp= (float)shi->obr->ob->index;
- }
- break;
- case SCE_PASS_INDEXMA:
- /* no filter */
- if (shi->vlr) {
- fp= rpass->rect + offset;
- if (*fp==0.0f)
- *fp= (float)shi->mat->index;
- }
- break;
- case SCE_PASS_MIST:
- /* */
- col= &shr->mist;
- pixsize= 1;
- break;
-
- case SCE_PASS_VECTOR:
- {
- /* add minimum speed in pixel, no filter */
- fp= rpass->rect + 4*offset;
- if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
- fp[0]= shr->winspeed[0];
- fp[1]= shr->winspeed[1];
- }
- if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
- fp[2]= shr->winspeed[2];
- fp[3]= shr->winspeed[3];
- }
-
- break;
+ *fp = (float)shi->mat->index;
+ }
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_MIST)) {
+ /* */
+ col = &shr->mist;
+ pixsize = 1;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
+ /* add minimum speed in pixel, no filter */
+ fp = rpass->rect + 4*offset;
+ if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
+ fp[0] = shr->winspeed[0];
+ fp[1] = shr->winspeed[1];
+ }
+ if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
+ fp[2] = shr->winspeed[2];
+ fp[3] = shr->winspeed[3];
}
- case SCE_PASS_RAYHITS:
- /* */
- col= shr->rayhits;
- pixsize= 4;
- break;
}
+ else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) {
+ /* */
+ col = shr->rayhits;
+ pixsize= 4;
+ }
+
if (col) {
fp= rpass->rect + pixsize*offset;
add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize);
@@ -574,86 +571,85 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
float *col= NULL, uvcol[3];
int a, pixsize= 3;
- switch (rpass->passtype) {
- case SCE_PASS_COMBINED:
- /* copy combined to use for preview */
- copy_v4_v4(rpass->rect + 4*offset, shr->combined);
- break;
- case SCE_PASS_Z:
- fp= rpass->rect + offset;
- *fp= shr->z;
- break;
- case SCE_PASS_RGBA:
- col= shr->col;
- pixsize= 4;
- break;
- case SCE_PASS_EMIT:
- col= shr->emit;
- break;
- case SCE_PASS_DIFFUSE:
- col= shr->diff;
- break;
- case SCE_PASS_SPEC:
- col= shr->spec;
- break;
- case SCE_PASS_SHADOW:
- col= shr->shad;
- break;
- case SCE_PASS_AO:
- col= shr->ao;
- break;
- case SCE_PASS_ENVIRONMENT:
- col= shr->env;
- break;
- case SCE_PASS_INDIRECT:
- col= shr->indirect;
- break;
- case SCE_PASS_REFLECT:
- col= shr->refl;
- break;
- case SCE_PASS_REFRACT:
- col= shr->refr;
- break;
- case SCE_PASS_NORMAL:
- col= shr->nor;
- break;
- case SCE_PASS_UV:
- if (shi->totuv) {
- uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0];
- uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1];
- uvcol[2]= 1.0f;
- col= uvcol;
- }
- break;
- case SCE_PASS_VECTOR:
- col= shr->winspeed;
- pixsize= 4;
- break;
- case SCE_PASS_INDEXOB:
- if (shi->vlr) {
- fp= rpass->rect + offset;
- *fp= (float)shi->obr->ob->index;
- }
- break;
- case SCE_PASS_INDEXMA:
- if (shi->vlr) {
- fp= rpass->rect + offset;
- *fp= (float)shi->mat->index;
- }
- break;
- case SCE_PASS_MIST:
- fp= rpass->rect + offset;
- *fp= shr->mist;
- break;
- case SCE_PASS_RAYHITS:
- col= shr->rayhits;
- pixsize= 4;
- break;
+ if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
+ /* copy combined to use for preview */
+ copy_v4_v4(rpass->rect + 4*offset, shr->combined);
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
+ fp = rpass->rect + offset;
+ *fp = shr->z;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) {
+ col = shr->col;
+ pixsize = 4;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) {
+ col = shr->emit;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
+ col = shr->diff;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) {
+ col = shr->spec;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) {
+ col = shr->shad;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_AO)) {
+ col = shr->ao;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) {
+ col = shr->env;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) {
+ col = shr->indirect;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) {
+ col = shr->refl;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) {
+ col = shr->refr;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) {
+ col = shr->nor;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_UV)) {
+ if (shi->totuv) {
+ uvcol[0] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[0];
+ uvcol[1] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[1];
+ uvcol[2] = 1.0f;
+ col = uvcol;
+ }
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
+ col = shr->winspeed;
+ pixsize = 4;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
+ if (shi->vlr) {
+ fp = rpass->rect + offset;
+ *fp = (float)shi->obr->ob->index;
+ }
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
+ if (shi->vlr) {
+ fp = rpass->rect + offset;
+ *fp = (float)shi->mat->index;
+ }
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_MIST)) {
+ fp = rpass->rect + offset;
+ *fp = shr->mist;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) {
+ col = shr->rayhits;
+ pixsize = 4;
}
+
if (col) {
- fp= rpass->rect + pixsize*offset;
+ fp = rpass->rect + pixsize*offset;
for (a=0; a<pixsize; a++)
- fp[a]= col[a];
+ fp[a] = col[a];
}
}
}
@@ -696,7 +692,7 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
bool done = false;
for (sample= 0; sample<totsample; sample++) {
- float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
pass += od;
if (pass[3]<1.0f) {
@@ -737,7 +733,7 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
/* check that z pass is enabled */
if (pa->rectz==NULL) return;
for (zpass= rl->passes.first; zpass; zpass= zpass->next)
- if (zpass->passtype==SCE_PASS_Z)
+ if (STREQ(zpass->name, RE_PASSNAME_Z))
break;
if (zpass==NULL) return;
@@ -758,8 +754,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
int sample;
for (sample=0; sample<totsample; sample++) {
- const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od;
- float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od;
+ const float *zrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_Z, R.viewname) + od;
+ float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname) + 4*od;
float rgb[3] = {0};
bool done = false;
@@ -994,7 +990,7 @@ static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
return;
for (sample= 0; sample<totsample; sample++) {
- float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname);
+ float *rectf = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname);
for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
rectf[0] = MAX2(rectf[0], 0.0f);
@@ -1076,7 +1072,7 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
totsample= get_sample_layers(pa, rl, rlpp);
for (sample= 0; sample<totsample; sample++) {
- fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR, R.viewname);
+ fp= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_VECTOR, R.viewname);
if (fp==NULL) break;
for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--)
@@ -1187,7 +1183,7 @@ void zbufshadeDA_tile(RenderPart *pa)
pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
- float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@@ -1339,7 +1335,7 @@ void zbufshade_tile(RenderPart *pa)
pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
for (rl= rr->layers.first; rl; rl= rl->next) {
- float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ float *rect= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK))
pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask");
@@ -1676,7 +1672,7 @@ void zbufshade_sss_tile(RenderPart *pa)
return;
}
- fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ fcol= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
@@ -1969,7 +1965,7 @@ void add_halo_flare(Render *re)
if ((rl->layflag & SCE_LAY_HALO) == 0)
continue;
- rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
+ rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname);
if (rect==NULL)
continue;
@@ -1998,3 +1994,37 @@ void add_halo_flare(Render *re)
}
}
+void render_internal_update_passes(RenderEngine *engine, Scene *scene, SceneRenderLayer *srl)
+{
+ int type;
+
+ RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
+
+#define CHECK_PASS(name, channels, chanid) \
+ if (srl->passflag & (SCE_PASS_ ## name)) { \
+ if (channels == 4) type = SOCK_RGBA; \
+ else if (channels == 3) type = SOCK_VECTOR; \
+ else type = SOCK_FLOAT; \
+ RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_ ## name, channels, chanid, type); \
+ }
+
+ CHECK_PASS(Z, 1, "Z");
+ CHECK_PASS(VECTOR, 4, "XYZW");
+ CHECK_PASS(NORMAL, 3, "XYZ");
+ CHECK_PASS(UV, 3, "UVA");
+ CHECK_PASS(RGBA, 4, "RGBA");
+ CHECK_PASS(EMIT, 3, "RGB");
+ CHECK_PASS(DIFFUSE, 3, "RGB");
+ CHECK_PASS(SPEC, 3, "RGB");
+ CHECK_PASS(AO, 3, "RGB");
+ CHECK_PASS(ENVIRONMENT, 3, "RGB");
+ CHECK_PASS(INDIRECT, 3, "RGB");
+ CHECK_PASS(SHADOW, 3, "RGB");
+ CHECK_PASS(REFLECT, 3, "RGB");
+ CHECK_PASS(REFRACT, 3, "RGB");
+ CHECK_PASS(INDEXOB, 1, "X");
+ CHECK_PASS(INDEXMA, 1, "X");
+ CHECK_PASS(MIST, 1, "Z");
+
+#undef CHECK_PASS
+}
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 76e6ca8d467..199322795f3 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -66,6 +66,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_hash.h"
#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
@@ -1458,6 +1459,14 @@ ObjectInstanceRen *RE_addRenderInstance(
}
}
+ /* Fill object info */
+ if (dob) {
+ obi->random_id = dob->random_id;
+ }
+ else {
+ obi->random_id = BLI_hash_int_2d(BLI_hash_string(obi->ob->id.name + 2), 0);
+ }
+
RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW);
if (mat) {
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index c4de95e863e..8dea0930b9e 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -2141,9 +2141,19 @@ const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int m
return NULL;
}
+float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi)
+{
+ return obi->ob->index;
+}
+
+float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi)
+{
+ return obi->random_id;
+}
+
const float (*RE_render_current_get_matrix(int matrix_id))[4]
{
- switch(matrix_id) {
+ switch (matrix_id) {
case RE_VIEW_MATRIX:
return (const float(*)[4])R.viewmat;
case RE_VIEWINV_MATRIX:
@@ -2171,4 +2181,4 @@ float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta)
}
return result;
-} \ No newline at end of file
+}
diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c
index d4e53eb7305..f0cf29e98ca 100644
--- a/source/blender/render/intern/source/sunsky.c
+++ b/source/blender/render/intern/source/sunsky.c
@@ -398,7 +398,7 @@ void InitAtmosphere(struct SunSky *sunSky, float sun_intens, float mief, float r
vLambda2[0] = fLambda2[0];
vLambda2[1] = fLambda2[1];
vLambda2[2] = fLambda2[2];
-
+
vLambda4[0] = fLambda4[0];
vLambda4[1] = fLambda4[1];
vLambda4[2] = fLambda4[2];
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index 610e86caa13..7fe52328781 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -275,10 +275,12 @@ static float metadensity(Object *ob, const float co[3])
break;
case MB_CUBE:
tp[2] = (tp[2] > ml->expz) ? (tp[2] - ml->expz) : ((tp[2] < -ml->expz) ? (tp[2] + ml->expz) : 0.f);
- /* no break, xy as plane */
+ /* no break, xy as plane */
+ ATTR_FALLTHROUGH;
case MB_PLANE:
tp[1] = (tp[1] > ml->expy) ? (tp[1] - ml->expy) : ((tp[1] < -ml->expy) ? (tp[1] + ml->expy) : 0.f);
- /* no break, x as tube */
+ /* no break, x as tube */
+ ATTR_FALLTHROUGH;
case MB_TUBE:
tp[0] = (tp[0] > ml->expx) ? (tp[0] - ml->expx) : ((tp[0] < -ml->expx) ? (tp[0] + ml->expx) : 0.f);
}
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 9f777631e52..68707f163af 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -1601,7 +1601,6 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
* Note: uses globals.
* \param v1 start coordinate s
* \param v2 target coordinate t
- * \param b1
* \param b2
* \param b3
* \param a index for coordinate (x, y, or z)
@@ -3494,7 +3493,7 @@ static void add_transp_speed(RenderLayer *rl, int offset, float speed[4], float
RenderPass *rpass;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
- if (rpass->passtype==SCE_PASS_VECTOR) {
+ if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
float *fp= rpass->rect + 4*offset;
if (speed==NULL) {
@@ -3528,7 +3527,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob)
RenderPass *rpass;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
- if (rpass->passtype == SCE_PASS_INDEXOB) {
+ if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) {
float *fp= rpass->rect + offset;
*fp= (float)ob->index;
break;
@@ -3541,7 +3540,7 @@ static void add_transp_material_index(RenderLayer *rl, int offset, Material *mat
RenderPass *rpass;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
- if (rpass->passtype == SCE_PASS_INDEXMA) {
+ if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) {
float *fp= rpass->rect + offset;
*fp= (float)mat->index;
break;
@@ -3558,78 +3557,74 @@ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr)
int delta= sizeof(ShadeResult)/4;
for (rpass= rl->passes.first; rpass; rpass= rpass->next) {
- float *col= NULL;
- int pixsize= 3;
+ float *col = NULL;
+ int pixsize = 3;
- switch (rpass->passtype) {
- case SCE_PASS_RGBA:
- col= shr->col;
- pixsize= 4;
- break;
- case SCE_PASS_EMIT:
- col= shr->emit;
- break;
- case SCE_PASS_DIFFUSE:
- col= shr->diff;
- break;
- case SCE_PASS_SPEC:
- col= shr->spec;
- break;
- case SCE_PASS_SHADOW:
- col= shr->shad;
- break;
- case SCE_PASS_AO:
- col= shr->ao;
- break;
- case SCE_PASS_ENVIRONMENT:
- col= shr->env;
- break;
- case SCE_PASS_INDIRECT:
- col= shr->indirect;
- break;
- case SCE_PASS_REFLECT:
- col= shr->refl;
- break;
- case SCE_PASS_REFRACT:
- col= shr->refr;
- break;
- case SCE_PASS_NORMAL:
- col= shr->nor;
- break;
- case SCE_PASS_MIST:
- col= &shr->mist;
- pixsize= 1;
- break;
- case SCE_PASS_Z:
- col= &shr->z;
- pixsize= 1;
- break;
- case SCE_PASS_VECTOR:
+ if (STREQ(rpass->name, RE_PASSNAME_RGBA)) {
+ col = shr->col;
+ pixsize = 4;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) {
+ col = shr->emit;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
+ col = shr->diff;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) {
+ col = shr->spec;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) {
+ col = shr->shad;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_AO)) {
+ col = shr->ao;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) {
+ col = shr->env;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) {
+ col = shr->indirect;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) {
+ col = shr->refl;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) {
+ col = shr->refr;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) {
+ col = shr->nor;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_MIST)) {
+ col = &shr->mist;
+ pixsize = 1;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
+ col = &shr->z;
+ pixsize = 1;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
+ ShadeResult *shr_t = shr+1;
+ float *fp = shr->winspeed; /* was initialized */
+ int samp;
+
+ /* add minimum speed in pixel */
+ for (samp = 1; samp<R.osa; samp++, shr_t++) {
- {
- ShadeResult *shr_t= shr+1;
- float *fp= shr->winspeed; /* was initialized */
- int samp;
+ if (shr_t->combined[3] > 0.0f) {
+ const float *speed = shr_t->winspeed;
- /* add minimum speed in pixel */
- for (samp= 1; samp<R.osa; samp++, shr_t++) {
-
- if (shr_t->combined[3] > 0.0f) {
- const float *speed= shr_t->winspeed;
-
- if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
- fp[0]= speed[0];
- fp[1]= speed[1];
- }
- if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
- fp[2]= speed[2];
- fp[3]= speed[3];
- }
- }
+ if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
+ fp[0] = speed[0];
+ fp[1] = speed[1];
+ }
+ if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
+ fp[2] = speed[2];
+ fp[3] = speed[3];
}
}
- break;
+ }
}
+
if (col) {
const float *fp= col+delta;
int samp;
@@ -3661,53 +3656,51 @@ static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, flo
float *fp, *col= NULL;
int pixsize= 3;
- switch (rpass->passtype) {
- case SCE_PASS_Z:
- fp= rpass->rect + offset;
- if (shr->z < *fp)
- *fp= shr->z;
- break;
- case SCE_PASS_RGBA:
- fp= rpass->rect + 4*offset;
- addAlphaOverFloat(fp, shr->col);
- break;
- case SCE_PASS_EMIT:
- col= shr->emit;
- break;
- case SCE_PASS_DIFFUSE:
- col= shr->diff;
- break;
- case SCE_PASS_SPEC:
- col= shr->spec;
- break;
- case SCE_PASS_SHADOW:
- col= shr->shad;
- break;
- case SCE_PASS_AO:
- col= shr->ao;
- break;
- case SCE_PASS_ENVIRONMENT:
- col= shr->env;
- break;
- case SCE_PASS_INDIRECT:
- col= shr->indirect;
- break;
- case SCE_PASS_REFLECT:
- col= shr->refl;
- break;
- case SCE_PASS_REFRACT:
- col= shr->refr;
- break;
- case SCE_PASS_NORMAL:
- col= shr->nor;
- break;
- case SCE_PASS_MIST:
- col= &shr->mist;
- pixsize= 1;
- break;
+ if (STREQ(rpass->name, RE_PASSNAME_Z)) {
+ fp = rpass->rect + offset;
+ if (shr->z < *fp)
+ *fp = shr->z;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) {
+ fp = rpass->rect + 4*offset;
+ addAlphaOverFloat(fp, shr->col);
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) {
+ col = shr->emit;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
+ col = shr->diff;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) {
+ col = shr->spec;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) {
+ col = shr->shad;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_AO)) {
+ col = shr->ao;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) {
+ col = shr->env;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) {
+ col = shr->indirect;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) {
+ col = shr->refl;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) {
+ col = shr->refr;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) {
+ col = shr->nor;
+ }
+ else if (STREQ(rpass->name, RE_PASSNAME_MIST)) {
+ col = &shr->mist;
+ pixsize = 1;
}
- if (col) {
+ if (col) {
fp= rpass->rect + pixsize*offset;
fp[0]= col[0] + (1.0f-alpha)*fp[0];
if (pixsize==3) {
@@ -3964,7 +3957,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf
float *fp, *col;
int a;
- fp = RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR, R.viewname);
+ fp = RE_RenderLayerGetPass(rl, RE_PASSNAME_VECTOR, R.viewname);
if (fp==NULL) return;
col= rectf+3;
@@ -4058,7 +4051,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
/* zero alpha pixels get speed vector max again */
if (addpassflag & SCE_PASS_VECTOR)
if (rl->layflag & SCE_LAY_SOLID) {
- float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname);
+ float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname);
reset_sky_speedvectors(pa, rl, rl->acolrect ? rl->acolrect : rect); /* if acolrect is set we use it */
}
/* filtered render, for now we assume only 1 filter size */
@@ -4246,7 +4239,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
if (alpha != 0.0f) {
RenderLayer *rl_other = ssamp.rlpp[a];
- float *rect = RE_RenderLayerGetPass(rl_other , SCE_PASS_COMBINED, R.viewname);
+ float *rect = RE_RenderLayerGetPass(rl_other , RE_PASSNAME_COMBINED, R.viewname);
addAlphaOverFloat(rect + 4 * od, samp_shr[a].combined);
add_transp_passes(rl_other , od, &samp_shr[a], alpha);
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index b6245a8c0d1..925563a0777 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -128,10 +128,6 @@ if(WITH_PYTHON)
../python
)
add_definitions(-DWITH_PYTHON)
-
- if(WITH_PYTHON_SECURITY)
- add_definitions(-DWITH_PYTHON_SECURITY)
- endif()
endif()
if(WITH_GAMEENGINE)
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 2b82f1becb3..492dec2cc10 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -102,7 +102,7 @@ enum {
};
struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
-struct wmWindow *WM_window_open_temp(struct bContext *C, const struct rcti *rect_init, int type);
+struct wmWindow *WM_window_open_temp(struct bContext *C, int x, int y, int sizex, int sizey, int type);
/* returns true if draw method is triple buffer */
bool WM_is_draw_triple(struct wmWindow *win);
@@ -252,6 +252,7 @@ int WM_operator_confirm_message(struct bContext *C, struct wmOperator *o
/* operator api */
void WM_operator_free (struct wmOperator *op);
+void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op);
void WM_operator_type_set(struct wmOperator *op, struct wmOperatorType *ot);
void WM_operator_stack_clear(struct wmWindowManager *wm);
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot);
@@ -276,6 +277,7 @@ int WM_operator_call (struct bContext *C, struct wmOperator *op);
int WM_operator_call_notest(struct bContext *C, struct wmOperator *op);
int WM_operator_repeat (struct bContext *C, struct wmOperator *op);
bool WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op);
+bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op);
int WM_operator_name_call_ptr(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties);
int WM_operator_name_call(struct bContext *C, const char *opstring, short context, struct PointerRNA *properties);
int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties, struct ReportList *reports, const bool is_undo);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index cd46e24264d..97f9257b4cb 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -542,7 +542,15 @@ typedef struct wmOperatorType {
* canceled due to some external reason, cancel is called
* - see defines below for return values */
int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
+
+ /* Called when a modal operator is canceled (not used often).
+ * Internal cleanup can be done here if needed. */
void (*cancel)(struct bContext *, struct wmOperator *);
+
+ /* Modal is used for operators which continuously run, eg:
+ * fly mode, knife tool, circle select are all examples of modal operators.
+ * Modal operators can handle events which would normally access other operators,
+ * they keep running until they don't return `OPERATOR_RUNNING_MODAL`. */
int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
/* verify if the operator can be executed in the current context, note
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index b76a1f1d422..67e961b9cd0 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -107,6 +107,17 @@ void WM_operator_free(wmOperator *op)
MEM_freeN(op);
}
+void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op)
+{
+ op = op->next;
+ while (op != NULL) {
+ wmOperator *op_next = op->next;
+ BLI_remlink(&wm->operators, op);
+ WM_operator_free(op);
+ op = op_next;
+ }
+}
+
/**
* Use with extreme care!,
* properties, customdata etc - must be compatible.
@@ -149,18 +160,23 @@ static void wm_reports_free(wmWindowManager *wm)
void wm_operator_register(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
- int tot;
+ int tot = 0;
BLI_addtail(&wm->operators, op);
- tot = BLI_listbase_count(&wm->operators);
-
- while (tot > MAX_OP_REGISTERED) {
- wmOperator *opt = wm->operators.first;
- BLI_remlink(&wm->operators, opt);
- WM_operator_free(opt);
- tot--;
+
+ /* only count registered operators */
+ while (op) {
+ wmOperator *op_prev = op->prev;
+ if (op->type->flag & OPTYPE_REGISTER) {
+ tot += 1;
+ }
+ if (tot > MAX_OP_REGISTERED) {
+ BLI_remlink(&wm->operators, op);
+ WM_operator_free(op);
+ }
+ op = op_prev;
}
-
+
/* so the console is redrawn */
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
WM_event_add_notifier(C, NC_WM | ND_HISTORY, NULL);
@@ -467,13 +483,12 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
void wm_close_and_free_all(bContext *C, ListBase *wmlist)
{
- Main *bmain = CTX_data_main(C);
wmWindowManager *wm;
-
+
while ((wm = wmlist->first)) {
wm_close_and_free(C, wm);
BLI_remlink(wmlist, wm);
- BKE_libblock_free_data(bmain, &wm->id);
+ BKE_libblock_free_data(&wm->id, true);
MEM_freeN(wm);
}
}
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 77ffa46b990..25c6980f58e 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -926,15 +926,14 @@ void wm_draw_update(bContext *C)
for (win = wm->windows.first; win; win = win->next) {
#ifdef WIN32
- if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
- GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
-
- if (state == GHOST_kWindowStateMinimized) {
- /* do not update minimized windows, it gives issues on intel drivers (see [#33223])
- * anyway, it seems logical to skip update for invisible windows
- */
- continue;
- }
+ GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
+
+ if (state == GHOST_kWindowStateMinimized) {
+ /* do not update minimized windows, gives issues on Intel (see T33223)
+ * and AMD (see T50856). it seems logical to skip update for invisible
+ * window anyway.
+ */
+ continue;
}
#endif
if (win->drawmethod != U.wmdrawmethod) {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index eba132062c9..f26ee0e73ec 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -715,7 +715,9 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
*/
static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot)
{
- return wm && (wm->op_undo_depth == 0) && (ot->flag & OPTYPE_REGISTER);
+ /* Check undo flag here since undo operators are also added to the list,
+ * to support checking if the same operator is run twice. */
+ return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO));
}
static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat)
@@ -878,6 +880,20 @@ bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op)
return false;
}
+bool WM_operator_is_repeat(const bContext *C, const wmOperator *op)
+{
+ /* may be in the operators list or not */
+ wmOperator *op_prev;
+ if (op->prev == NULL && op->next == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ op_prev = wm->operators.last;
+ }
+ else {
+ op_prev = op->prev;
+ }
+ return (op_prev && (op->type == op_prev->type));
+}
+
static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot,
PointerRNA *properties, ReportList *reports)
{
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 05d63869074..379772d5175 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -316,7 +316,7 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
}
/* in case UserDef was read, we re-initialize all, and do versioning */
-static void wm_init_userdef(bContext *C, const bool from_memory)
+static void wm_init_userdef(bContext *C, const bool use_factory_settings)
{
Main *bmain = CTX_data_main(C);
@@ -336,7 +336,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
}
/* avoid re-saving for every small change to our prefs, allow overrides */
- if (from_memory) {
+ if (use_factory_settings) {
BLO_update_defaults_userpref_blend();
}
@@ -470,6 +470,10 @@ static void wm_file_read_post(bContext *C, bool is_startup_file)
if (is_startup_file) {
/* possible python hasn't been initialized */
if (CTX_py_init_get(C)) {
+ /* Only run when we have a template path found. */
+ if (BKE_appdir_app_template_any()) {
+ BPY_execute_string(C, "__import__('bl_app_template_utils').reset()");
+ }
/* sync addons, these may have changed from the defaults */
BPY_execute_string(C, "__import__('addon_utils').reset_all()");
@@ -554,7 +558,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* confusing this global... */
G.relbase_valid = 1;
- retval = BKE_blendfile_read(C, filepath, reports);
+ retval = BKE_blendfile_read(C, filepath, reports, 0);
/* when loading startup.blend's, we can be left with a blank path */
if (G.main->name[0]) {
G.save_over = 1;
@@ -629,22 +633,34 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/**
- * called on startup, (context entirely filled with NULLs)
- * or called for 'New File'
- * both startup.blend and userpref.blend are checked
- * the optional parameter custom_file points to an alternative startup page
- * custom_file can be NULL
+ * Called on startup, (context entirely filled with NULLs)
+ * or called for 'New File' both startup.blend and userpref.blend are checked.
+ *
+ * \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead.
+ * Used for "Restore Factory Settings".
+ * \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL).
+ * \param app_template_override: Template to use instead of the template defined in user-preferences.
+ * When not-null, this is written into the user preferences.
*/
-int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file)
+int wm_homefile_read(
+ bContext *C, ReportList *reports,
+ bool use_factory_settings, bool use_empty_data,
+ const char *filepath_startup_override, const char *app_template_override)
{
ListBase wmbase;
- char startstr[FILE_MAX];
- char prefstr[FILE_MAX];
- int success = 0;
+ bool success = false;
+
+ char filepath_startup[FILE_MAX];
+ char filepath_userdef[FILE_MAX];
+
+ /* When 'app_template' is set: '{BLENDER_USER_CONFIG}/{app_template}' */
+ char app_template_system[FILE_MAX];
+ /* When 'app_template' is set: '{BLENDER_SYSTEM_SCRIPTS}/startup/bl_app_templates_system/{app_template}' */
+ char app_template_config[FILE_MAX];
/* Indicates whether user preferences were really load from memory.
*
- * This is used for versioning code, and for this we can not rely on from_memory
+ * This is used for versioning code, and for this we can not rely on use_factory_settings
* passed via argument. This is because there might be configuration folder
* exists but it might not have userpref.blend and in this case we fallback to
* reading home file from memory.
@@ -652,9 +668,10 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
* And in this case versioning code is to be run.
*/
bool read_userdef_from_memory = true;
+ eBLOReadSkip skip_flags = 0;
/* options exclude eachother */
- BLI_assert((from_memory && custom_file) == 0);
+ BLI_assert((use_factory_settings && filepath_startup_override) == 0);
if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) {
BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
@@ -665,71 +682,146 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
UI_view2d_zoom_cache_reset();
G.relbase_valid = 0;
- if (!from_memory) {
- const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
- if (custom_file) {
- BLI_strncpy(startstr, custom_file, FILE_MAX);
- if (cfgdir) {
- BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
- }
- else {
- prefstr[0] = '\0';
- }
+ /* put aside screens to match with persistent windows later */
+ wm_window_match_init(C, &wmbase);
+
+ filepath_startup[0] = '\0';
+ filepath_userdef[0] = '\0';
+ app_template_system[0] = '\0';
+ app_template_config[0] = '\0';
+
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
+ if (!use_factory_settings) {
+ if (cfgdir) {
+ BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL);
+ BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL);
}
- else if (cfgdir) {
- BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE);
- BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
+ else {
+ use_factory_settings = true;
+ }
+
+ if (filepath_startup_override) {
+ BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX);
+ }
+ }
+
+ /* load preferences before startup.blend */
+ if (!use_factory_settings && BLI_exists(filepath_userdef)) {
+ UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL);
+ if (userdef != NULL) {
+ BKE_blender_userdef_set_data(userdef);
+ MEM_freeN(userdef);
+
+ read_userdef_from_memory = false;
+ skip_flags |= BLO_READ_SKIP_USERDEF;
+ printf("Read prefs: %s\n", filepath_userdef);
+ }
+ }
+
+ const char *app_template = NULL;
+
+ if (filepath_startup_override != NULL) {
+ /* pass */
+ }
+ else if (app_template_override && app_template_override[0]) {
+ app_template = app_template_override;
+ }
+ else if (!use_factory_settings && U.app_template[0]) {
+ app_template = U.app_template;
+ }
+
+ if (app_template != NULL) {
+ BKE_appdir_app_template_id_search(app_template, app_template_system, sizeof(app_template_system));
+ BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL);
+ }
+
+ /* insert template name into startup file */
+ if (app_template != NULL) {
+ /* note that the path is being set even when 'use_factory_settings == true'
+ * this is done so we can load a templates factory-settings */
+ if (!use_factory_settings) {
+ BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE, NULL);
+ if (BLI_access(filepath_startup, R_OK) != 0) {
+ filepath_startup[0] = '\0';
+ }
}
else {
- startstr[0] = '\0';
- prefstr[0] = '\0';
- from_memory = 1;
+ filepath_startup[0] = '\0';
+ }
+
+ if (filepath_startup[0] == '\0') {
+ BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_system, BLENDER_STARTUP_FILE, NULL);
}
}
-
- /* put aside screens to match with persistent windows later */
- wm_window_match_init(C, &wmbase);
-
- if (!from_memory) {
- if (BLI_access(startstr, R_OK) == 0) {
- success = (BKE_blendfile_read(C, startstr, NULL) != BKE_BLENDFILE_READ_FAIL);
+
+ if (!use_factory_settings || (filepath_startup[0] != '\0')) {
+ if (BLI_access(filepath_startup, R_OK) == 0) {
+ success = (BKE_blendfile_read(C, filepath_startup, NULL, skip_flags) != BKE_BLENDFILE_READ_FAIL);
}
if (BLI_listbase_is_empty(&U.themes)) {
if (G.debug & G_DEBUG)
- printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr);
- success = 0;
+ printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", filepath_startup);
+ success = false;
}
}
- if (success == 0 && custom_file && reports) {
- BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file);
- /*We can not return from here because wm is already reset*/
+ if (success == false && filepath_startup_override && reports) {
+ /* We can not return from here because wm is already reset */
+ BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", filepath_startup_override);
}
- if (success == 0) {
- success = BKE_blendfile_read_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true);
+ if (success == false) {
+ success = BKE_blendfile_read_from_memory(
+ C, datatoc_startup_blend, datatoc_startup_blend_size,
+ NULL, skip_flags, true);
if (BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
}
- BKE_tempdir_init(U.tempdir);
+ }
-#ifdef WITH_PYTHON_SECURITY
- /* use alternative setting for security nuts
- * otherwise we'd need to patch the binary blob - startup.blend.c */
- U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
-#endif
+ if (use_empty_data) {
+ BKE_blendfile_read_make_empty(C);
}
-
- /* check new prefs only after startup.blend was finished */
- if (!from_memory && BLI_exists(prefstr)) {
- int done = BKE_blendfile_read_userdef(prefstr, NULL);
- if (done != BKE_BLENDFILE_READ_FAIL) {
- read_userdef_from_memory = false;
- printf("Read new prefs: %s\n", prefstr);
+
+ /* Load template preferences,
+ * unlike regular preferences we only use some of the settings,
+ * see: BKE_blender_userdef_set_app_template */
+ if (app_template_system[0] != '\0') {
+ char temp_path[FILE_MAX];
+ temp_path[0] = '\0';
+ if (!use_factory_settings) {
+ BLI_path_join(temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE, NULL);
+ if (BLI_access(temp_path, R_OK) != 0) {
+ temp_path[0] = '\0';
+ }
+ }
+
+ if (temp_path[0] == '\0') {
+ BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL);
+ }
+
+ UserDef *userdef_template = NULL;
+ /* just avoids missing file warning */
+ if (BLI_exists(temp_path)) {
+ userdef_template = BKE_blendfile_userdef_read(temp_path, NULL);
+ }
+ if (userdef_template == NULL) {
+ /* we need to have preferences load to overwrite preferences from previous template */
+ userdef_template = BKE_blendfile_userdef_read_from_memory(
+ datatoc_startup_blend, datatoc_startup_blend_size, NULL);
+ }
+ if (userdef_template) {
+ BKE_blender_userdef_set_app_template(userdef_template);
+ BKE_blender_userdef_free_data(userdef_template);
+ MEM_freeN(userdef_template);
}
}
-
+
+ if (app_template_override) {
+ BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template));
+ }
+
/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
* can remove this eventually, only in a 2.53 and older, now its not written */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
@@ -744,11 +836,14 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
G.main->name[0] = '\0';
/* When loading factory settings, the reset solid OpenGL lights need to be applied. */
- if (!G.background) GPU_default_lights();
-
- /* XXX */
- G.save_over = 0; // start with save preference untitled.blend
- G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */
+ if (!G.background) {
+ GPU_default_lights();
+ }
+
+ /* start with save preference untitled.blend */
+ G.save_over = 0;
+ /* disable auto-play in startup.blend... */
+ G.fileflags &= ~G_FILE_AUTOPLAY;
wm_file_read_post(C, true);
@@ -998,7 +1093,7 @@ static int wm_file_write(bContext *C, const char *filepath, int fileflags, Repor
BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath);
return ret;
}
-
+
/* 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 */
@@ -1264,6 +1359,13 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
char filepath[FILE_MAX];
int fileflags;
+ const char *app_template = U.app_template[0] ? U.app_template : NULL;
+ const char * const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template);
+ if (cfgdir == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create user config path");
+ return OPERATOR_CANCELLED;
+ }
+
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
/* check current window and close it if temp */
@@ -1273,7 +1375,8 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE, NULL);
+
printf("trying to save homefile at %s ", filepath);
ED_editors_flush_edits(C, false);
@@ -1351,21 +1454,44 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
char filepath[FILE_MAX];
+ const char *cfgdir;
+ bool ok = false;
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
- printf("trying to save userpref at %s ", filepath);
-
- if (BKE_blendfile_write_userdef(filepath, op->reports) == 0) {
- printf("fail\n");
- return OPERATOR_CANCELLED;
+ if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) {
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ printf("trying to save userpref at %s ", filepath);
+ if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) {
+ printf("ok\n");
+ ok = true;
+ }
+ else {
+ printf("fail\n");
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path");
}
- printf("ok\n");
+ if (U.app_template[0] && (cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
+ /* Also save app-template prefs */
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ printf("trying to save app-template userpref at %s ", filepath);
+ if (BKE_blendfile_userdef_write(filepath, op->reports) == 0) {
+ printf("fail\n");
+ ok = true;
+ }
+ else {
+ printf("ok\n");
+ }
+ }
+ else if (U.app_template[0]) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path");
+ }
- return OPERATOR_FINISHED;
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void WM_OT_save_userpref(wmOperatorType *ot)
@@ -1400,11 +1526,11 @@ void WM_OT_read_history(wmOperatorType *ot)
static int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
- const bool from_memory = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
+ const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
char filepath_buf[FILE_MAX];
const char *filepath = NULL;
- if (!from_memory) {
+ if (!use_factory_settings) {
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
/* This can be used when loading of a start-up file should only change
@@ -1426,7 +1552,34 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
G.fileflags &= ~G_FILE_NO_UI;
}
- return wm_homefile_read(C, op->reports, from_memory, filepath) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ char app_template_buf[sizeof(U.app_template)];
+ const char *app_template;
+ PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template");
+ const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash");
+ const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty");
+
+ if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) {
+ RNA_property_string_get(op->ptr, prop_app_template, app_template_buf);
+ app_template = app_template_buf;
+ }
+ else if (!use_factory_settings) {
+ /* TODO: dont reset prefs on 'New File' */
+ BLI_strncpy(app_template_buf, U.app_template, sizeof(app_template_buf));
+ app_template = app_template_buf;
+ }
+ else {
+ app_template = NULL;
+ }
+
+ if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, filepath, app_template)) {
+ if (use_splash) {
+ WM_init_splash(C);
+ }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void WM_OT_read_homefile(wmOperatorType *ot)
@@ -1449,17 +1602,36 @@ void WM_OT_read_homefile(wmOperatorType *ot)
"Load user interface setup from the .blend file");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ /* So the splash can be kept open after loading a file (for templates). */
+ prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
/* omit poll to run in background mode */
}
void WM_OT_read_factory_settings(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
ot->name = "Load Factory Settings";
ot->idname = "WM_OT_read_factory_settings";
ot->description = "Load default file and user preferences";
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_read_exec;
+
+ prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
/* omit poll to run in background mode */
}
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 3b733f9558c..f19c999a4f1 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -608,7 +608,8 @@ static void lib_relocate_do(
}
/* Note that in reload case, we also want to replace indirect usages. */
- const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
+ const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
+ (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) {
WMLinkAppendDataItem *item = itemlink->link;
ID *old_id = item->customdata;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 4b2369a1a7c..9bafe72d805 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -192,7 +192,7 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_init_reports(C);
/* get the default database, plus a wm */
- wm_homefile_read(C, NULL, G.factory_startup, NULL);
+ wm_homefile_read(C, NULL, G.factory_startup, false, NULL, NULL);
BLT_lang_set(NULL);
@@ -572,7 +572,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_file_exit(); /* for fsmenu */
UI_exit();
- BKE_blender_userdef_free();
+ BKE_blender_userdef_free_data(&U);
RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index e201fa433d4..db5fc23146f 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -121,6 +121,13 @@ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
if (ot->srna != kmi->ptr->type) {
/* matches wm_keymap_item_properties_set but doesnt alloc new ptr */
WM_operator_properties_create_ptr(kmi->ptr, ot);
+ /* 'kmi->ptr->data' NULL'd above, keep using existing properties.
+ * Note: the operators property types may have changed,
+ * we will need a more comprehensive sanitize function to support this properly.
+ */
+ if (kmi->properties) {
+ kmi->ptr->data = kmi->properties;
+ }
WM_operator_properties_sanitize(kmi->ptr, 1);
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index cef5e7e4a8e..d3ebd3e4d2c 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -900,7 +900,7 @@ void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
{
- wmOperatorType *ot = WM_operatortype_find(opstring, 0);
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
if (ot)
WM_operator_properties_create_ptr(ptr, ot);
@@ -1118,6 +1118,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ search[0] = '\0';
#if 0 /* ok, this isn't so easy... */
uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
#endif
@@ -1402,20 +1403,6 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
}
}
-static void popup_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
-{
- wmOperator *op = op_ptr;
- if (op->type->check) {
- if (op->type->check(C, op)) {
- /* check for popup and re-layout buttons */
- ARegion *ar_menu = CTX_wm_menu(C);
- if (ar_menu) {
- ED_region_tag_refresh_ui(ar_menu);
- }
- }
- }
-}
-
/* Dialogs are popups that require user verification (click OK) before exec */
static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
{
@@ -1434,8 +1421,6 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
- UI_block_func_set(block, popup_check_cb, op, NULL);
-
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
/* clear so the OK button is left alone */
@@ -1474,8 +1459,6 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
- UI_block_func_set(block, popup_check_cb, op, NULL);
-
/* since ui is defined the auto-layout args are not used */
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
@@ -1522,7 +1505,7 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
data->width = width;
data->height = height;
data->free_op = true; /* if this runs and gets registered we may want not to free it */
- UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -1552,7 +1535,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
if (!do_redo || !(U.uiflag & USER_GLOBALUNDO))
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
- UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
+ UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op, op);
if (do_call)
wm_block_redo_cb(C, op, 0);
@@ -1594,7 +1577,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int h
data->free_op = true; /* if this runs and gets registered we may want not to free it */
/* op is not executed until popup OK but is clicked */
- UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -1761,6 +1744,36 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
ibuf = IMB_ibImageFromMemory((unsigned char *)datatoc_splash_png,
datatoc_splash_png_size, IB_rect, NULL, "<splash screen>");
}
+
+ /* overwrite splash with template image */
+ if (U.app_template[0] != '\0') {
+ ImBuf *ibuf_template = NULL;
+ char splash_filepath[FILE_MAX];
+ char template_directory[FILE_MAX];
+
+ if (BKE_appdir_app_template_id_search(
+ U.app_template,
+ template_directory, sizeof(template_directory)))
+ {
+ BLI_join_dirfile(
+ splash_filepath, sizeof(splash_filepath), template_directory,
+ (U.pixelsize == 2) ? "splash_2x.png" : "splash.png");
+ ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL);
+ if (ibuf_template) {
+ const int x_expect = ibuf->x;
+ const int y_expect = 230 * (int)U.pixelsize;
+ /* don't cover the header text */
+ if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) {
+ memcpy(ibuf->rect, ibuf_template->rect, ibuf_template->x * ibuf_template->y * sizeof(char[4]));
+ }
+ else {
+ printf("Splash expected %dx%d found %dx%d, ignoring: %s\n",
+ x_expect, y_expect, ibuf_template->x, ibuf_template->y, splash_filepath);
+ }
+ IMB_freeImBuf(ibuf_template);
+ }
+ }
+ }
#endif
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
@@ -1786,13 +1799,13 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
if (version_suffix != NULL && version_suffix[0]) {
/* placed after the version number in the image,
* placing y is tricky to match baseline */
- int x = 260 - (2 * UI_DPI_WINDOW_FAC);
- int y = 242 + (4 * UI_DPI_WINDOW_FAC);
- int w = 240;
+ int x = 260 * U.pixelsize - (2 * UI_DPI_FAC);
+ int y = 242 * U.pixelsize + (4 * UI_DPI_FAC);
+ int w = 240 * U.pixelsize;
/* hack to have text draw 'text_sel' */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, version_suffix, x * U.pixelsize, y * U.pixelsize, w * U.pixelsize, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ but = uiDefBut(block, UI_BTYPE_LABEL, 0, version_suffix, x, y, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
/* XXX, set internal flag - UI_SELECT */
UI_but_flag_enable(but, 1);
UI_block_emboss_set(block, UI_EMBOSS);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 2d43c47679d..de169881bc4 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -77,6 +77,7 @@
#include "GPU_extensions.h"
#include "GPU_init_exit.h"
#include "GPU_glew.h"
+#include "BLF_api.h"
/* for assert */
#ifndef NDEBUG
@@ -311,7 +312,7 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
if (tmpwin == NULL)
do_exit = 1;
- if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved) {
+ if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) {
if (do_exit) {
if (!GHOST_confirmQuit(win->ghostwin))
return;
@@ -374,14 +375,39 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
}
}
-static float wm_window_get_virtual_pixelsize(void)
+static void wm_window_set_dpi(wmWindow *win)
{
- return ((U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1.0f : 2.0f);
-}
+ int auto_dpi = GHOST_GetDPIHint(win->ghostwin);
-float wm_window_pixelsize(wmWindow *win)
-{
- return (GHOST_GetNativePixelSize(win->ghostwin) * wm_window_get_virtual_pixelsize());
+ /* Lazily init UI scale size, preserving backwards compatibility by
+ * computing UI scale from ratio of previous DPI and auto DPI */
+ if (U.ui_scale == 0) {
+ int virtual_pixel = (U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1 : 2;
+
+ if (U.dpi == 0) {
+ U.ui_scale = virtual_pixel;
+ }
+ else {
+ U.ui_scale = (virtual_pixel * U.dpi * 96.0f) / (auto_dpi * 72.0f);
+ }
+
+ CLAMP(U.ui_scale, 0.25f, 4.0f);
+ }
+
+ /* Blender's UI drawing assumes DPI 72 as a good default following macOS
+ * while Windows and Linux use DPI 96. GHOST assumes a default 96 so we
+ * remap the DPI to Blender's convention. */
+ int dpi = auto_dpi * U.ui_scale * (72.0 / 96.0f);
+
+ /* Automatically set larger pixel size for high DPI. */
+ int pixelsize = MAX2(1, dpi / 54);
+
+ /* Set user preferences globals for drawing, and for forward compatibility. */
+ U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize;
+ U.dpi = dpi / pixelsize;
+ U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE;
+
+ BKE_blender_userdef_refresh();
}
/* belongs to below */
@@ -456,10 +482,8 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
glClear(GL_COLOR_BUFFER_BIT);
}
- /* displays with larger native pixels, like Macbook. Used to scale dpi with */
/* needed here, because it's used before it reads userdef */
- U.pixelsize = wm_window_pixelsize(win);
- BKE_blender_userdef_refresh();
+ wm_window_set_dpi(win);
wm_window_swap_buffers(win);
@@ -618,15 +642,27 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
* \param type: WM_WINDOW_RENDER, WM_WINDOW_USERPREFS...
* \return the window or NULL.
*/
-wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type)
+wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, int type)
{
wmWindow *win_prev = CTX_wm_window(C);
wmWindow *win;
ScrArea *sa;
Scene *scene = CTX_data_scene(C);
const char *title;
- rcti rect = *rect_init;
- const short px_virtual = (short)wm_window_get_virtual_pixelsize();
+
+ /* convert to native OS window coordinates */
+ const float native_pixel_size = GHOST_GetNativePixelSize(win_prev->ghostwin);
+ x /= native_pixel_size;
+ y /= native_pixel_size;
+ sizex /= native_pixel_size;
+ sizey /= native_pixel_size;
+
+ /* calculate postition */
+ rcti rect;
+ rect.xmin = x + win_prev->posx - sizex / 2;
+ rect.ymin = y + win_prev->posy - sizey / 2;
+ rect.xmax = rect.xmin + sizex;
+ rect.ymax = rect.ymin + sizey;
/* changes rect to fit within desktop */
wm_window_check_position(&rect);
@@ -644,9 +680,8 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type)
win->posy = rect.ymin;
}
- /* multiply with virtual pixelsize, ghost handles native one (e.g. for retina) */
- win->sizex = BLI_rcti_size_x(&rect) * px_virtual;
- win->sizey = BLI_rcti_size_y(&rect) * px_virtual;
+ win->sizex = BLI_rcti_size_x(&rect);
+ win->sizey = BLI_rcti_size_y(&rect);
if (win->ghostwin) {
wm_window_set_size(win, win->sizex, win->sizey);
@@ -835,8 +870,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
GHOST_ActivateWindowDrawingContext(win->ghostwin);
/* this can change per window */
- U.pixelsize = wm_window_pixelsize(win);
- BKE_blender_userdef_refresh();
+ wm_window_set_dpi(win);
}
}
@@ -1035,6 +1069,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
if (type == GHOST_kEventWindowSize) {
WM_jobs_stop(wm, win->screen, NULL);
}
+
+ wm_window_set_dpi(win);
/* win32: gives undefined window size when minimized */
if (state != GHOST_kWindowStateMinimized) {
@@ -1118,7 +1154,19 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
}
break;
}
-
+
+ case GHOST_kEventWindowDPIHintChanged:
+ {
+ wm_window_set_dpi(win);
+ /* font's are stored at each DPI level, without this we can easy load 100's of fonts */
+ BLF_cache_clear();
+
+ BKE_blender_userdef_refresh();
+ WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
+ break;
+ }
+
case GHOST_kEventOpenMainFile:
{
PointerRNA props_ptr;
@@ -1199,11 +1247,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
{
// only update if the actual pixel size changes
float prev_pixelsize = U.pixelsize;
- U.pixelsize = wm_window_pixelsize(win);
+ wm_window_set_dpi(win);
if (U.pixelsize != prev_pixelsize) {
- BKE_blender_userdef_refresh();
-
// close all popups since they are positioned with the pixel
// size baked in and it's difficult to correct them
wmWindow *oldWindow = CTX_wm_window(C);
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 396907a3f6d..9a1518e15b0 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -35,7 +35,10 @@ struct wmOperatorType;
/* wm_files.c */
void wm_history_file_read(void);
-int wm_homefile_read(struct bContext *C, struct ReportList *reports, bool from_memory, const char *filepath);
+int wm_homefile_read(
+ struct bContext *C, struct ReportList *reports,
+ bool use_factory_settings, bool use_empty_data,
+ const char *filepath_startup_override, const char *app_template_override);
void wm_file_read_report(bContext *C);
void WM_OT_save_homefile(struct wmOperatorType *ot);
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index c106f9d7851..f70ec6b47f6 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -63,8 +63,6 @@ void wm_window_swap_buffers (wmWindow *win);
void wm_window_set_swap_interval(wmWindow *win, int interval);
bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
-float wm_window_pixelsize(wmWindow *win);
-
void wm_get_cursor_position (wmWindow *win, int *x, int *y);
void wm_cursor_position_from_ghost (wmWindow *win, int *x, int *y);
void wm_cursor_position_to_ghost (wmWindow *win, int *x, int *y);
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 58bebc66a3e..66c72be3d5d 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -35,24 +35,13 @@ if(WIN32 AND NOT UNIX)
string(SUBSTRING ${BLENDER_VERSION} 0 1 bver1)
string(SUBSTRING ${BLENDER_VERSION} 2 1 bver2)
string(SUBSTRING ${BLENDER_VERSION} 3 1 bver3)
- if(MINGW)
- add_definitions(
- -DWINDRES
- -DBLEN_VER_RC_STR_M=${BLENDER_VERSION}
- -DBLEN_VER_RC_1=${bver1}
- -DBLEN_VER_RC_2=${bver2}
- -DBLEN_VER_RC_3=${bver3}
- -DBLEN_VER_RC_4=0
- )
- else()
- add_definitions(
- -DBLEN_VER_RC_STR=${BLENDER_VERSION}
- -DBLEN_VER_RC_1=${bver1}
- -DBLEN_VER_RC_2=${bver2}
- -DBLEN_VER_RC_3=${bver3}
- -DBLEN_VER_RC_4=0
- )
- endif()
+ add_definitions(
+ -DBLEN_VER_RC_STR=${BLENDER_VERSION}
+ -DBLEN_VER_RC_1=${bver1}
+ -DBLEN_VER_RC_2=${bver2}
+ -DBLEN_VER_RC_3=${bver3}
+ -DBLEN_VER_RC_4=0
+ )
add_executable(
blenderplayer ${EXETYPE}
@@ -176,11 +165,17 @@ endif()
extern_rangetree
extern_wcwidth
bf_intern_libmv
- extern_glog
- extern_gflags
extern_sdlew
)
+ if(NOT WITH_SYSTEM_GLOG)
+ list(APPEND BLENDER_SORTED_LIBS extern_glog)
+ endif()
+
+ if(NOT WITH_SYSTEM_GFLAGS)
+ list(APPEND BLENDER_SORTED_LIBS extern_gflags)
+ endif()
+
if(WITH_MOD_CLOTH_ELTOPO)
list(APPEND BLENDER_SORTED_LIBS extern_eltopo)
endif()
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 08d00e9148a..d00c7b6a022 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -199,6 +199,7 @@ extern bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id);
extern const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid);
extern const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid);
extern struct PyObject *pyrna_id_CreatePyObject(struct ID *id);
+extern bool pyrna_id_CheckPyObject(struct PyObject *obj);
/* bpy_interface.c */
bool BPY_string_is_keyword(const char *str) { return false; }
@@ -229,7 +230,7 @@ void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE
void *g_system;
bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO
-float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
+float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL
float RE_filter_value(int type, float x) RET_ZERO
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) RET_NULL
void RE_texture_rng_init() RET_NONE
@@ -243,6 +244,7 @@ float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *c
int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO
void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE
+struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL
struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
bool RE_HasFakeLayer(RenderResult *res) RET_ZERO
@@ -273,6 +275,8 @@ struct Object *RE_GetCamera(struct Render *re) RET_NULL
float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] RET_NULL
const float (*RE_render_current_get_matrix(int matrix_id))[4] RET_NULL
+float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) RET_ZERO
+float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi) RET_ZERO
/* blenkernel */
bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) RET_ZERO
@@ -306,6 +310,7 @@ int WM_operator_confirm(struct bContext *C, struct wmOperator *op, const struct
struct MenuType *WM_menutype_find(const char *idname, bool quiet) RET_NULL
void WM_operator_stack_clear(struct wmWindowManager *wm) RET_NONE
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot) RET_NONE
+bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op) RET_ZERO;
void WM_autosave_init(wmWindowManager *wm) RET_NONE
void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner) RET_NONE
@@ -477,7 +482,7 @@ void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist
struct BGpic *ED_view3D_background_image_new(struct View3D *v3d) RET_NULL
void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic) RET_NONE
void ED_view3D_background_image_clear(struct View3D *v3d) RET_NONE
-void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]) RET_NONE
+void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4], const struct rcti *rect) RET_NONE
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) RET_ZERO
void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa) RET_NONE
void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE
@@ -649,7 +654,8 @@ struct RenderData *RE_engine_get_render_data(struct Render *re) RET_NULL
void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) RET_NONE
void RE_engine_update_progress(struct RenderEngine *engine, float progress) RET_NONE
void RE_engine_set_error_message(RenderEngine *engine, const char *msg) RET_NONE
-void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results) RET_NONE
+void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername) RET_NONE
+void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int highlight, int merge_results) RET_NONE
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) RET_NONE
void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y) RET_NONE
void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename) RET_NONE
@@ -674,6 +680,7 @@ void RE_point_density_free(struct PointDensity *pd) RET_NONE
void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
void RE_FreeAllPersistentData(void) RET_NONE
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
+void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int channels, const char *chanid, int type) RET_NONE
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
@@ -714,7 +721,9 @@ struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL
int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname,
const char *propname, const struct wmEvent *event) RET_ZERO
-/* RNA COLLADA dependency */
+/* RNA COLLADA dependency */
+/* XXX (gaia) Why do we need this declaration here? */
+/* The collada header is included anyways further up... */
int collada_export(struct Scene *sce,
const char *filepath,
int apply_modifiers,
@@ -727,8 +736,7 @@ int collada_export(struct Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -736,12 +744,17 @@ int collada_export(struct Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim) RET_ZERO
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info) RET_ZERO
void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE
/* bpy/python internal api */
-void operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
+extern void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata);
+extern void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata);
+void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
+void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
void BPY_text_free_code(struct Text *text) RET_NONE
void BPY_id_release(struct ID *id) RET_NONE
int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result) RET_ZERO
@@ -749,9 +762,9 @@ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTa
float BPY_driver_exec(PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime) RET_ZERO /* might need this one! */
void BPY_DECREF(void *pyob_ptr) RET_NONE
void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) RET_NONE
-void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO
struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL
+bool pyrna_id_CheckPyObject(struct PyObject *obj) RET_ZERO
void BPY_context_update(struct bContext *C) RET_NONE
const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) RET_ARG(msgid)
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index eea45545949..8f26e248424 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -113,24 +113,13 @@ if(WIN32 AND NOT UNIX)
string(SUBSTRING ${BLENDER_VERSION} 0 1 bver1)
string(SUBSTRING ${BLENDER_VERSION} 2 1 bver2)
string(SUBSTRING ${BLENDER_VERSION} 3 1 bver3)
- if(MINGW)
- add_definitions(
- -DWINDRES
- -DBLEN_VER_RC_STR_M=${BLENDER_VERSION}
- -DBLEN_VER_RC_1=${bver1}
- -DBLEN_VER_RC_2=${bver2}
- -DBLEN_VER_RC_3=${bver3}
- -DBLEN_VER_RC_4=0
- )
- else()
- add_definitions(
- -DBLEN_VER_RC_STR=${BLENDER_VERSION}
- -DBLEN_VER_RC_1=${bver1}
- -DBLEN_VER_RC_2=${bver2}
- -DBLEN_VER_RC_3=${bver3}
- -DBLEN_VER_RC_4=0
- )
- endif()
+ add_definitions(
+ -DBLEN_VER_RC_STR=${BLENDER_VERSION}
+ -DBLEN_VER_RC_1=${bver1}
+ -DBLEN_VER_RC_2=${bver2}
+ -DBLEN_VER_RC_3=${bver3}
+ -DBLEN_VER_RC_4=0
+ )
list(APPEND SRC
@@ -652,7 +641,6 @@ elseif(WIN32)
if(WITH_PYTHON)
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
- # MinGW TODO: This bit of Python configuration diverges from MSVC
if(NOT CMAKE_COMPILER_IS_GNUCC)
install(
FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll
@@ -721,9 +709,9 @@ elseif(WIN32)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy
COMMAND ${CMAKE_COMMAND} -E
- tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}.tar.gz"
+ tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}$<$<CONFIG:Debug>:d>.tar.gz"
DEPENDS
- ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}.tar.gz
+ ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}$<$<CONFIG:Debug>:d>.tar.gz
${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages
)
@@ -749,20 +737,6 @@ elseif(WIN32)
DESTINATION ${BLENDER_VERSION}/python/bin
CONFIGURATIONS Debug
)
-
- # MinGW needs Python DLL
- if(MINGW)
- install(
- FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll
- DESTINATION "."
- CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel
- )
- install(
- FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll
- DESTINATION "."
- CONFIGURATIONS Debug
- )
- endif()
endif()
unset(_PYTHON_VERSION_NO_DOTS)
@@ -785,57 +759,19 @@ elseif(WIN32)
FILES ${LIBDIR}/pthreads/lib/pthreadVC2.dll
DESTINATION "."
)
- else()
- #MinGW64 comes with own version. For portable builds it will probaly have to be copied to work
- if(NOT WITH_MINGW64)
- install(
- FILES ${LIBDIR}/pthreads/lib/pthreadGC2.dll
- DESTINATION "."
- )
- elseif(WITH_MINGW64)
- install(
- FILES
- ${LIBDIR}/binaries/libgcc_s_sjlj-1.dll
- ${LIBDIR}/binaries/libwinpthread-1.dll
- ${LIBDIR}/binaries/libstdc++-6.dll
- DESTINATION "."
- )
-
- if(WITH_OPENMP)
- install(
- FILES
- ${LIBDIR}/binaries/libgomp-1.dll
- DESTINATION "."
- )
- endif()
- endif()
endif()
if(WITH_CODEC_FFMPEG)
- if(WITH_MINGW64)
- install(
- FILES
- ${LIBDIR}/ffmpeg/lib/avcodec-53.dll
- ${LIBDIR}/ffmpeg/lib/avformat-53.dll
- ${LIBDIR}/ffmpeg/lib/avdevice-53.dll
- ${LIBDIR}/ffmpeg/lib/avutil-51.dll
- ${LIBDIR}/ffmpeg/lib/swscale-2.dll
- ${LIBDIR}/ffmpeg/lib/swresample-0.dll
- ${LIBDIR}/ffmpeg/lib/xvidcore.dll
- DESTINATION "."
- )
- else()
- install(
- FILES
- ${LIBDIR}/ffmpeg/lib/avcodec-57.dll
- ${LIBDIR}/ffmpeg/lib/avformat-57.dll
- ${LIBDIR}/ffmpeg/lib/avdevice-57.dll
- ${LIBDIR}/ffmpeg/lib/avutil-55.dll
- ${LIBDIR}/ffmpeg/lib/swscale-4.dll
- ${LIBDIR}/ffmpeg/lib/swresample-2.dll
- DESTINATION "."
- )
- endif()
+ install(
+ FILES
+ ${LIBDIR}/ffmpeg/lib/avcodec-57.dll
+ ${LIBDIR}/ffmpeg/lib/avformat-57.dll
+ ${LIBDIR}/ffmpeg/lib/avdevice-57.dll
+ ${LIBDIR}/ffmpeg/lib/avutil-55.dll
+ ${LIBDIR}/ffmpeg/lib/swscale-4.dll
+ ${LIBDIR}/ffmpeg/lib/swresample-2.dll
+ DESTINATION "."
+ )
endif()
if(WITH_CODEC_SNDFILE)
@@ -851,30 +787,13 @@ elseif(WIN32)
${LIBDIR}/openal/lib/OpenAL32.dll
DESTINATION "."
)
- # MinGW TODO: Need to update to a newer OpenAL version
- # which does not depend on wrap_oal.dll
- if(CMAKE_COMPILER_IS_GNUCC)
- install(
- FILES
- ${LIBDIR}/openal/lib/wrap_oal.dll
- DESTINATION "."
- )
- endif()
endif()
if(WITH_SDL)
- #MinGW TODO: Update to SDL2
- if(NOT CMAKE_COMPILER_IS_GNUCC)
- install(
- FILES ${LIBDIR}/sdl/lib/SDL2.dll
- DESTINATION "."
- )
- else()
- install(
- FILES ${LIBDIR}/sdl/lib/SDL.dll
- DESTINATION "."
- )
- endif()
+ install(
+ FILES ${LIBDIR}/sdl/lib/SDL2.dll
+ DESTINATION "."
+ )
endif()
if(WITH_SYSTEM_AUDASPACE)
@@ -901,19 +820,11 @@ elseif(WIN32)
if(WITH_OPENCOLORIO)
set(OCIOBIN ${LIBDIR}/opencolorio/bin)
- if(NOT MINGW)
install(
FILES
${OCIOBIN}/OpenColorIO.dll
DESTINATION "."
)
- else()
- install(
- FILES
- ${OCIOBIN}/libOpenColorIO.dll
- DESTINATION "."
- )
- endif()
endif()
elseif(APPLE)
@@ -997,21 +908,26 @@ elseif(APPLE)
# python
if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
- # the python zip is first extract as part of the build process,
+ # the python zip is first extracted as part of the build process,
# and then later installed as part of make install. this is much
# quicker, and means we can easily exclude files on copy
- # Not needed for PYTHON_MODULE or WEB_PLUGIN due uses Pyhon framework
+ # Not needed for PYTHON_MODULE or WEB_PLUGIN due uses Pyhon framework
+ # use a hash of the .zip path to handle switching between different
+ # lib directories without needing a clean build
+ string(SHA1 PYTHON_ZIP_HASH ${LIBDIR}/release/${PYTHON_ZIP})
+ set(PYTHON_EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PYTHON_ZIP_HASH}/python)
+
add_custom_target(
extractpyzip
- DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/python)
+ DEPENDS ${PYTHON_EXTRACT_DIR})
set(PYTHON_ZIP "python_${CMAKE_OSX_ARCHITECTURES}.zip")
add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/python
- COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
- COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
- COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ OUTPUT ${PYTHON_EXTRACT_DIR}
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/"
${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
@@ -1019,13 +935,13 @@ elseif(APPLE)
# copy extracted python files
install_dir(
- ${CMAKE_CURRENT_BINARY_DIR}/python
+ ${PYTHON_EXTRACT_DIR}
\${TARGETDIR_VER}
)
# copy site-packages files
install_dir(
${LIBDIR}/release/site-packages
- ${CMAKE_CURRENT_BINARY_DIR}/python/lib/python${PYTHON_VERSION}
+ \${TARGETDIR_VER}/python/lib/python${PYTHON_VERSION}
)
install(DIRECTORY ${LIBDIR}/python/bin
@@ -1082,16 +998,16 @@ elseif(APPLE)
# python
if(WITH_PYTHON AND NOT WITH_PYTHON_FRAMEWORK)
add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/python
- COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
- COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/python/"
- COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/python/"
+ OUTPUT ${PYTHON_EXTRACT_DIR}
+ COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/"
+ COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/"
${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}"
DEPENDS ${LIBDIR}/release/${PYTHON_ZIP})
# copy extracted python files
install_dir(
- ${CMAKE_CURRENT_BINARY_DIR}/python
+ ${PYTHON_EXTRACT_DIR}
\${PLAYER_TARGETDIR_VER}
)
endif()
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index d7fe8d8ce59..6e698166fd9 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -40,7 +40,7 @@
# pragma warning (disable:4786)
#endif
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "KX_BlenderCanvas.h"
#include "KX_BlenderKeyboardDevice.h"
@@ -104,13 +104,13 @@ typedef void * wmUIHandlerRemoveFunc;
# include AUD_DEVICE_H
#endif
-static BlendFileData *load_game_data(char *filename)
+static BlendFileData *load_game_data(const char *filename)
{
ReportList reports;
BlendFileData *bfd;
BKE_reports_init(&reports, RPT_STORE);
- bfd= BLO_read_from_file(filename, &reports);
+ bfd= BLO_read_from_file(filename, &reports, BLO_READ_SKIP_USERDEF);
if (!bfd) {
printf("Loading %s failed: ", filename);
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
index 927b26faf8a..a6b2340d7b4 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
@@ -29,7 +29,7 @@
* \ingroup blroutines
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "MEM_guardedalloc.h"
diff --git a/source/gameengine/Expressions/intern/HashedPtr.cpp b/source/gameengine/Expressions/intern/HashedPtr.cpp
index 005ac16b231..11d9482f993 100644
--- a/source/gameengine/Expressions/intern/HashedPtr.cpp
+++ b/source/gameengine/Expressions/intern/HashedPtr.cpp
@@ -40,10 +40,8 @@ CHashedPtr::CHashedPtr(void* val) : m_valptr(val)
unsigned int CHashedPtr::hash() const
{
-#if defined(_WIN64) && !defined(FREE_WINDOWS64)
+#if defined(_WIN64)
unsigned __int64 key = (unsigned __int64)m_valptr;
-#elif defined(FREE_WINDOWS64)
- unsigned long long key = (unsigned long long)m_valptr;
#else
unsigned long key = (unsigned long)m_valptr;
#endif
diff --git a/source/gameengine/Expressions/intern/InputParser.cpp b/source/gameengine/Expressions/intern/InputParser.cpp
index e8cc7fba284..583d8da63cb 100644
--- a/source/gameengine/Expressions/intern/InputParser.cpp
+++ b/source/gameengine/Expressions/intern/InputParser.cpp
@@ -37,7 +37,7 @@
// cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc...
#include "EXP_IfExpr.h"
-#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
+#if defined(WIN32) || defined(WIN64)
#define strcasecmp _stricmp
#ifndef strtoll
diff --git a/source/gameengine/Expressions/intern/PyObjectPlus.cpp b/source/gameengine/Expressions/intern/PyObjectPlus.cpp
index de45bee76a7..1e4a59aeb5c 100644
--- a/source/gameengine/Expressions/intern/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/intern/PyObjectPlus.cpp
@@ -335,7 +335,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
Py_DECREF(resultlist);
return NULL;
}
- // walkthrough
+ ATTR_FALLTHROUGH;
case KX_PYATTRIBUTE_TYPE_INT:
{
int *val = reinterpret_cast<int*>(ptr);
@@ -406,7 +406,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
{
return NULL;
}
- // walkthrough
+ ATTR_FALLTHROUGH;
case KX_PYATTRIBUTE_TYPE_INT:
{
int *val = reinterpret_cast<int*>(ptr);
@@ -638,7 +638,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
PyErr_Format(PyExc_AttributeError, "Size check error for attribute, \"%s\", report to blender.org", attrdef->m_name);
goto UNDO_AND_ERROR;
}
- // walkthrough
+ ATTR_FALLTHROUGH;
case KX_PYATTRIBUTE_TYPE_INT:
{
int *var = reinterpret_cast<int*>(ptr);
@@ -883,7 +883,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
PyErr_Format(PyExc_AttributeError, "attribute size check error for attribute \"%s\", report to blender.org", attrdef->m_name);
goto FREE_AND_ERROR;
}
- // walkthrough
+ ATTR_FALLTHROUGH;
case KX_PYATTRIBUTE_TYPE_INT:
{
int *var = reinterpret_cast<int*>(ptr);
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index abb64cf1733..e34a5296139 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -133,7 +133,7 @@ bool SCA_PropertySensor::CheckPropertyCondition()
{
case KX_PROPSENSOR_NOTEQUAL:
reverse = true;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case KX_PROPSENSOR_EQUAL:
{
CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
@@ -231,7 +231,7 @@ bool SCA_PropertySensor::CheckPropertyCondition()
}
case KX_PROPSENSOR_LESSTHAN:
reverse = true;
- /* fall-through */
+ ATTR_FALLTHROUGH;
case KX_PROPSENSOR_GREATERTHAN:
{
CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname);
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h
index 9a108203ee8..688ed8ac0f4 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.h
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h
@@ -40,7 +40,7 @@
# include <windows.h>
#endif /* WIN32 */
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <map>
diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h
index 504df2376bb..24922197723 100644
--- a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h
+++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h
@@ -67,8 +67,6 @@ public:
* Call this routine to update the mouse device when a button state changes.
* \param button Which button state changes.
* \param isDown The new state of the button.
- * \param x Position x-coordinate of the cursor at the time of the state change.
- * \param y Position y-coordinate of the cursor at the time of the state change.
* \return Indication as to whether the event was processed.
*/
virtual bool ConvertButtonEvent(TButtonId button, bool isDown);
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 408006a0dae..50c34bbadaf 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -36,7 +36,7 @@
# include <windows.h>
#endif
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "GPU_extensions.h"
#include "GPU_init_exit.h"
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index dd93a6ff424..0c206dfce3d 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -355,7 +355,7 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL
BLI_strncpy(bfd->main->name, progname, sizeof(bfd->main->name));
}
} else {
- bfd= BLO_read_from_file(progname, &reports);
+ bfd= BLO_read_from_file(progname, &reports, BLO_READ_SKIP_NONE);
}
if (!bfd && filename) {
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index 95679b5d3a6..9cbd61590b6 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -169,7 +169,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
rasty->GetViewMatrix().getValue(&viewmat[0][0]);
float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL);
+ GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL, NULL);
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
}
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 72815cadc70..d344e18c313 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <iostream>
#include "BL_Shader.h"
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp
index cc7fea5ad25..c3b799b9424 100644
--- a/source/gameengine/Ketsji/BL_Texture.cpp
+++ b/source/gameengine/Ketsji/BL_Texture.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <iostream>
#include <map>
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 476fbd29b8b..d26e35f8138 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "KX_BlenderMaterial.h"
#include "BL_Material.h"
diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h
index 420565e62f6..5a0c4588ae2 100644
--- a/source/gameengine/Ketsji/KX_Dome.h
+++ b/source/gameengine/Ketsji/KX_Dome.h
@@ -38,7 +38,7 @@
#include "RAS_IRasterizer.h"
#include "KX_KetsjiEngine.h"
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <vector>
#include "MEM_guardedalloc.h"
diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
index f3947fdd710..be1a4b4ef3a 100644
--- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp
+++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
@@ -31,10 +31,8 @@
*/
-#if defined(_WIN64) && !defined(FREE_WINDOWS64)
+#if defined(_WIN64)
typedef unsigned __int64 uint_ptr;
-#elif defined(FREE_WINDOWS64)
-typedef unsigned long long uint_ptr;
#else
typedef unsigned long uint_ptr;
#endif
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index b0a8e376eb6..d82a0fd533b 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -80,12 +80,6 @@
#define DEFAULT_LOGIC_TIC_RATE 60.0
//#define DEFAULT_PHYSICS_TIC_RATE 60.0
-#ifdef FREE_WINDOWS /* XXX mingw64 (gcc 4.7.0) defines a macro for DrawText that translates to DrawTextA. Not good */
-#ifdef DrawText
-#undef DrawText
-#endif
-#endif
-
const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
"Physics:", // tc_physics
"Logic:", // tc_logic
diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp
index 239bfde4c98..c84b2474c90 100644
--- a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp
+++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp
@@ -345,6 +345,7 @@ static MT_Point3 nearestPointToObstacle(MT_Point3& pos ,KX_Obstacle* obstacle)
MT_Point3 res = obstacle->m_pos + abdir*proj;
return res;
}
+ ATTR_FALLTHROUGH;
}
case KX_OBSTACLE_CIRCLE :
default:
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index cdc2f9f3644..97a7e161e9f 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -30,7 +30,7 @@
* \ingroup ketsji
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#ifdef _MSC_VER
# pragma warning (disable:4786)
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index a27f37c0441..d858097abef 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -108,7 +108,7 @@ void KX_SoundActuator::play()
case KX_SOUNDACT_LOOPBIDIRECTIONAL:
case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
sound = AUD_Sound_pingpong(sound);
- // fall through
+ ATTR_FALLTHROUGH;
case KX_SOUNDACT_LOOPEND:
case KX_SOUNDACT_LOOPSTOP:
loop = true;
@@ -124,7 +124,7 @@ void KX_SoundActuator::play()
AUD_Device_free(device);
// in case of pingpong, we have to free the sound
- if(sound != m_sound)
+ if (sound != m_sound)
AUD_Sound_free(sound);
if (m_handle != NULL) {
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index e52dc1ba052..8b00f1b47fa 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -37,6 +37,7 @@ set(INC
../../SceneGraph
../../../blender/blenkernel
../../../blender/blenlib
+ ../../../blender/gpu
../../../blender/makesdna
../../../../intern/container
../../../../intern/guardedalloc
diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt
index c65fcac5161..fc7dc90e03b 100644
--- a/source/gameengine/Rasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
../../blender/makesdna
../../blender/blenlib
../../blender/blenkernel
+ ../../blender/gpu
../../blender/imbuf
../../../intern/container
../../../intern/glew-mx
diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index 82b26749fd1..f379e2eb486 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -24,7 +24,7 @@
* \ingroup bgerast
*/
-#define STRINGIFY(A) #A
+#include "BLI_utildefines.h"
#include "RAS_OpenGLFilters/RAS_Blur2DFilter.h"
#include "RAS_OpenGLFilters/RAS_Sharpen2DFilter.h"
@@ -43,7 +43,7 @@
#include "RAS_2DFilterManager.h"
#include <iostream>
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <stdio.h>
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
index b2d580161ca..71c8cfe745f 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
@@ -30,7 +30,7 @@
#include <windows.h>
#endif // WIN32
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "RAS_MaterialBucket.h"
#include "RAS_TexVert.h"
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
index fff988a07c5..69e859f06d9 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <stdio.h>
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
index e589bffcaf1..58b3c61bd05 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <stdio.h>
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 3f82c513f7d..5eed9b3b8f8 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -35,7 +35,7 @@
#include "RAS_OpenGLRasterizer.h"
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "RAS_ICanvas.h"
#include "RAS_Rect.h"
@@ -994,8 +994,8 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat,
}
bool negX = (scale[0] < 0.0f);
- bool negY = (scale[0] < 0.0f);
- bool negZ = (scale[0] < 0.0f);
+ bool negY = (scale[1] < 0.0f);
+ bool negZ = (scale[2] < 0.0f);
if (negX || negY || negZ) {
m_viewmatrix.tscale((negX)?-1.0f:1.0f, (negY)?-1.0f:1.0f, (negZ)?-1.0f:1.0f, 1.0);
}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp
index d54b3232067..26b956cd74e 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include <stdio.h>
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
index 316871e6025..f980116f5f8 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
@@ -27,7 +27,7 @@
#include "RAS_StorageVA.h"
-#include "glew-mx.h"
+#include "GPU_glew.h"
RAS_StorageVA::RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer) :
m_drawingmode(RAS_IRasterizer::KX_TEXTURED),
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
index 114defb60a5..4ba5882a46e 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
@@ -28,7 +28,7 @@
#include "RAS_StorageVBO.h"
#include "RAS_MeshObject.h"
-#include "glew-mx.h"
+#include "GPU_glew.h"
VBO::VBO(RAS_DisplayArray *data, unsigned int indices)
{
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
index 4c8e4a8931c..c82b6a3206d 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
@@ -29,7 +29,7 @@
#define __KX_VERTEXBUFFEROBJECTSTORAGE
#include <map>
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "RAS_IStorage.h"
#include "RAS_IRasterizer.h"
diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp
index 0db1fa293da..b91a312a5d7 100644
--- a/source/gameengine/VideoTexture/ImageBase.cpp
+++ b/source/gameengine/VideoTexture/ImageBase.cpp
@@ -43,7 +43,7 @@ extern "C" {
#include "Exception.h"
-#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
+#if (defined(WIN32) || defined(WIN64))
#define strcasecmp _stricmp
#endif
diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h
index 4c9fc5a58fb..5a09c9a67b3 100644
--- a/source/gameengine/VideoTexture/ImageBase.h
+++ b/source/gameengine/VideoTexture/ImageBase.h
@@ -40,7 +40,7 @@
#include "FilterBase.h"
-#include "glew-mx.h"
+#include "GPU_glew.h"
// forward declarations
struct PyImage;
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
index 7e8c534d7d5..57062343b67 100644
--- a/source/gameengine/VideoTexture/ImageRender.cpp
+++ b/source/gameengine/VideoTexture/ImageRender.cpp
@@ -36,7 +36,7 @@
#include <math.h>
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "KX_PythonInit.h"
#include "DNA_scene_types.h"
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp
index 8852c190053..ad3d8875e28 100644
--- a/source/gameengine/VideoTexture/ImageViewport.cpp
+++ b/source/gameengine/VideoTexture/ImageViewport.cpp
@@ -33,7 +33,7 @@
#include "EXP_PyObjectPlus.h"
#include <structmember.h>
-#include "glew-mx.h"
+#include "GPU_glew.h"
#include "KX_PythonInit.h"
#include "RAS_ICanvas.h"
diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp
index bb995747360..48dc4c705bf 100644
--- a/source/gameengine/VideoTexture/Texture.cpp
+++ b/source/gameengine/VideoTexture/Texture.cpp
@@ -55,7 +55,7 @@
#include "Exception.h"
#include <memory.h>
-#include "glew-mx.h"
+#include "GPU_glew.h"
extern "C" {
#include "IMB_imbuf.h"
diff --git a/source/gameengine/VideoTexture/VideoDeckLink.h b/source/gameengine/VideoTexture/VideoDeckLink.h
index 50099d2ead4..d5419176691 100644
--- a/source/gameengine/VideoTexture/VideoDeckLink.h
+++ b/source/gameengine/VideoTexture/VideoDeckLink.h
@@ -47,7 +47,7 @@ extern "C" {
#include "BLI_threads.h"
#include "BLI_blenlib.h"
}
-#include "GL/glew.h"
+#include "GPU_glew.h"
#ifdef WIN32
#include "dvpapi.h"
#endif