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:
authorLukas Tönne <lukas.toenne@gmail.com>2015-05-04 18:00:40 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2015-05-04 18:14:25 +0300
commitbf7e8b42fa269c310e456fa55263ff2d9849804e (patch)
tree571b8177bc7d854c865126e8c11b680577b0d98c /source
parent20e960215a80a41fd7e9782d009531d8d9f827cd (diff)
parent1227e5c3d1ee20e9af57984a261b1d51d48c0263 (diff)
Merge branch 'master' into strand_editmode
Conflicts: source/blender/bmesh/bmesh_class.h source/blender/bmesh/intern/bmesh_mesh_conv.h
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c8
-rw-r--r--source/blender/blenkernel/BKE_blender.h4
-rw-r--r--source/blender/blenkernel/BKE_curve.h1
-rw-r--r--source/blender/blenkernel/BKE_global.h3
-rw-r--r--source/blender/blenkernel/BKE_image.h8
-rw-r--r--source/blender/blenkernel/BKE_library.h5
-rw-r--r--source/blender/blenkernel/BKE_material.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh_mapping.h2
-rw-r--r--source/blender/blenkernel/BKE_object.h17
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h2
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h5
-rw-r--r--source/blender/blenkernel/BKE_scene.h4
-rw-r--r--source/blender/blenkernel/BKE_screen.h4
-rw-r--r--source/blender/blenkernel/BKE_tracking.h15
-rw-r--r--source/blender/blenkernel/intern/blender.c2
-rw-r--r--source/blender/blenkernel/intern/curve.c57
-rw-r--r--source/blender/blenkernel/intern/image.c96
-rw-r--r--source/blender/blenkernel/intern/library.c17
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c3
-rw-r--r--source/blender/blenkernel/intern/material.c36
-rw-r--r--source/blender/blenkernel/intern/mesh.c49
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c41
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c93
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c5
-rw-r--r--source/blender/blenkernel/intern/multires.c4
-rw-r--r--source/blender/blenkernel/intern/object.c86
-rw-r--r--source/blender/blenkernel/intern/ocean.c4
-rw-r--r--source/blender/blenkernel/intern/packedFile.c10
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c2
-rw-r--r--source/blender/blenkernel/intern/particle_system.c26
-rw-r--r--source/blender/blenkernel/intern/pbvh.c4
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c73
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h7
-rw-r--r--source/blender/blenkernel/intern/scene.c85
-rw-r--r--source/blender/blenkernel/intern/screen.c30
-rw-r--r--source/blender/blenkernel/intern/sequencer.c15
-rw-r--r--source/blender/blenkernel/intern/sound.c19
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c8
-rw-r--r--source/blender/blenkernel/intern/text.c3
-rw-r--r--source/blender/blenkernel/intern/tracking.c89
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c16
-rw-r--r--source/blender/blenkernel/intern/unit.c7
-rw-r--r--source/blender/blenlib/BLI_array_utils.h8
-rw-r--r--source/blender/blenlib/BLI_compiler_typecheck.h299
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h10
-rw-r--r--source/blender/blenlib/BLI_math_base.h4
-rw-r--r--source/blender/blenlib/BLI_math_bits.h51
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h1
-rw-r--r--source/blender/blenlib/BLI_math_vector.h1
-rw-r--r--source/blender/blenlib/BLI_string.h2
-rw-r--r--source/blender/blenlib/BLI_utildefines.h16
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/array_utils.c41
-rw-r--r--source/blender/blenlib/intern/convexhull2d.c2
-rw-r--r--source/blender/blenlib/intern/math_base.c15
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c19
-rw-r--r--source/blender/blenlib/intern/math_bits_inline.c59
-rw-r--r--source/blender/blenlib/intern/math_matrix.c59
-rw-r--r--source/blender/blenlib/intern/math_rotation.c6
-rw-r--r--source/blender/blenlib/intern/math_vector.c10
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c2
-rw-r--r--source/blender/blenlib/intern/string.c43
-rw-r--r--source/blender/blenlib/intern/timecode.c28
-rw-r--r--source/blender/blenloader/intern/readfile.c23
-rw-r--r--source/blender/blenloader/intern/versioning_270.c32
-rw-r--r--source/blender/blenloader/intern/writefile.c77
-rw-r--r--source/blender/bmesh/bmesh_class.h30
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c257
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h32
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c714
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h64
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c22
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.h22
-rw-r--r--source/blender/bmesh/intern/bmesh_inline.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c40
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c26
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h19
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c25
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h22
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c50
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h9
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_validate.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c44
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h58
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c1
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h108
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api_inline.h49
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c124
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h18
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c20
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c125
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h41
-rw-r--r--source/blender/bmesh/intern/bmesh_queries_inline.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c56
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_structure_inline.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c9
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.h9
-rw-r--r--source/blender/bmesh/operators/bmo_connect_concave.c4
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c2
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c2
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c7
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c106
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c16
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c18
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c73
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.h9
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate.h16
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c69
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_dissolve.c16
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c5
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c113
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c10
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.c5
-rw-r--r--source/blender/collada/SceneExporter.cpp2
-rw-r--r--source/blender/collada/collada_utils.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp73
-rw-r--r--source/blender/compositor/operations/COM_BlurBaseOperation.cpp3
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.cpp33
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c152
-rw-r--r--source/blender/editors/animation/anim_markers.c2
-rw-r--r--source/blender/editors/animation/anim_ops.c2
-rw-r--r--source/blender/editors/animation/keyframing.c43
-rw-r--r--source/blender/editors/armature/pose_group.c12
-rw-r--r--source/blender/editors/curve/editcurve_add.c20
-rw-r--r--source/blender/editors/curve/editfont.c2
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c103
-rw-r--r--source/blender/editors/hair/hair_edit.c2
-rw-r--r--source/blender/editors/include/ED_buttons.h2
-rw-r--r--source/blender/editors/include/ED_mesh.h24
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_object.h6
-rw-r--r--source/blender/editors/include/ED_outliner.h36
-rw-r--r--source/blender/editors/include/ED_paint.h2
-rw-r--r--source/blender/editors/include/ED_screen.h3
-rw-r--r--source/blender/editors/include/ED_util.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h19
-rw-r--r--source/blender/editors/include/UI_interface.h9
-rw-r--r--source/blender/editors/include/UI_resources.h5
-rw-r--r--source/blender/editors/interface/interface.c55
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c22
-rw-r--r--source/blender/editors/interface/interface_handlers.c92
-rw-r--r--source/blender/editors/interface/interface_intern.h10
-rw-r--r--source/blender/editors/interface/interface_panel.c219
-rw-r--r--source/blender/editors/interface/interface_templates.c50
-rw-r--r--source/blender/editors/interface/interface_utils.c31
-rw-r--r--source/blender/editors/interface/interface_widgets.c17
-rw-r--r--source/blender/editors/interface/resources.c16
-rw-r--r--source/blender/editors/interface/view2d_ops.c12
-rw-r--r--source/blender/editors/mask/mask_draw.c4
-rw-r--r--source/blender/editors/mesh/editface.c2
-rw-r--r--source/blender/editors/mesh/editmesh_add.c5
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c3
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c68
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c6
-rw-r--r--source/blender/editors/mesh/editmesh_path.c2
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c112
-rw-r--r--source/blender/editors/mesh/editmesh_select.c665
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c8
-rw-r--r--source/blender/editors/mesh/mesh_data.c63
-rw-r--r--source/blender/editors/mesh/mesh_intern.h5
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c3
-rw-r--r--source/blender/editors/mesh/mesh_ops.c7
-rw-r--r--source/blender/editors/mesh/meshtools.c8
-rw-r--r--source/blender/editors/object/object_add.c40
-rw-r--r--source/blender/editors/object/object_bake_api.c6
-rw-r--r--source/blender/editors/object/object_constraint.c2
-rw-r--r--source/blender/editors/object/object_data_transfer.c4
-rw-r--r--source/blender/editors/object/object_edit.c71
-rw-r--r--source/blender/editors/object/object_hook.c5
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c6
-rw-r--r--source/blender/editors/object/object_transform.c6
-rw-r--r--source/blender/editors/object/object_vgroup.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c8
-rw-r--r--source/blender/editors/physics/rigidbody_object.c1
-rw-r--r--source/blender/editors/render/render_intern.h1
-rw-r--r--source/blender/editors/render/render_internal.c10
-rw-r--r--source/blender/editors/render/render_opengl.c21
-rw-r--r--source/blender/editors/render/render_ops.c1
-rw-r--r--source/blender/editors/render/render_preview.c12
-rw-r--r--source/blender/editors/render/render_shading.c73
-rw-r--r--source/blender/editors/screen/area.c230
-rw-r--r--source/blender/editors/screen/glutil.c39
-rw-r--r--source/blender/editors/screen/screen_ops.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c40
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c671
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h4
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c3
-rw-r--r--source/blender/editors/sound/sound_ops.c4
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c31
-rw-r--r--source/blender/editors/space_clip/clip_draw.c4
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_utils.c46
-rw-r--r--source/blender/editors/space_clip/space_clip.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c20
-rw-r--r--source/blender/editors/space_clip/tracking_select.c2
-rw-r--r--source/blender/editors/space_file/file_draw.c20
-rw-r--r--source/blender/editors/space_file/filelist.c2
-rw-r--r--source/blender/editors/space_file/filesel.c6
-rw-r--r--source/blender/editors/space_file/fsmenu.c2
-rw-r--r--source/blender/editors/space_image/image_buttons.c37
-rw-r--r--source/blender/editors/space_image/image_draw.c32
-rw-r--r--source/blender/editors/space_image/image_ops.c18
-rw-r--r--source/blender/editors/space_image/space_image.c2
-rw-r--r--source/blender/editors/space_info/info_ops.c4
-rw-r--r--source/blender/editors/space_info/info_stats.c33
-rw-r--r--source/blender/editors/space_nla/nla_draw.c6
-rw-r--r--source/blender/editors/space_node/node_draw.c6
-rw-r--r--source/blender/editors/space_node/node_edit.c28
-rw-r--r--source/blender/editors/space_node/node_group.c4
-rw-r--r--source/blender/editors/space_node/node_view.c2
-rw-r--r--source/blender/editors/space_node/space_node.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c36
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h4
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c5
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c116
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c207
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c31
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h6
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c5
-rw-r--r--source/blender/editors/space_text/text_ops.c2
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c4
-rw-r--r--source/blender/editors/space_view3d/drawobject.c36
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c123
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c239
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c2
-rw-r--r--source/blender/editors/transform/transform.c3
-rw-r--r--source/blender/editors/transform/transform.h5
-rw-r--r--source/blender/editors/transform/transform_conversions.c213
-rw-r--r--source/blender/editors/transform/transform_manipulator.c13
-rw-r--r--source/blender/editors/transform/transform_ops.c3
-rw-r--r--source/blender/editors/transform/transform_snap.c22
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
-rw-r--r--source/blender/editors/util/ed_util.c26
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c7
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c2
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp6
-rw-r--r--source/blender/freestyle/intern/application/Controller.h1
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h29
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp29
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp12
-rw-r--r--source/blender/freestyle/intern/system/PythonInterpreter.h22
-rw-r--r--source/blender/gpu/GPU_debug.h2
-rw-r--r--source/blender/gpu/GPU_draw.h10
-rw-r--r--source/blender/gpu/GPU_extensions.h3
-rw-r--r--source/blender/gpu/GPU_material.h2
-rw-r--r--source/blender/gpu/intern/gpu_debug.c1
-rw-r--r--source/blender/gpu/intern/gpu_draw.c48
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c112
-rw-r--r--source/blender/gpu/intern/gpu_material.c4
-rw-r--r--source/blender/imbuf/IMB_imbuf.h15
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h2
-rw-r--r--source/blender/imbuf/intern/IMB_metadata.h10
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c6
-rw-r--r--source/blender/imbuf/intern/colormanagement.c20
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp3
-rw-r--r--source/blender/imbuf/intern/divers.c82
-rw-r--r--source/blender/imbuf/intern/imageprocess.c4
-rw-r--r--source/blender/imbuf/intern/metadata.c7
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp30
-rw-r--r--source/blender/imbuf/intern/rectop.c18
-rw-r--r--source/blender/imbuf/intern/thumbs.c5
-rw-r--r--source/blender/makesdna/DNA_curve_types.h1
-rw-r--r--source/blender/makesdna/DNA_scene_types.h4
-rw-r--r--source/blender/makesdna/DNA_screen_types.h4
-rw-r--r--source/blender/makesdna/DNA_space_types.h4
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/DNA_view2d_types.h2
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h5
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h10
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c3
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c37
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c72
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c7
-rw-r--r--source/blender/makesrna/intern/rna_object.c15
-rw-r--r--source/blender/makesrna/intern/rna_scene.c48
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_space.c44
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c26
-rw-r--r--source/blender/makesrna/intern/rna_wm.c41
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c4
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c4
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c9
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c2
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c2
-rw-r--r--source/blender/nodes/composite/node_composite_util.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c2
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c23
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c9
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h9
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c6
-rw-r--r--source/blender/python/bmesh/bmesh_py_utils.c12
-rw-r--r--source/blender/python/intern/bpy_app.c1
-rw-r--r--source/blender/python/intern/bpy_props.c7
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c2
-rw-r--r--source/blender/render/extern/include/RE_bake.h2
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h16
-rw-r--r--source/blender/render/intern/include/render_result.h1
-rw-r--r--source/blender/render/intern/source/bake_api.c2
-rw-r--r--source/blender/render/intern/source/convertblender.c3
-rw-r--r--source/blender/render/intern/source/multires_bake.c10
-rw-r--r--source/blender/render/intern/source/pipeline.c60
-rw-r--r--source/blender/render/intern/source/render_result.c113
-rw-r--r--source/blender/render/intern/source/shadeinput.c9
-rw-r--r--source/blender/render/intern/source/texture_ocean.c2
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/WM_types.h27
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c68
-rw-r--r--source/blender/windowmanager/intern/wm_files.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c8
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c39
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c58
-rw-r--r--source/blender/windowmanager/wm_event_system.h1
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c2
-rw-r--r--source/creator/creator.c2
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp629
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h11
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_Light.h2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp83
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h4
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp14
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp11
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp15
362 files changed, 7610 insertions, 3671 deletions
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index c65a0825a49..215d2484c18 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -199,7 +199,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
GlyphBLF *g;
FT_Error err;
FT_Bitmap bitmap, tempbitmap;
- int sharp = (U.text_render & USER_TEXT_DISABLE_AA);
+ const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0;
int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
FT_BBox bbox;
unsigned int key;
@@ -224,7 +224,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
if (font->flags & BLF_HINTING)
flags &= ~FT_LOAD_NO_HINTING;
- if (sharp)
+ if (is_sharp)
err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO);
else
err = FT_Load_Glyph(font->face, (FT_UInt)index, flags);
@@ -237,7 +237,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
/* get the glyph. */
slot = font->face->glyph;
- if (sharp) {
+ if (is_sharp) {
err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
/* Convert result from 1 bit per pixel to 8 bit per pixel */
@@ -266,7 +266,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
g->height = (int)bitmap.rows;
if (g->width && g->height) {
- if (sharp) {
+ if (is_sharp) {
/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
int i;
for (i = 0; i < (g->width * g->height); i++) {
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 0789335de6a..80332c08fc2 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 274
-#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 5
@@ -87,7 +87,7 @@ void BKE_userdef_free(void);
void BKE_userdef_state(void);
/* set this callback when a UI is running */
-void set_blender_test_break_cb(void (*func)(void));
+void BKE_blender_callback_test_break_set(void (*func)(void));
int blender_test_break(void);
#define BKE_UNDO_STR_MAX 64
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index ec3c0447269..9de13ce9240 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -90,6 +90,7 @@ void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys);
void BKE_curve_material_index_remove(struct Curve *cu, int index);
void BKE_curve_material_index_clear(struct Curve *cu);
int BKE_curve_material_index_validate(struct Curve *cu);
+void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len);
ListBase *BKE_curve_nurbs_get(struct Curve *cu);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 935a922b3ec..22ddae88b28 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -126,10 +126,11 @@ enum {
G_DEBUG_FREESTYLE = (1 << 7), /* freestyle messages */
G_DEBUG_DEPSGRAPH = (1 << 8), /* depsgraph messages */
G_DEBUG_SIMDATA = (1 << 9), /* sim debug data display */
+ G_DEBUG_GPU_MEM = (1 << 10), /* gpu memory in status bar */
};
#define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
- G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH)
+ G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM)
/* G.fileflags */
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index ad191968a40..155f26d9bd9 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -46,6 +46,7 @@ struct ImageFormatData;
struct ImagePool;
struct Main;
struct ReportList;
+struct RenderResult;
#define IMA_MAX_SPACE 64
@@ -58,10 +59,11 @@ void BKE_image_free_buffers(struct Image *image);
/* call from library */
void BKE_image_free(struct Image *image);
-void BKE_imbuf_stamp_info(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf);
+void BKE_render_result_stamp_info(struct Scene *scene, struct Object *camera, struct RenderResult *rr);
+void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf);
void BKE_image_stamp_buf(struct Scene *scene, struct Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels);
bool BKE_imbuf_alpha_test(struct ImBuf *ibuf);
-int BKE_imbuf_write_stamp(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
+int BKE_imbuf_write_stamp(struct Scene *scene, struct RenderResult *rr, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
void BKE_imbuf_write_prepare(struct ImBuf *ibuf, struct ImageFormatData *imf);
int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const bool is_copy);
@@ -175,7 +177,7 @@ struct Image *BKE_image_load_exists(const char *filepath);
struct Image *BKE_image_add_generated(
struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d);
/* adds image from imbuf, owns imbuf */
-struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf);
+struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf, const char *name);
/* for reload, refresh, pack */
void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index e88a4e88209..6ecc955e26c 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -107,8 +107,9 @@ void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagg
struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowManager *));
-void set_free_notifier_reference_cb(void (*func)(const void *));
+void BKE_library_callback_free_window_manager_set(void (*func)(struct bContext *, struct wmWindowManager *));
+void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *));
+void BKE_library_callback_free_editor_id_reference_set(void (*func)(const struct ID *));
/* use when "" is given to new_id() */
#define ID_FALLBACK_NAME N_("Untitled")
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 56393727d28..0cfa1aeecb5 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -50,6 +50,7 @@ void BKE_material_free_ex(struct Material *ma, bool do_id_user);
void test_object_materials(struct Main *bmain, struct ID *id);
void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
void init_material(struct Material *ma);
+void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Material *ma);
struct Material *localize_material(struct Material *ma);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index c0d8902eb71..ebf4384d5a7 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -108,6 +108,7 @@ void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblis
void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
void BKE_mesh_material_index_remove(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
+void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index da44c989146..dcf5d2ed78d 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -102,7 +102,7 @@ typedef struct MeshElemMap {
/* mapping */
UvVertMap *BKE_mesh_uv_vert_map_create(
struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
- unsigned int totpoly, unsigned int totvert, int selected, float *limit);
+ unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding);
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 0ddc9b0b256..0e0c779c033 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -33,6 +33,8 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
struct Base;
struct EvaluationContext;
struct Scene;
@@ -82,9 +84,18 @@ bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
-struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name);
-struct Object *BKE_object_add(struct Main *bmain, struct Scene *scene, int type);
-void *BKE_object_obdata_add_from_type(struct Main *bmain, int type);
+struct Object *BKE_object_add_only_object(
+ struct Main *bmain,
+ int type, const char *name)
+ ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
+struct Object *BKE_object_add(
+ struct Main *bmain, struct Scene *scene,
+ int type, const char *name)
+ ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+void *BKE_object_obdata_add_from_type(
+ struct Main *bmain,
+ int type, const char *name)
+ ATTR_NONNULL(1);
void BKE_object_lod_add(struct Object *ob);
void BKE_object_lod_sort(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index 8fab44121de..a2397922061 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -48,7 +48,7 @@ struct PackedFile *dupPackedFile(const struct PackedFile *pf_src);
struct PackedFile *newPackedFile(struct ReportList *reports, const char *filename, const char *relabase);
struct PackedFile *newPackedFileMemory(void *mem, int memlen);
-void packAll(struct Main *bmain, struct ReportList *reports);
+void packAll(struct Main *bmain, struct ReportList *reports, bool verbose);
void packLibraries(struct Main *bmain, struct ReportList *reports);
/* unpack */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 03ad1765f8d..1df633cc966 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -104,8 +104,9 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
/* for orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision. */
-void BKE_pbvh_raycast_project_ray_root(PBVH *bvh, bool original, float ray_start[3],
- float ray_end[3], float ray_normal[3]);
+void BKE_pbvh_raycast_project_ray_root(
+ PBVH *bvh, bool original,
+ float ray_start[3], float ray_end[3], float ray_normal[3]);
/* Drawing */
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 79778d504a5..75a5e919bad 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -127,8 +127,8 @@ struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char
bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
/* render profile */
-int get_render_subsurf_level(const struct RenderData *r, int level);
-int get_render_child_particle_number(const struct RenderData *r, int num);
+int get_render_subsurf_level(const struct RenderData *r, int level, bool for_render);
+int get_render_child_particle_number(const struct RenderData *r, int num, bool for_render);
int get_render_shadow_samples(const struct RenderData *r, int samples);
float get_render_aosss_error(const struct RenderData *r, float error);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 43499933d16..c584051708b 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -273,6 +273,9 @@ void BKE_spacedata_freelist(ListBase *lb);
void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
void BKE_spacedata_draw_locks(int set);
+void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *));
+void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+
/* area/regions */
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
@@ -280,6 +283,7 @@ void BKE_screen_area_free(struct ScrArea *sa);
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
+struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y);
struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
struct ScrArea *BKE_screen_find_area_xy(struct bScreen *sc, const int spacetype, int x, int y);
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index ef997446c6c..ea56c084fb5 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -136,6 +136,21 @@ struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct Movie
void BKE_tracking_plane_tracks_deselect_all(struct ListBase *plane_tracks_base);
+bool BKE_tracking_plane_track_has_point_track(struct MovieTrackingPlaneTrack *plane_track,
+ struct MovieTrackingTrack *track);
+bool BKE_tracking_plane_track_remove_point_track(struct MovieTrackingPlaneTrack *plane_track,
+ struct MovieTrackingTrack *track);
+
+void BKE_tracking_plane_tracks_remove_point_track(struct MovieTracking *tracking,
+ struct MovieTrackingTrack *track);
+
+void BKE_tracking_plane_track_replace_point_track(struct MovieTrackingPlaneTrack *plane_track,
+ struct MovieTrackingTrack *old_track,
+ struct MovieTrackingTrack *new_track);
+void BKE_tracking_plane_tracks_replace_point_track(struct MovieTracking *tracking,
+ struct MovieTrackingTrack *old_track,
+ struct MovieTrackingTrack *new_track);
+
/* **** Plane Marker **** */
struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track,
struct MovieTrackingPlaneMarker *plane_marker);
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 2085fefdb93..37bd9c5db5c 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -623,7 +623,7 @@ int BKE_write_file_userdef(const char *filepath, ReportList *reports)
static void (*blender_test_break_cb)(void) = NULL;
-void set_blender_test_break_cb(void (*func)(void))
+void BKE_blender_callback_test_break_set(void (*func)(void))
{
blender_test_break_cb = func;
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 5fcdc9c2e78..30ceaea89b8 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -4422,9 +4422,6 @@ void BKE_curve_material_index_remove(Curve *cu, int index)
for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->mat_nr && nu->mat_nr >= index) {
nu->mat_nr--;
- if (curvetype == OB_CURVE) {
- nu->charidx--;
- }
}
}
}
@@ -4446,9 +4443,6 @@ void BKE_curve_material_index_clear(Curve *cu)
for (nu = cu->nurb.first; nu; nu = nu->next) {
nu->mat_nr = 0;
- if (curvetype == OB_CURVE) {
- nu->charidx = 0;
- }
}
}
}
@@ -4475,9 +4469,6 @@ int BKE_curve_material_index_validate(Curve *cu)
for (nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->mat_nr > max_idx) {
nu->mat_nr = 0;
- if (curvetype == OB_CURVE) {
- nu->charidx = 0;
- }
is_valid = false;
}
}
@@ -4492,6 +4483,54 @@ int BKE_curve_material_index_validate(Curve *cu)
}
}
+void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len)
+{
+ const int curvetype = BKE_curve_type_get(cu);
+ const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+ if (n < remap_len_short) { \
+ BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+ n = remap[n]; \
+ } ((void)0)
+
+ if (curvetype == OB_FONT) {
+ struct CharInfo *strinfo;
+ int charinfo_len, i;
+
+ if (cu->editfont) {
+ EditFont *ef = cu->editfont;
+ strinfo = ef->textbufinfo;
+ charinfo_len = ef->len;
+ }
+ else {
+ strinfo = cu->strinfo;
+ charinfo_len = cu->len_wchar;
+ }
+
+ for (i = 0; i <= charinfo_len; i++) {
+ if (strinfo[i].mat_nr > 0) {
+ strinfo[i].mat_nr -= 1;
+ MAT_NR_REMAP(strinfo[i].mat_nr);
+ strinfo[i].mat_nr += 1;
+ }
+ }
+ }
+ else {
+ Nurb *nu;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+ if (nurbs) {
+ for (nu = nurbs->first; nu; nu = nu->next) {
+ MAT_NR_REMAP(nu->mat_nr);
+ }
+ }
+ }
+
+#undef MAT_NR_REMAP
+
+}
+
void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect)
{
r_rect->xmin = cu->xof + tb->x;
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index a09c42e9178..5169559d80b 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -883,12 +883,16 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei
/* Create an image image from ibuf. The refcount of ibuf is increased,
* caller should take care to drop its reference by calling
* IMB_freeImBuf if needed. */
-Image *BKE_image_add_from_imbuf(ImBuf *ibuf)
+Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name)
{
/* on save, type is changed to FILE in editsima.c */
Image *ima;
- ima = image_alloc(G.main, BLI_path_basename(ibuf->name), IMA_SRC_FILE, IMA_TYPE_IMAGE);
+ if (name == NULL) {
+ name = BLI_path_basename(ibuf->name);
+ }
+
+ ima = image_alloc(G.main, name, IMA_SRC_FILE, IMA_TYPE_IMAGE);
if (ima) {
BLI_strncpy(ima->name, ibuf->name, FILE_MAX);
@@ -2028,26 +2032,45 @@ void BKE_image_stamp_buf(
#undef BUFF_MARGIN_Y
}
-void BKE_imbuf_stamp_info(Scene *scene, Object *camera, struct ImBuf *ibuf)
+void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderResult *rr)
{
- struct StampData stamp_data;
+ struct StampData *stamp_data;
- if (!ibuf) return;
+ if (!(scene && scene->r.stamp & R_STAMP_ALL))
+ return;
- /* fill all the data values, no prefix */
- stampdata(scene, camera, &stamp_data, 0);
+ if (!rr->stamp_data) {
+ stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data");
+ }
+ else {
+ stamp_data = rr->stamp_data;
+ }
- if (stamp_data.file[0]) IMB_metadata_change_field(ibuf, "File", stamp_data.file);
- if (stamp_data.note[0]) IMB_metadata_change_field(ibuf, "Note", stamp_data.note);
- if (stamp_data.date[0]) IMB_metadata_change_field(ibuf, "Date", stamp_data.date);
- if (stamp_data.marker[0]) IMB_metadata_change_field(ibuf, "Marker", stamp_data.marker);
- if (stamp_data.time[0]) IMB_metadata_change_field(ibuf, "Time", stamp_data.time);
- if (stamp_data.frame[0]) IMB_metadata_change_field(ibuf, "Frame", stamp_data.frame);
- if (stamp_data.camera[0]) IMB_metadata_change_field(ibuf, "Camera", stamp_data.camera);
- if (stamp_data.cameralens[0]) IMB_metadata_change_field(ibuf, "Lens", stamp_data.cameralens);
- if (stamp_data.scene[0]) IMB_metadata_change_field(ibuf, "Scene", stamp_data.scene);
- if (stamp_data.strip[0]) IMB_metadata_change_field(ibuf, "Strip", stamp_data.strip);
- if (stamp_data.rendertime[0]) IMB_metadata_change_field(ibuf, "RenderTime", stamp_data.rendertime);
+ stampdata(scene, camera, stamp_data, 0);
+
+ if (!rr->stamp_data) {
+ rr->stamp_data = stamp_data;
+ }
+}
+
+
+void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf)
+{
+ struct StampData *stamp_data = rr->stamp_data;
+
+ if (!ibuf || !stamp_data) return;
+
+ if (stamp_data->file[0]) IMB_metadata_change_field(ibuf, "File", stamp_data->file);
+ if (stamp_data->note[0]) IMB_metadata_change_field(ibuf, "Note", stamp_data->note);
+ if (stamp_data->date[0]) IMB_metadata_change_field(ibuf, "Date", stamp_data->date);
+ if (stamp_data->marker[0]) IMB_metadata_change_field(ibuf, "Marker", stamp_data->marker);
+ if (stamp_data->time[0]) IMB_metadata_change_field(ibuf, "Time", stamp_data->time);
+ if (stamp_data->frame[0]) IMB_metadata_change_field(ibuf, "Frame", stamp_data->frame);
+ if (stamp_data->camera[0]) IMB_metadata_change_field(ibuf, "Camera", stamp_data->camera);
+ if (stamp_data->cameralens[0]) IMB_metadata_change_field(ibuf, "Lens", stamp_data->cameralens);
+ if (stamp_data->scene[0]) IMB_metadata_change_field(ibuf, "Scene", stamp_data->scene);
+ if (stamp_data->strip[0]) IMB_metadata_change_field(ibuf, "Strip", stamp_data->strip);
+ if (stamp_data->rendertime[0]) IMB_metadata_change_field(ibuf, "RenderTime", stamp_data->rendertime);
}
bool BKE_imbuf_alpha_test(ImBuf *ibuf)
@@ -2242,15 +2265,14 @@ int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf,
return ok;
}
-int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, const char *name, struct ImageFormatData *imf)
+int BKE_imbuf_write_stamp(Scene *scene, struct RenderResult *rr, ImBuf *ibuf, const char *name, struct ImageFormatData *imf)
{
if (scene && scene->r.stamp & R_STAMP_ALL)
- BKE_imbuf_stamp_info(scene, camera, ibuf);
+ BKE_imbuf_stamp_info(rr, ibuf);
return BKE_imbuf_write(ibuf, name, imf);
}
-
static void do_makepicstring(
char *string, const char *base, const char *relbase, int frame, const char imtype,
const ImageFormatData *im_format, const short use_ext, const short use_frames,
@@ -3504,6 +3526,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
{
Render *re;
RenderResult rres;
+ RenderView *rv;
float *rectf, *rectz;
unsigned int *rect;
float dither;
@@ -3535,7 +3558,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
}
else if (ima->renders[ima->render_slot]) {
rres = *(ima->renders[ima->render_slot]);
- rres.have_combined = RE_RenderViewGetRectf(&rres, actview) != NULL;
+ rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL;
}
else
memset(&rres, 0, sizeof(RenderResult));
@@ -3550,12 +3573,26 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
if (from_render) {
BLI_lock_thread(LOCK_VIEWER);
*lock_r = re;
+ rv = NULL;
+ }
+ else {
+ rv = BLI_findlink(&rres.views, actview);
+ if (rv == NULL)
+ rv = rres.views.first;
}
/* this gives active layer, composite or sequence result */
- rect = (unsigned int *)rres.rect32;
- rectf = rres.rectf;
- rectz = rres.rectz;
+ if (rv == NULL) {
+ rect = (unsigned int *)rres.rect32;
+ rectf = rres.rectf;
+ rectz = rres.rectz;
+ }
+ else {
+ rect = (unsigned int *)rv->rect32;
+ rectf = rv->rectf;
+ rectz = rv->rectz;
+ }
+
dither = iuser->scene->r.dither_intensity;
/* combined layer gets added as first layer */
@@ -3586,6 +3623,15 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
if (rpass) {
channels = rpass->channels;
rectf = rpass->rect;
+
+ if (!rectf) {
+ /* Happens when Save Buffers is enabled.
+ * Use display buffer stored in the render layer.
+ */
+ rect = (unsigned int *) rl->display_buffer;
+ byte_buffer_in_display_space = true;
+ }
+
dither = 0.0f; /* don't dither passes */
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 2cee08a821b..42856e82062 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -865,18 +865,24 @@ static void BKE_library_free(Library *lib)
static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL;
-void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) )
+void BKE_library_callback_free_window_manager_set(void (*func)(bContext *C, wmWindowManager *) )
{
free_windowmanager_cb = func;
}
static void (*free_notifier_reference_cb)(const void *) = NULL;
-void set_free_notifier_reference_cb(void (*func)(const void *) )
+void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *) )
{
free_notifier_reference_cb = func;
}
+static void (*free_editor_id_reference_cb)(const ID *) = NULL;
+
+void BKE_library_callback_free_editor_id_reference_set(void (*func)(const ID *))
+{
+ free_editor_id_reference_cb = func;
+}
static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
{
@@ -1034,8 +1040,13 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
/* avoid notifying on removed data */
BKE_main_lock(bmain);
- if (free_notifier_reference_cb)
+ if (free_notifier_reference_cb) {
free_notifier_reference_cb(id);
+ }
+
+ if (free_editor_id_reference_cb) {
+ free_editor_id_reference_cb(id);
+ }
BLI_remlink(lb, id);
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 387d093051e..13ec970c65c 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -1360,6 +1360,9 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x
case PROP_SHARP:
value_layer = value_layer * value_layer;
break;
+ case PROP_INVSQUARE:
+ value_layer = value_layer * (2.0f - value_layer);
+ break;
case PROP_LIN:
default:
/* nothing */
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index b5b7f3d06aa..eaaf1319167 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -53,6 +53,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_array_utils.h"
#include "BKE_animsys.h"
#include "BKE_displist.h"
@@ -66,6 +67,8 @@
#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_curve.h"
+#include "BKE_editmesh.h"
+#include "BKE_font.h"
#include "GPU_material.h"
@@ -806,9 +809,13 @@ void assign_material_id(ID *id, Material *ma, short act)
if (act > MAXMAT) return;
if (act < 1) act = 1;
+ /* this is needed for Python overrides,
+ * we just have to take care that the UI can't do this */
+#if 0
/* prevent crashing when using accidentally */
BLI_assert(id->lib == NULL);
if (id->lib) return;
+#endif
/* test arraylens */
@@ -918,6 +925,35 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
test_object_materials(G.main, ob->data);
}
+
+void BKE_material_remap_object(Object *ob, const unsigned int *remap)
+{
+ Material ***matar = give_matarar(ob);
+ const short *totcol_p = give_totcolp(ob);
+
+ BLI_array_permute(ob->mat, ob->totcol, remap);
+
+ if (ob->matbits) {
+ BLI_array_permute(ob->matbits, ob->totcol, remap);
+ }
+
+ if (matar) {
+ BLI_array_permute(*matar, *totcol_p, remap);
+ }
+
+ if (ob->type == OB_MESH) {
+ BKE_mesh_material_remap(ob->data, remap, ob->totcol);
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ BKE_curve_material_remap(ob->data, remap, ob->totcol);
+ }
+ else {
+ /* add support for this object data! */
+ BLI_assert(matar == NULL);
+ }
+}
+
+
/* XXX - this calls many more update calls per object then are needed, could be optimized */
void assign_matarar(struct Object *ob, struct Material ***matar, short totcol)
{
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index eec2b108ca3..e66a4d48fc8 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -1265,7 +1265,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
dl = dispbase->first;
while (dl) {
- int smooth = dl->rt & CU_SMOOTH ? 1 : 0;
+ const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
if (dl->type == DL_SEGM) {
startvert = vertcount;
@@ -1344,7 +1344,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
}
- if (smooth) mpoly->flag |= ME_SMOOTH;
+ if (is_smooth) mpoly->flag |= ME_SMOOTH;
mpoly++;
mloop += 3;
index += 3;
@@ -1423,7 +1423,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
}
- if (smooth) mpoly->flag |= ME_SMOOTH;
+ if (is_smooth) mpoly->flag |= ME_SMOOTH;
mpoly++;
mloop += 4;
@@ -1773,6 +1773,36 @@ void BKE_mesh_material_index_clear(Mesh *me)
}
}
+void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int remap_len)
+{
+ const short remap_len_short = (short)remap_len;
+
+#define MAT_NR_REMAP(n) \
+ if (n < remap_len_short) { \
+ BLI_assert(n >= 0 && remap[n] < remap_len_short); \
+ n = remap[n]; \
+ } ((void)0)
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ BMIter iter;
+ BMFace *efa;
+
+ BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ MAT_NR_REMAP(efa->mat_nr);
+ }
+ }
+ else {
+ int i;
+ for (i = 0; i < me->totpoly; i++) {
+ MAT_NR_REMAP(me->mpoly[i].mat_nr);
+ }
+ }
+
+#undef MAT_NR_REMAP
+
+}
+
void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
{
Mesh *me = meshOb->data;
@@ -1890,6 +1920,7 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
{
int i;
MVert *mvert = me->mvert;
+ float (*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL);
for (i = 0; i < me->totvert; i++, mvert++)
mul_m4_v3(mat, mvert->co);
@@ -1904,7 +1935,17 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys)
}
}
- /* don't update normals, caller can do this explicitly */
+ /* don't update normals, caller can do this explicitly.
+ * We do update loop normals though, those may not be auto-generated (see e.g. STL import script)! */
+ if (lnors) {
+ float m3[3][3];
+
+ copy_m3_m4(m3, mat);
+ normalize_m3(m3);
+ for (i = 0; i < me->totloop; i++, lnors++) {
+ mul_m3_v3(m3, *lnors);
+ }
+ }
}
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index ebdbd3aac8a..e4a85eb399b 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -55,7 +55,7 @@
* but for now this replaces it because its unused. */
UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
- unsigned int totpoly, unsigned int totvert, int selected, float *limit)
+ unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding)
{
UvVertMap *vmap;
UvMapVert *buf;
@@ -109,7 +109,10 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop,
buf++;
}
- winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0;
+ if (use_winding)
+ winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0;
+ else
+ winding[a] = 0;
}
}
@@ -177,8 +180,6 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
}
/**
-
-
* Generates a map where the key is the vertex and the value is a list
* of polys or loops that use that vertex as a corner. The lists are allocated
* from one memory pool.
@@ -251,9 +252,10 @@ void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem,
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
}
-/* Generates a map where the key is the vertex and the value is a list
- * of edges that use that vertex as an endpoint. The lists are allocated
- * from one memory pool. */
+/**
+ * Generates a map where the key is the vertex and the value is a list of edges that use that vertex as an endpoint.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
const MEdge *medge, int totvert, int totedge)
{
@@ -293,6 +295,10 @@ void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem,
*r_mem = indices;
}
+/**
+ * Generates a map where the key is the edge and the value is a list of polygons that use that edge.
+ * The lists are allocated from one memory pool.
+ */
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem,
const MEdge *UNUSED(medge), const int totedge,
const MPoly *mpoly, const int totpoly,
@@ -400,7 +406,8 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem,
* Used currently for UVs and 'smooth groups'.
* \{ */
-/** Callback deciding whether the given poly/loop/edge define an island boundary or not.
+/**
+ * Callback deciding whether the given poly/loop/edge define an island boundary or not.
*/
typedef bool (*MeshRemap_CheckIslandBoundary)(
const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge,
@@ -583,8 +590,7 @@ static void poly_edge_loop_islands_calc(
}
static bool poly_is_island_boundary_smooth_cb(
- const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me,
- const int nbr_egde_users)
+ const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users)
{
/* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */
return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2));
@@ -681,7 +687,6 @@ void BKE_mesh_loop_islands_add(
const size_t curr_num_islands = (size_t)island_store->islands_num;
int i = item_num;
- island_store->items_to_islands_num = item_num;
while (i--) {
island_store->items_to_islands[items_indices[i]] = curr_island_idx;
}
@@ -716,17 +721,21 @@ void BKE_mesh_loop_islands_add(
* not sure we want that at all!
*/
static bool mesh_check_island_boundary_uv(
- const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me,
- const int UNUSED(nbr_egde_users))
+ const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, const int UNUSED(nbr_egde_users))
{
/* Edge is UV boundary if tagged as seam. */
return (me->flag & ME_SEAM) != 0;
}
/**
- * \note all this could be optimized...
- * Not sure it would be worth the more complex code, though, those loops
- * are supposed to be really quick to do...
+ * Calculate UV islands.
+ *
+ * \note Currently we only consider edges tagges as seams as UV boundaries. This has the advantages of simplicity,
+ * and being valid/common to all UV maps. However, it means actual UV islands whithout matching UV seams
+ * will not be handled correctly...
+ *
+ * \note All this could be optimized...
+ * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do...
*/
bool BKE_mesh_calc_islands_loop_poly_uv(
MVert *UNUSED(verts), const int UNUSED(totvert),
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index aca72614094..f3e2f395002 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -977,6 +977,8 @@ void BKE_mesh_remap_calc_loops_from_dm(
float (*poly_nors_dst)[3] = NULL;
float (*loop_nors_dst)[3] = NULL;
+ float (*poly_cents_src)[3] = NULL;
+
MeshElemMap *vert_to_loop_map_src = NULL;
int *vert_to_loop_map_src_buff = NULL;
MeshElemMap *vert_to_poly_map_src = NULL;
@@ -1012,6 +1014,8 @@ void BKE_mesh_remap_calc_loops_from_dm(
int *indices_interp = NULL;
float *weights_interp = NULL;
+ MLoop *ml_src, *ml_dst;
+ MPoly *mp_src, *mp_dst;
int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src;
IslandResult **islands_res;
@@ -1089,11 +1093,13 @@ void BKE_mesh_remap_calc_loops_from_dm(
edges_src, num_edges_src, polys_src, num_polys_src, loops_src, num_loops_src);
if (use_from_vert) {
loop_to_poly_map_src = MEM_mallocN(sizeof(*loop_to_poly_map_src) * (size_t)num_loops_src, __func__);
- for (pidx_src = 0; pidx_src < num_polys_src; pidx_src++) {
- MPoly *mp = &polys_src[pidx_src];
- for (plidx_src = 0, lidx_src = mp->loopstart; plidx_src < mp->totloop; plidx_src++, lidx_src++) {
+ poly_cents_src = MEM_mallocN(sizeof(*poly_cents_src) * (size_t)num_polys_src, __func__);
+ for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) {
+ ml_src = &loops_src[mp_src->loopstart];
+ for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop; plidx_src++, lidx_src++) {
loop_to_poly_map_src[lidx_src] = pidx_src;
}
+ BKE_mesh_calc_poly_center(mp_src, ml_src, verts_src, poly_cents_src[pidx_src]);
}
}
@@ -1155,10 +1161,13 @@ void BKE_mesh_remap_calc_loops_from_dm(
int num_verts_active = 0;
BLI_BITMAP_SET_ALL(verts_active, false, (size_t)num_verts_src);
for (i = 0; i < isld->count; i++) {
- MPoly *mp_src = &polys_src[isld->indices[i]];
+ mp_src = &polys_src[isld->indices[i]];
for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; lidx_src++) {
- BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v);
- num_verts_active++;
+ const unsigned int vidx_src = loops_src[lidx_src].v;
+ if (!BLI_BITMAP_TEST(verts_active, vidx_src)) {
+ BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v);
+ num_verts_active++;
+ }
}
}
/* verts 'ownership' is transfered to treedata here, which will handle its freeing. */
@@ -1199,13 +1208,13 @@ void BKE_mesh_remap_calc_loops_from_dm(
int num_faces_active = 0;
BLI_BITMAP_SET_ALL(faces_active, false, (size_t)num_faces_src);
for (i = 0; i < num_faces_src; i++) {
- MPoly *mp_src = &polys_src[tessface_to_poly_map_src[i]];
+ mp_src = &polys_src[tessface_to_poly_map_src[i]];
if (island_store.items_to_islands[mp_src->loopstart] == tindex) {
BLI_BITMAP_ENABLE(faces_active, i);
num_faces_active++;
}
}
- /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */
+ /* verts and faces 'ownership' is transfered to treedata here, which will handle its freeing. */
bvhtree_from_mesh_faces_ex(
&treedata[tindex], verts_src, verts_allocated_src,
faces_src, num_faces_src, faces_allocated_src,
@@ -1233,10 +1242,14 @@ void BKE_mesh_remap_calc_loops_from_dm(
islands_res[tindex] = MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__);
}
- for (pidx_dst = 0; pidx_dst < numpolys_dst; pidx_dst++) {
- MPoly *mp_dst = &polys_dst[pidx_dst];
+ for (pidx_dst = 0, mp_dst = polys_dst; pidx_dst < numpolys_dst; pidx_dst++, mp_dst++) {
float (*pnor_dst)[3] = &poly_nors_dst[pidx_dst];
+ /* Only in use_from_vert case, we may need polys' centers as fallback in case we cannot decide which
+ * corner to use from normals only. */
+ float pcent_dst[3];
+ bool pcent_dst_valid = false;
+
if ((size_t)mp_dst->totloop > islands_res_buff_size) {
islands_res_buff_size = (size_t)mp_dst->totloop;
for (tindex = 0; tindex < num_trees; tindex++) {
@@ -1246,8 +1259,8 @@ void BKE_mesh_remap_calc_loops_from_dm(
for (tindex = 0; tindex < num_trees; tindex++) {
BVHTreeFromMesh *tdata = &treedata[tindex];
- MLoop *ml_dst = &loops_dst[mp_dst->loopstart];
+ ml_dst = &loops_dst[mp_dst->loopstart];
for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) {
if (use_from_vert) {
float tmp_co[3];
@@ -1263,6 +1276,7 @@ void BKE_mesh_remap_calc_loops_from_dm(
float (*nor_dst)[3];
float (*nors_src)[3];
float best_nor_dot = -2.0f;
+ float best_sqdist_fallback = FLT_MAX;
int best_index_src = -1;
if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) {
@@ -1279,16 +1293,50 @@ void BKE_mesh_remap_calc_loops_from_dm(
for (i = vert_to_refelem_map_src[nearest.index].count; i--;) {
const int index_src = vert_to_refelem_map_src[nearest.index].indices[i];
const float dot = dot_v3v3(nors_src[index_src], *nor_dst);
- if (dot > best_nor_dot) {
- best_nor_dot = dot;
- best_index_src = index_src;
+
+ pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ?
+ loop_to_poly_map_src[index_src] : index_src;
+ /* WARNING! This is not the *real* lidx_src in case of POLYNOR, we only use it
+ * to check we stay on current island (all loops from a given poly are
+ * on same island!). */
+ lidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ?
+ index_src : polys_src[pidx_src].loopstart;
+
+ /* A same vert may be at the boundary of several islands! Hence, we have to ensure
+ * poly/loop we are currently considering *belongs* to current island! */
+ if (island_store.items_to_islands[lidx_src] != tindex) {
+ continue;
+ }
+
+ if (dot > best_nor_dot - 1e-6f) {
+ /* We need something as fallback decision in case dest normal matches several
+ * source normals (see T44522), using distance between polys' centers here. */
+ float *pcent_src;
+ float sqdist;
+
+ mp_src = &polys_src[pidx_src];
+ ml_src = &loops_src[mp_src->loopstart];
+
+ if (!pcent_dst_valid) {
+ BKE_mesh_calc_poly_center(
+ mp_dst, &loops_dst[mp_dst->loopstart], verts_dst, pcent_dst);
+ pcent_dst_valid = true;
+ }
+ pcent_src = poly_cents_src[pidx_src];
+ sqdist = len_squared_v3v3(pcent_dst, pcent_src);
+
+ if ((dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) {
+ best_nor_dot = dot;
+ best_sqdist_fallback = sqdist;
+ best_index_src = index_src;
+ }
}
}
if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
/* Our best_index_src is a poly one for now!
* Have to find its loop matching our closest vertex. */
- MPoly *mp_src = &polys_src[best_index_src];
- MLoop *ml_src = &loops_src[mp_src->loopstart];
+ mp_src = &polys_src[best_index_src];
+ ml_src = &loops_src[mp_src->loopstart];
for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++, ml_src++) {
if ((int)ml_src->v == nearest.index) {
best_index_src = plidx_src + mp_src->loopstart;
@@ -1296,7 +1344,8 @@ void BKE_mesh_remap_calc_loops_from_dm(
}
}
}
- islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / (hit_dist * best_nor_dot)) : 1e18f;
+ best_nor_dot = (best_nor_dot + 1.0f) * 0.5f;
+ islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist * best_nor_dot) : 1e18f;
islands_res[tindex][plidx_dst].hit_dist = hit_dist;
islands_res[tindex][plidx_dst].index_src = best_index_src;
}
@@ -1488,12 +1537,11 @@ void BKE_mesh_remap_calc_loops_from_dm(
if (last_valid_pidx_isld_src != -1) {
/* Find a new valid loop in that new poly (nearest one for now).
* Note we could be much more subtle here, again that's for later... */
- MPoly *mp_src;
- MLoop *ml_src, *ml_dst = &loops_dst[lidx_dst];
int j;
float best_dist_sq = FLT_MAX;
float tmp_co[3];
+ ml_dst = &loops_dst[lidx_dst];
copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
/* We do our transform here, since we may do several raycast/nearest queries. */
@@ -1532,10 +1580,10 @@ void BKE_mesh_remap_calc_loops_from_dm(
/* Else, we use source poly, indices stored in islands_res are those of polygons. */
pidx_src = isld_res->index_src;
if (pidx_src >= 0) {
- MPoly *mp_src = &polys_src[pidx_src];
float *hit_co = isld_res->hit_point;
int best_loop_index_src;
+ mp_src = &polys_src[pidx_src];
/* If prev and curr poly are the same, no need to do anything more!!! */
if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) {
int pidx_isld_src, pidx_isld_src_prev;
@@ -1575,11 +1623,11 @@ void BKE_mesh_remap_calc_loops_from_dm(
if (last_valid_pidx_isld_src != -1) {
/* Find a new valid loop in that new poly (nearest point on poly for now).
* Note we could be much more subtle here, again that's for later... */
- MLoop *ml_dst = &loops_dst[lidx_dst];
float best_dist_sq = FLT_MAX;
float tmp_co[3];
int j;
+ ml_dst = &loops_dst[lidx_dst];
copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
/* We do our transform here, since we may do several raycast/nearest queries. */
@@ -1710,6 +1758,9 @@ void BKE_mesh_remap_calc_loops_from_dm(
if (loop_to_poly_map_src) {
MEM_freeN(loop_to_poly_map_src);
}
+ if (poly_cents_src) {
+ MEM_freeN(poly_cents_src);
+ }
if (vcos_interp) {
MEM_freeN(vcos_interp);
}
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 645567eea67..18f3db6bd15 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -37,8 +37,9 @@
#include "BKE_editmesh.h"
/* Static function for alloc */
-static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
- BMesh *bm, BMVert **vtable, BMEdge **etable)
+static BMFace *bm_face_create_from_mpoly(
+ MPoly *mp, MLoop *ml,
+ BMesh *bm, BMVert **vtable, BMEdge **etable)
{
BMVert **verts = BLI_array_alloca(verts, mp->totloop);
BMEdge **edges = BLI_array_alloca(edges, mp->totloop);
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 4ac96405fbf..e4bf05c2b5b 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -340,13 +340,13 @@ static int multires_get_level(Object *ob, MultiresModifierData *mmd,
bool render, bool ignore_simplify)
{
if (render)
- return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl) : mmd->renderlvl;
+ return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl, true) : mmd->renderlvl;
else if (ob->mode == OB_MODE_SCULPT)
return mmd->sculptlvl;
else if (ignore_simplify)
return mmd->lvl;
else
- return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl) : mmd->lvl;
+ return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl, false) : mmd->lvl;
}
void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl)
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 304275d2b1a..99c5e22d51a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -808,34 +808,11 @@ void BKE_object_unlink(Object *ob)
}
}
}
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOops *so = (SpaceOops *)sl;
-
- if (so->treestore) {
- TreeStoreElem *tselem;
- BLI_mempool_iter iter;
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- if (tselem->id == (ID *)ob) tselem->id = NULL;
- }
- }
- }
- else if (sl->spacetype == SPACE_BUTS) {
- SpaceButs *sbuts = (SpaceButs *)sl;
-
- if (sbuts->pinid == (ID *)ob) {
- sbuts->flag &= ~SB_PIN_CONTEXT;
- sbuts->pinid = NULL;
- }
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
-
- if (snode->from == (ID *)ob) {
- snode->flag &= ~SNODE_PIN;
- snode->from = NULL;
- }
+#if 0
+ else if (ELEM(sl->spacetype, SPACE_OUTLINER, SPACE_BUTS, SPACE_NODE)) {
+ /* now handled by WM_main_remove_editor_id_reference */
}
+#endif
}
sa = sa->next;
@@ -938,26 +915,6 @@ bool BKE_object_exists_check(Object *obtest)
/* *************************************************** */
-void *BKE_object_obdata_add_from_type(Main *bmain, int type)
-{
- switch (type) {
- case OB_MESH: return BKE_mesh_add(bmain, "Mesh");
- case OB_CURVE: return BKE_curve_add(bmain, "Curve", OB_CURVE);
- case OB_SURF: return BKE_curve_add(bmain, "Surf", OB_SURF);
- case OB_FONT: return BKE_curve_add(bmain, "Text", OB_FONT);
- case OB_MBALL: return BKE_mball_add(bmain, "Meta");
- case OB_CAMERA: return BKE_camera_add(bmain, "Camera");
- case OB_LAMP: return BKE_lamp_add(bmain, "Lamp");
- case OB_LATTICE: return BKE_lattice_add(bmain, "Lattice");
- case OB_ARMATURE: return BKE_armature_add(bmain, "Armature");
- case OB_SPEAKER: return BKE_speaker_add(bmain, "Speaker");
- case OB_EMPTY: return NULL;
- default:
- printf("BKE_object_obdata_add_from_type: Internal error, bad type: %d\n", type);
- return NULL;
- }
-}
-
static const char *get_obdata_defname(int type)
{
switch (type) {
@@ -978,6 +935,30 @@ static const char *get_obdata_defname(int type)
}
}
+void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
+{
+ if (name == NULL) {
+ name = get_obdata_defname(type);
+ }
+
+ switch (type) {
+ case OB_MESH: return BKE_mesh_add(bmain, name);
+ case OB_CURVE: return BKE_curve_add(bmain, name, OB_CURVE);
+ case OB_SURF: return BKE_curve_add(bmain, name, OB_SURF);
+ case OB_FONT: return BKE_curve_add(bmain, name, OB_FONT);
+ case OB_MBALL: return BKE_mball_add(bmain, name);
+ case OB_CAMERA: return BKE_camera_add(bmain, name);
+ case OB_LAMP: return BKE_lamp_add(bmain, name);
+ case OB_LATTICE: return BKE_lattice_add(bmain, name);
+ case OB_ARMATURE: return BKE_armature_add(bmain, name);
+ case OB_SPEAKER: return BKE_speaker_add(bmain, name);
+ case OB_EMPTY: return NULL;
+ default:
+ printf("%s: Internal error, bad type: %d\n", __func__, type);
+ return NULL;
+ }
+}
+
/* more general add: creates minimum required data, but without vertices etc. */
Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
{
@@ -1063,16 +1044,16 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
/* general add: to scene, with layer from area and default name */
/* creates minimum required data, but without vertices etc. */
-Object *BKE_object_add(Main *bmain, Scene *scene, int type)
+Object *BKE_object_add(
+ Main *bmain, Scene *scene,
+ int type, const char *name)
{
Object *ob;
Base *base;
- char name[MAX_ID_NAME];
- BLI_strncpy(name, get_obdata_defname(type), sizeof(name));
ob = BKE_object_add_only_object(bmain, type, name);
- ob->data = BKE_object_obdata_add_from_type(bmain, type);
+ ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
ob->lay = scene->lay;
@@ -1770,8 +1751,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
mul_m4_m4m4(ob->obmat, gob->obmat, target->obmat);
if (gob->dup_group) { /* should always be true */
float tvec[3];
- copy_v3_v3(tvec, gob->dup_group->dupli_ofs);
- mul_mat3_m4_v3(ob->obmat, tvec);
+ mul_v3_mat3_m4v3(tvec, ob->obmat, gob->dup_group->dupli_ofs);
sub_v3_v3(ob->obmat[3], tvec);
}
BKE_object_apply_mat4(ob, ob->obmat, false, true);
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index b89b5ab4bbc..1a178fb2bdf 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -738,8 +738,8 @@ static void set_height_normalize_factor(struct Ocean *oc)
for (i = 0; i < oc->_M; ++i) {
for (j = 0; j < oc->_N; ++j) {
- if (max_h < fabsf(oc->_disp_y[i * oc->_N + j])) {
- max_h = fabsf(oc->_disp_y[i * oc->_N + j]);
+ if (max_h < fabs(oc->_disp_y[i * oc->_N + j])) {
+ max_h = fabs(oc->_disp_y[i * oc->_N + j]);
}
}
}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 61e39d0ad47..68212521617 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -224,7 +224,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
}
/* no libraries for now */
-void packAll(Main *bmain, ReportList *reports)
+void packAll(Main *bmain, ReportList *reports, bool verbose)
{
Image *ima;
VFont *vfont;
@@ -237,7 +237,7 @@ void packAll(Main *bmain, ReportList *reports)
BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
tot ++;
}
- else if (BKE_image_is_animated(ima)) {
+ else if (BKE_image_is_animated(ima) && verbose) {
BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported",
ima->id.name + 2);
}
@@ -258,10 +258,10 @@ void packAll(Main *bmain, ReportList *reports)
}
}
- if (tot == 0)
- BKE_report(reports, RPT_INFO, "No new files have been packed");
- else
+ if (tot > 0)
BKE_reportf(reports, RPT_INFO, "Packed %d files", tot);
+ else if (verbose)
+ BKE_report(reports, RPT_INFO, "No new files have been packed");
}
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 1429d3b1cdc..4a2540e385b 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -668,6 +668,8 @@ static void exec_distribute_parent(TaskPool *UNUSED(pool), void *taskdata, int U
ParticleSystem *psys= task->ctx->sim.psys;
ParticleData *pa;
int p;
+
+ BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin);
pa= psys->particles + task->begin;
switch (psys->part->from) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 5a263e24fc4..4bc46a476a5 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -297,7 +297,7 @@ int psys_get_child_number(Scene *scene, ParticleSystem *psys)
else
nbr= psys->part->child_nbr;
- return get_render_child_particle_number(&scene->r, nbr);
+ return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL);
}
int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
@@ -559,17 +559,24 @@ static void initialize_all_particles(ParticleSimulationData *sim)
ParticleSystem *psys = sim->psys;
PARTICLE_P;
+ LOOP_PARTICLES {
+ initialize_particle(sim, pa);
+ }
+}
+
+static void free_unexisting_particles(ParticleSimulationData *sim)
+{
+ ParticleSystem *psys = sim->psys;
+ PARTICLE_P;
+
psys->totunexist = 0;
LOOP_PARTICLES {
- if ((pa->flag & PARS_UNEXIST)==0)
- initialize_particle(sim, pa);
-
- if (pa->flag & PARS_UNEXIST)
+ if (pa->flag & PARS_UNEXIST) {
psys->totunexist++;
+ }
}
- /* Free unexisting particles. */
if (psys->totpart && psys->totunexist == psys->totpart) {
if (psys->particles->boid)
MEM_freeN(psys->particles->boid);
@@ -3790,6 +3797,7 @@ static void system_step(ParticleSimulationData *sim, float cfra)
initialize_all_particles(sim);
/* reset only just created particles (on startframe all particles are recreated) */
reset_all_particles(sim, 0.0, cfra, oldtotpart);
+ free_unexisting_particles(sim);
if (psys->fluid_springs) {
MEM_freeN(psys->fluid_springs);
@@ -4136,6 +4144,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
{
PARTICLE_P;
float disp = psys_get_current_display_percentage(psys);
+ bool free_unexisting = false;
/* Particles without dynamics haven't been reset yet because they don't use pointcache */
if (psys->recalc & PSYS_RECALC_RESET)
@@ -4145,6 +4154,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
free_keyed_keys(psys);
distribute_particles(&sim, part->from);
initialize_all_particles(&sim);
+ free_unexisting = true;
/* flag for possible explode modifiers after this system */
sim.psmd->flag |= eParticleSystemFlag_Pars;
@@ -4163,6 +4173,10 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
pa->flag &= ~PARS_NO_DISP;
}
+ /* free unexisting after reseting particles */
+ if (free_unexisting)
+ free_unexisting_particles(&sim);
+
if (part->phystype == PART_PHYS_KEYED) {
psys_count_keyed_targets(&sim);
set_keyed_keys(&sim);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index fdda72e4f7d..bcbf3b8e77b 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1612,7 +1612,9 @@ bool BKE_pbvh_node_raycast(
return hit;
}
-void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
+void BKE_pbvh_raycast_project_ray_root(
+ PBVH *bvh, bool original,
+ float ray_start[3], float ray_end[3], float ray_normal[3])
{
if (bvh->nodes) {
float rootmin_start, rootmin_end;
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 5977243a21c..02b8cdba05b 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -667,8 +667,9 @@ static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f);
}
-static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e,
- float priority)
+static void edge_queue_insert(
+ EdgeQueueContext *eq_ctx, BMEdge *e,
+ float priority)
{
BMVert **pair;
@@ -694,8 +695,9 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e,
}
}
-static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx,
- BMEdge *e)
+static void long_edge_queue_edge_add(
+ EdgeQueueContext *eq_ctx,
+ BMEdge *e)
{
#ifdef USE_EDGEQUEUE_TAG
if (EDGE_QUEUE_TEST(e) == false)
@@ -765,8 +767,9 @@ static void long_edge_queue_edge_add_recursive(
}
#endif /* USE_EDGEQUEUE_EVEN_SUBDIV */
-static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx,
- BMEdge *e)
+static void short_edge_queue_edge_add(
+ EdgeQueueContext *eq_ctx,
+ BMEdge *e)
{
#ifdef USE_EDGEQUEUE_TAG
if (EDGE_QUEUE_TEST(e) == false)
@@ -779,8 +782,9 @@ static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx,
}
}
-static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx,
- BMFace *f)
+static void long_edge_queue_face_add(
+ EdgeQueueContext *eq_ctx,
+ BMFace *f)
{
if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
BMLoop *l_iter;
@@ -795,7 +799,7 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx,
if (len_sq > eq_ctx->q->limit_len_squared) {
long_edge_queue_edge_add_recursive(
eq_ctx, l_iter->radial_next, l_iter,
- len_sq, eq_ctx->q->limit_len_squared);
+ len_sq, eq_ctx->q->limit_len);
}
#else
long_edge_queue_edge_add(eq_ctx, l_iter->e);
@@ -805,8 +809,9 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx,
}
}
-static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx,
- BMFace *f)
+static void short_edge_queue_face_add(
+ EdgeQueueContext *eq_ctx,
+ BMFace *f)
{
if (edge_queue_tri_in_sphere(eq_ctx->q, f)) {
BMLoop *l_iter;
@@ -829,9 +834,10 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx,
*
* The highest priority (lowest number) is given to the longest edge.
*/
-static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh, const float center[3],
- float radius)
+static void long_edge_queue_create(
+ EdgeQueueContext *eq_ctx,
+ PBVH *bvh, const float center[3],
+ float radius)
{
int n;
@@ -877,9 +883,10 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
*
* The highest priority (lowest number) is given to the shortest edge.
*/
-static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh, const float center[3],
- float radius)
+static void short_edge_queue_create(
+ EdgeQueueContext *eq_ctx,
+ PBVH *bvh, const float center[3],
+ float radius)
{
int n;
@@ -920,8 +927,9 @@ static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE);
}
-static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
- BMEdge *e, BLI_Buffer *edge_loops)
+static void pbvh_bmesh_split_edge(
+ EdgeQueueContext *eq_ctx, PBVH *bvh,
+ BMEdge *e, BLI_Buffer *edge_loops)
{
BMVert *v_new;
float co_mid[3], no_mid[3];
@@ -1037,16 +1045,12 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh,
BM_edge_kill(bvh->bm, e);
}
-static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh,
- BLI_Buffer *edge_loops)
+static bool pbvh_bmesh_subdivide_long_edges(
+ EdgeQueueContext *eq_ctx, PBVH *bvh,
+ BLI_Buffer *edge_loops)
{
bool any_subdivided = false;
-#ifdef USE_EDGEQUEUE_TAG_VERIFY
- pbvh_bmesh_edge_tag_verify(bvh);
-#endif
-
-
while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
BMVert *v1 = pair[0], *v2 = pair[1];
@@ -1295,9 +1299,10 @@ static bool pbvh_bmesh_collapse_short_edges(
/************************* Called from pbvh.c *************************/
-bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
- const float ray_normal[3], float *dist,
- bool use_original)
+bool pbvh_bmesh_node_raycast(
+ PBVHNode *node, const float ray_start[3],
+ const float ray_normal[3], float *dist,
+ bool use_original)
{
bool hit = false;
@@ -1433,8 +1438,9 @@ static void pbvh_bmesh_node_layers_reset(PBVH *bvh)
/* Build a PBVH from a BMesh */
-void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
- const int cd_vert_node_offset, const int cd_face_node_offset)
+void BKE_pbvh_build_bmesh(
+ PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
+ const int cd_vert_node_offset, const int cd_face_node_offset)
{
BMIter iter;
BMFace *f;
@@ -1474,8 +1480,9 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
}
/* Collapse short edges, subdivide long edges */
-bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
- const float center[3], float radius)
+bool BKE_pbvh_bmesh_update_topology(
+ PBVH *bvh, PBVHTopologyUpdateMode mode,
+ const float center[3], float radius)
{
/* 2 is enough for edge faces - manifold edge */
BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2);
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 6b3ef8eb5da..a2b08a1f6d3 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -175,9 +175,10 @@ void BB_expand_with_bb(BB *bb, BB *bb2);
void BBC_update_centroid(BBC *bbc);
int BB_widest_axis(const BB *bb);
void pbvh_grow_nodes(PBVH *bvh, int totnode);
-bool ray_face_intersection(const float ray_start[3], const float ray_normal[3],
- const float *t0, const float *t1, const float *t2,
- const float *t3, float *fdist);
+bool ray_face_intersection(
+ const float ray_start[3], const float ray_normal[3],
+ const float *t0, const float *t1, const float *t2,
+ const float *t3, float *fdist);
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
/* pbvh_bmesh.c */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 07e2a186444..575a42ed690 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -75,6 +75,7 @@
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "BKE_node.h"
@@ -82,6 +83,7 @@
#include "BKE_paint.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
#include "BKE_unit.h"
@@ -154,6 +156,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
{
Scene *scen;
SceneRenderLayer *srl, *new_srl;
+ FreestyleLineSet *lineset;
ToolSettings *ts;
Base *base, *obase;
@@ -237,6 +240,14 @@ Scene *BKE_scene_copy(Scene *sce, int type)
new_srl = scen->r.layers.first;
for (srl = sce->r.layers.first; srl; srl = srl->next) {
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) {
+ if (lineset->linestyle) {
+ id_us_plus((ID *)lineset->linestyle);
+ lineset->linestyle = BKE_linestyle_copy(G.main, lineset->linestyle);
+ }
+ }
+ }
new_srl = new_srl->next;
}
}
@@ -680,7 +691,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->gm.recastData.cellsize = 0.3f;
sce->gm.recastData.cellheight = 0.2f;
- sce->gm.recastData.agentmaxslope = M_PI / 2;
+ sce->gm.recastData.agentmaxslope = M_PI_4;
sce->gm.recastData.agentmaxclimb = 0.9f;
sce->gm.recastData.agentheight = 2.0f;
sce->gm.recastData.agentradius = 0.6f;
@@ -798,33 +809,6 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
return NULL;
}
-static void scene_unlink_space_node(SpaceNode *snode, Scene *sce)
-{
- if (snode->id == &sce->id) {
- /* nasty DNA logic for SpaceNode:
- * ideally should be handled by editor code, but would be bad level call
- */
- bNodeTreePath *path, *path_next;
- for (path = snode->treepath.first; path; path = path_next) {
- path_next = path->next;
- MEM_freeN(path);
- }
- BLI_listbase_clear(&snode->treepath);
-
- snode->id = NULL;
- snode->from = NULL;
- snode->nodetree = NULL;
- snode->edittree = NULL;
- }
-}
-
-static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce)
-{
- if (sbuts->pinid == &sce->id) {
- sbuts->pinid = NULL;
- }
-}
-
void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
{
Scene *sce1;
@@ -849,24 +833,11 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
/* all screens */
for (screen = bmain->screen.first; screen; screen = screen->id.next) {
- ScrArea *area;
-
- if (screen->scene == sce)
+ if (screen->scene == sce) {
screen->scene = newsce;
-
- for (area = screen->areabase.first; area; area = area->next) {
- SpaceLink *space_link;
- for (space_link = area->spacedata.first; space_link; space_link = space_link->next) {
- switch (space_link->spacetype) {
- case SPACE_NODE:
- scene_unlink_space_node((SpaceNode *)space_link, sce);
- break;
- case SPACE_BUTS:
- scene_unlink_space_buts((SpaceButs *)space_link, sce);
- break;
- }
- }
}
+
+ /* editors are handled by WM_main_remove_editor_id_reference */
}
BKE_libblock_free(bmain, sce);
@@ -1968,20 +1939,30 @@ bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv)
/* render simplification */
-int get_render_subsurf_level(const RenderData *r, int lvl)
+int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
{
- if (r->mode & R_SIMPLIFY)
- return min_ii(r->simplify_subsurf, lvl);
- else
+ if (r->mode & R_SIMPLIFY) {
+ if (for_render)
+ return min_ii(r->simplify_subsurf_render, lvl);
+ else
+ return min_ii(r->simplify_subsurf, lvl);
+ }
+ else {
return lvl;
+ }
}
-int get_render_child_particle_number(const RenderData *r, int num)
+int get_render_child_particle_number(const RenderData *r, int num, bool for_render)
{
- if (r->mode & R_SIMPLIFY)
- return (int)(r->simplify_particles * num);
- else
+ if (r->mode & R_SIMPLIFY) {
+ if (for_render)
+ return (int)(r->simplify_particles_render * num);
+ else
+ return (int)(r->simplify_particles * num);
+ }
+ else {
return num;
+ }
}
int get_render_shadow_samples(const RenderData *r, int samples)
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 3c43bfa2920..840e1f99f84 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -272,6 +272,19 @@ void BKE_spacedata_draw_locks(int set)
}
}
+static void (*spacedata_id_unref_cb)(struct SpaceLink *sl, const struct ID *id) = NULL;
+
+void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *))
+{
+ spacedata_id_unref_cb = func;
+}
+
+void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id)
+{
+ if (spacedata_id_unref_cb) {
+ spacedata_id_unref_cb(sl, id);
+ }
+}
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)
@@ -405,6 +418,23 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa)
return NULL;
}
+ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y)
+{
+ ARegion *ar_found = NULL;
+ if (sa) {
+ ARegion *ar;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) {
+ if (BLI_rcti_isect_pt(&ar->winrct, x, y)) {
+ ar_found = ar;
+ break;
+ }
+ }
+ }
+ }
+ return ar_found;
+}
+
/**
* \note, ideally we can get the area from the context,
* there are a few places however where this isn't practical.
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 535dcd6ba4d..bb48023de56 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -2423,6 +2423,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa
IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
sequencer_imbuf_assign_spaces(scene, i);
+ IMB_metadata_copy(i, ibuf);
IMB_freeImBuf(ibuf);
ibuf = i;
@@ -2474,6 +2475,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa
ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra);
if (ibuf_new != ibuf) {
+ IMB_metadata_copy(ibuf_new, ibuf);
IMB_freeImBuf(ibuf);
ibuf = ibuf_new;
}
@@ -2496,6 +2498,7 @@ static ImBuf *copy_from_ibuf_still(const SeqRenderData *context, Sequence *seq,
if (ibuf) {
rval = IMB_dupImBuf(ibuf);
+ IMB_metadata_copy(rval, ibuf);
IMB_freeImBuf(ibuf);
}
@@ -2509,9 +2512,11 @@ static void copy_to_ibuf_still(const SeqRenderData *context, Sequence *seq, floa
/* we have to store a copy, since the passed ibuf
* could be preprocessed afterwards (thereby silently
* changing the cached image... */
- ibuf = IMB_dupImBuf(ibuf);
+ ImBuf *oibuf = ibuf;
+ ibuf = IMB_dupImBuf(oibuf);
if (ibuf) {
+ IMB_metadata_copy(ibuf, oibuf);
sequencer_imbuf_assign_spaces(context->scene, ibuf);
}
@@ -2721,7 +2726,7 @@ static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq
BLI_path_abs(name, G.main->name);
}
- flag = IB_rect;
+ flag = IB_rect | IB_metadata;
if (seq->alpha_mode == SEQ_ALPHA_PREMUL)
flag |= IB_alphamode_premul;
@@ -3583,6 +3588,8 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq
out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2);
+ IMB_metadata_copy(out, ibuf2);
+
IMB_freeImBuf(ibuf1);
IMB_freeImBuf(ibuf2);
}
@@ -4640,7 +4647,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char
char name_esc[SEQ_NAME_MAXSTR * 2];
BLI_strescape(name_esc, name, sizeof(name_esc));
- return BLI_snprintf(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
+ return BLI_snprintf_rlen(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
}
/* XXX - hackish function needed for transforming strips! TODO - have some better solution */
@@ -4974,7 +4981,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 == NULL || sound->playback_handle == NULL) {
+ if (sound->playback_handle == NULL) {
#if 0
if (op)
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 6a831d23aea..30c17773f7d 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -66,7 +66,7 @@ static int sound_cfra;
bSound *BKE_sound_new_file(struct Main *bmain, const char *filename)
{
- bSound *sound = NULL;
+ bSound *sound;
char str[FILE_MAX];
const char *path;
@@ -89,11 +89,6 @@ bSound *BKE_sound_new_file(struct Main *bmain, const char *filename)
BKE_sound_load(bmain, sound);
- if (!sound->playback_handle) {
- BKE_libblock_free(bmain, sound);
- sound = NULL;
- }
-
return sound;
}
@@ -246,12 +241,6 @@ bSound *BKE_sound_new_buffer(struct Main *bmain, bSound *source)
sound_load(bmain, sound);
- if (!sound->playback_handle)
- {
- BKE_libblock_free(bmain, sound);
- sound = NULL;
- }
-
return sound;
}
@@ -272,12 +261,6 @@ bSound *BKE_sound_new_limiter(struct Main *bmain, bSound *source, float start, f
sound_load(bmain, sound);
- if (!sound->playback_handle)
- {
- BKE_libblock_free(bmain, sound);
- sound = NULL;
- }
-
return sound;
}
#endif
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index a4e0eaaa324..2b05a6c8fc5 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -300,7 +300,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
- vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit);
+ vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit, false);
if (!vmap)
return 0;
@@ -3828,7 +3828,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
/* note: editmode calculation can only run once per
* modifier stack evaluation (uses freed cache) [#36299] */
if (flags & SUBSURF_FOR_EDIT_MODE) {
- int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
+ int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels;
smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS);
ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
@@ -3840,7 +3840,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
else if (flags & SUBSURF_USE_RENDER_PARAMS) {
/* Do not use cache in render mode. */
CCGSubSurf *ss;
- int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels) : smd->renderLevels;
+ int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels, true) : smd->renderLevels;
if (levels == 0)
return dm;
@@ -3856,7 +3856,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
}
else {
int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
- int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels;
+ int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels;
CCGSubSurf *ss;
/* It is quite possible there is a much better place to do this. It
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 9f441b45db9..1966d5af7d1 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -473,6 +473,7 @@ Text *BKE_text_copy(Main *bmain, Text *ta)
BLI_listbase_clear(&tan->lines);
tan->curl = tan->sell = NULL;
+ tan->compiled = NULL;
tan->nlines = ta->nlines;
@@ -651,7 +652,7 @@ void BKE_text_unlink(Main *bmain, Text *text)
}
}
- /* Freestyle (while looping oer the scene) */
+ /* Freestyle (while looping over the scene) */
for (srl = sce->r.layers.first; srl; srl = srl->next) {
for (module = srl->freestyleConfig.modules.first; module; module = module->next) {
if (module->script == text)
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 83db0639468..e3f04296f50 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -1302,6 +1302,95 @@ void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
}
}
+bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingTrack *track)
+{
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] == track) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingTrack *track)
+{
+ int i, track_index;
+ MovieTrackingTrack **new_point_tracks;
+
+ if (plane_track->point_tracksnr <= 4) {
+ return false;
+ }
+
+ new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1),
+ "new point tracks array");
+
+ for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] != track) {
+ new_point_tracks[track_index++] = plane_track->point_tracks[i];
+ }
+ }
+
+ MEM_freeN(plane_track->point_tracks);
+ plane_track->point_tracks = new_point_tracks;
+ plane_track->point_tracksnr--;
+
+ return true;
+}
+
+void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking,
+ MovieTrackingTrack *track)
+{
+ MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = next_plane_track)
+ {
+ next_plane_track = plane_track->next;
+ if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
+ if (!BKE_tracking_plane_track_remove_point_track(plane_track, track)) {
+ /* Delete planes with less than 3 point tracks in it. */
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ }
+ }
+ }
+}
+
+void BKE_tracking_plane_track_replace_point_track(MovieTrackingPlaneTrack *plane_track,
+ MovieTrackingTrack *old_track,
+ MovieTrackingTrack *new_track)
+{
+ int i;
+ for (i = 0; i < plane_track->point_tracksnr; i++) {
+ if (plane_track->point_tracks[i] == old_track) {
+ plane_track->point_tracks[i] = new_track;
+ break;
+ }
+ }
+}
+
+void BKE_tracking_plane_tracks_replace_point_track(MovieTracking *tracking,
+ MovieTrackingTrack *old_track,
+ MovieTrackingTrack *new_track)
+{
+ MovieTrackingPlaneTrack *plane_track;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ for (plane_track = plane_tracks_base->first;
+ plane_track;
+ plane_track = plane_track->next)
+ {
+ if (BKE_tracking_plane_track_has_point_track(plane_track, old_track)) {
+ BKE_tracking_plane_track_replace_point_track(plane_track,
+ old_track,
+ new_track);
+ }
+ }
+}
+
/*********************** Plane Marker *************************/
MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track,
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index 4cb3f2ca493..76261bddfbc 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -534,19 +534,9 @@ void BKE_autotrack_context_finish(AutoTrackContext *context)
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
int track;
for (track = 0; track < context->num_tracks; ++track) {
- MovieTrackingTrack *old_track;
- bool do_update = false;
- int j;
-
- old_track = context->options[track].track;
- for (j = 0; j < plane_track->point_tracksnr; j++) {
- if (plane_track->point_tracks[j] == old_track) {
- do_update = true;
- break;
- }
- }
-
- if (do_update) {
+ if (BKE_tracking_plane_track_has_point_track(plane_track,
+ context->options[track].track))
+ {
BKE_tracking_track_plane_from_existing_motion(
plane_track,
context->first_frame);
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 5a2c77b5619..0d83695d2f1 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -370,12 +370,7 @@ static size_t unit_as_string(char *str, int len_max, double value, int prec, bUn
value_conv = value / unit->scalar;
/* Convert to a string */
- {
- len = BLI_snprintf(str, len_max, "%.*f", prec, value_conv);
-
- if (len >= len_max)
- len = len_max;
- }
+ len = BLI_snprintf_rlen(str, len_max, "%.*f", prec, value_conv);
/* Add unit prefix and strip zeros */
diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h
index 0dd1439e58c..ff7976dc701 100644
--- a/source/blender/blenlib/BLI_array_utils.h
+++ b/source/blender/blenlib/BLI_array_utils.h
@@ -34,6 +34,14 @@ void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir
#define BLI_array_wrap(arr, arr_len, dir) \
_bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir)
+void _bli_array_permute(
+ void *arr, const unsigned int arr_len, const size_t arr_stride,
+ const unsigned int *index, void *arr_temp);
+#define BLI_array_permute(arr, arr_len, order) \
+ _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, NULL)
+#define BLI_array_permute_ex(arr, arr_len, index, arr_temp) \
+ _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp)
+
int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p);
#define BLI_array_findindex(arr, arr_len, p) \
_bli_array_findindex(arr, arr_len, sizeof(*(arr)), p)
diff --git a/source/blender/blenlib/BLI_compiler_typecheck.h b/source/blender/blenlib/BLI_compiler_typecheck.h
index 652c4a954b9..b9fb3ebf47a 100644
--- a/source/blender/blenlib/BLI_compiler_typecheck.h
+++ b/source/blender/blenlib/BLI_compiler_typecheck.h
@@ -381,4 +381,303 @@
# define CHECK_TYPE_ANY(...) (void)0
#endif
+
+/**
+ * GENERIC_TYPE_ANY: handy macro to reuse a single expression for multiple types, eg:
+ *
+ * \code{.c}
+ * _Generic(value,
+ * GENERIC_TYPE_ANY(result_a, Foo *, Bar *, Baz *),
+ * GENERIC_TYPE_ANY(result_b, Spam *, Spaz *, Spot *),
+ * )
+ * \endcode
+ *
+ * excuse ridiculously long generated args.
+ * \code{.py}
+ * for i in range(63):
+ * args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)]
+ * print("#define _VA_GENERIC_TYPE_ANY%d(r, %s) \\" % (i + 2, ", ".join(args)))
+ * print(" %s: r " % (": r, ".join(args)))
+ * \endcode
+ */
+#define _VA_GENERIC_TYPE_ANY2(r, a0) \
+ a0: r
+#define _VA_GENERIC_TYPE_ANY3(r, a0, b0) \
+ a0: r, b0: r
+#define _VA_GENERIC_TYPE_ANY4(r, a0, b0, c0) \
+ a0: r, b0: r, c0: r
+#define _VA_GENERIC_TYPE_ANY5(r, a0, b0, c0, d0) \
+ a0: r, b0: r, c0: r, d0: r
+#define _VA_GENERIC_TYPE_ANY6(r, a0, b0, c0, d0, e0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r
+#define _VA_GENERIC_TYPE_ANY7(r, a0, b0, c0, d0, e0, f0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r
+#define _VA_GENERIC_TYPE_ANY8(r, a0, b0, c0, d0, e0, f0, g0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r
+#define _VA_GENERIC_TYPE_ANY9(r, a0, b0, c0, d0, e0, f0, g0, h0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r
+#define _VA_GENERIC_TYPE_ANY10(r, a0, b0, c0, d0, e0, f0, g0, h0, i0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r
+#define _VA_GENERIC_TYPE_ANY11(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r
+#define _VA_GENERIC_TYPE_ANY12(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r
+#define _VA_GENERIC_TYPE_ANY13(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r
+#define _VA_GENERIC_TYPE_ANY14(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r
+#define _VA_GENERIC_TYPE_ANY15(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r
+#define _VA_GENERIC_TYPE_ANY16(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r
+#define _VA_GENERIC_TYPE_ANY17(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r
+#define _VA_GENERIC_TYPE_ANY18(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r
+#define _VA_GENERIC_TYPE_ANY19(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r
+#define _VA_GENERIC_TYPE_ANY20(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r
+#define _VA_GENERIC_TYPE_ANY21(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r
+#define _VA_GENERIC_TYPE_ANY22(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r
+#define _VA_GENERIC_TYPE_ANY23(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r
+#define _VA_GENERIC_TYPE_ANY24(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r
+#define _VA_GENERIC_TYPE_ANY25(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r
+#define _VA_GENERIC_TYPE_ANY26(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r
+#define _VA_GENERIC_TYPE_ANY27(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r
+#define _VA_GENERIC_TYPE_ANY28(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r
+#define _VA_GENERIC_TYPE_ANY29(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r
+#define _VA_GENERIC_TYPE_ANY30(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r
+#define _VA_GENERIC_TYPE_ANY31(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r
+#define _VA_GENERIC_TYPE_ANY32(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r
+#define _VA_GENERIC_TYPE_ANY33(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r
+#define _VA_GENERIC_TYPE_ANY34(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r
+#define _VA_GENERIC_TYPE_ANY35(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r
+#define _VA_GENERIC_TYPE_ANY36(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r
+#define _VA_GENERIC_TYPE_ANY37(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r
+#define _VA_GENERIC_TYPE_ANY38(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r
+#define _VA_GENERIC_TYPE_ANY39(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r
+#define _VA_GENERIC_TYPE_ANY40(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r
+#define _VA_GENERIC_TYPE_ANY41(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r
+#define _VA_GENERIC_TYPE_ANY42(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r
+#define _VA_GENERIC_TYPE_ANY43(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r
+#define _VA_GENERIC_TYPE_ANY44(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r
+#define _VA_GENERIC_TYPE_ANY45(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r
+#define _VA_GENERIC_TYPE_ANY46(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r
+#define _VA_GENERIC_TYPE_ANY47(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r
+#define _VA_GENERIC_TYPE_ANY48(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r
+#define _VA_GENERIC_TYPE_ANY49(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r
+#define _VA_GENERIC_TYPE_ANY50(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r
+#define _VA_GENERIC_TYPE_ANY51(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r
+#define _VA_GENERIC_TYPE_ANY52(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r
+#define _VA_GENERIC_TYPE_ANY53(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r
+#define _VA_GENERIC_TYPE_ANY54(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r
+#define _VA_GENERIC_TYPE_ANY55(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r
+#define _VA_GENERIC_TYPE_ANY56(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r
+#define _VA_GENERIC_TYPE_ANY57(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r
+#define _VA_GENERIC_TYPE_ANY58(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r
+#define _VA_GENERIC_TYPE_ANY59(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r
+#define _VA_GENERIC_TYPE_ANY60(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r
+#define _VA_GENERIC_TYPE_ANY61(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r
+#define _VA_GENERIC_TYPE_ANY62(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r
+#define _VA_GENERIC_TYPE_ANY63(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r
+#define _VA_GENERIC_TYPE_ANY64(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \
+ u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \
+ w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2) \
+ a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \
+ q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \
+ g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \
+ w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r, k2: r
+
+# define GENERIC_TYPE_ANY(...) VA_NARGS_CALL_OVERLOAD(_VA_GENERIC_TYPE_ANY, __VA_ARGS__)
+
#endif /* __BLI_COMPILER_TYPECHECK_H__ */
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index 9ac233a8fa4..a4b8f77bfa6 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -168,6 +168,16 @@
#define BLI_SMALLSTACK_IS_EMPTY(var) \
((_BLI_SMALLSTACK_CAST(var) _##var##_stack) == NULL)
+/* fill in a lookup table */
+#define BLI_SMALLSTACK_AS_TABLE(var, data) \
+{ \
+ LinkNode *_##var##_iter; \
+ unsigned int i; \
+ for (_##var##_iter = _##var##_stack, i = 0; _##var##_iter; _##var##_iter = _##var##_iter->next, i++) { \
+ (data)[i] = _BLI_SMALLSTACK_CAST(var) (_##var##_iter->link); \
+ } \
+} ((void)0)
+
/* loop over stack members last-added-first */
#define BLI_SMALLSTACK_ITER_BEGIN(var, item) \
{ \
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index daa7db8e3cf..79a2d57c966 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -214,9 +214,7 @@ MINLINE int iroundf(float a);
MINLINE int divide_round_i(int a, int b);
MINLINE int mod_i(int i, int n);
-MINLINE unsigned int highest_order_bit_i(unsigned int n);
-MINLINE unsigned short highest_order_bit_s(unsigned short n);
-
+int pow_i(int base, int exp);
double double_round(double x, int ndigits);
#ifdef BLI_MATH_GCC_WARN_PRAGMA
diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h
new file mode 100644
index 00000000000..876c0d92e31
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_bits.h
@@ -0,0 +1,51 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * */
+
+#ifndef __BLI_MATH_BITS_H__
+#define __BLI_MATH_BITS_H__
+
+/** \file BLI_math_bits.h
+ * \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_math_inline.h"
+
+MINLINE unsigned int highest_order_bit_i(unsigned int n);
+MINLINE unsigned short highest_order_bit_s(unsigned short n);
+
+#ifdef __GNUC__
+# define count_bits_i(i) __builtin_popcount(i)
+#else
+MINLINE int count_bits_i(unsigned int n);
+#endif
+
+#if BLI_MATH_DO_INLINE
+#include "intern/math_bits_inline.c"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_MATH_BITS_H__ */
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 45972d03175..f7eeb1ec7a1 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -106,6 +106,7 @@ void mul_v2_m4v3(float r[2], float M[4][4], const float v[3]);
void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]);
void mul_m2v2(float M[2][2], float v[2]);
void mul_mat3_m4_v3(float M[4][4], float r[3]);
+void mul_v3_mat3_m4v3(float r[3], float M[4][4], const float v[3]);
void mul_m4_v4(float M[4][4], float r[4]);
void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]);
void mul_project_m4_v3(float M[4][4], float vec[3]);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 9c8a9f54379..82a2b9c9ab2 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -314,6 +314,7 @@ double len_squared_vn(const float *array, const int size) ATTR_WARN_UNUSED_RESUL
float normalize_vn_vn(float *array_tar, const float *array_src, const int size);
float normalize_vn(float *array_tar, const int size);
void range_vn_i(int *array_tar, const int size, const int start);
+void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start);
void range_vn_fl(float *array_tar, const int size, const float start, const float step);
void negate_vn(float *array_tar, const int size);
void negate_vn_vn(float *array_tar, const float *array_src, const int size);
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index c4853e37398..e6c1cc8b4b6 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -59,8 +59,10 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict
char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC;
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4);
+size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4);
size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0);
+size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0);
char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 2ddc8faa8b1..8f2f906ed17 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -435,7 +435,7 @@ extern "C" {
} (void)0
/* assuming a static array */
-#if defined(__GNUC__) && !defined(__cplusplus)
+#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__)
# define ARRAY_SIZE(arr) \
((sizeof(struct {int isnt_array : ((const void *)&(arr) == &(arr)[0]);}) * 0) + \
(sizeof(arr) / sizeof(*(arr))))
@@ -493,8 +493,11 @@ extern "C" {
#define OFFSETOF_STRUCT(_struct, _member) \
((((char *)&((_struct)->_member)) - ((char *)(_struct))) + sizeof((_struct)->_member))
-/* memcpy, skipping the first part of a struct,
- * ensures 'struct_dst' isn't const and that the offset can be computed at compile time */
+/**
+ * memcpy helper, skipping the first part of a struct,
+ * ensures 'struct_dst' isn't const and the offset can be computed at compile time.
+ * This isn't inclusive, the value of \a member isn't copied.
+ */
#define MEMCPY_STRUCT_OFS(struct_dst, struct_src, member) { \
CHECK_TYPE_NONCONST(struct_dst); \
((void)(struct_dst == struct_src), \
@@ -503,6 +506,13 @@ extern "C" {
sizeof(*(struct_dst)) - OFFSETOF_STRUCT(struct_dst, member))); \
} (void)0
+#define MEMSET_STRUCT_OFS(struct_var, value, member) { \
+ CHECK_TYPE_NONCONST(struct_var); \
+ memset((char *)(struct_var) + OFFSETOF_STRUCT(struct_var, member), \
+ value, \
+ sizeof(*(struct_var)) - OFFSETOF_STRUCT(struct_var, member)); \
+} (void)0
+
/* Warning-free macros for storing ints in pointers. Use these _only_
* for storing an int in a pointer, not a pointer in an int (64bit)! */
#define SET_INT_IN_POINTER(i) ((void *)(intptr_t)(i))
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 73bd4869566..797bdaa2ae4 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -75,6 +75,7 @@ set(SRC
intern/listbase.c
intern/math_base.c
intern/math_base_inline.c
+ intern/math_bits_inline.c
intern/math_color.c
intern/math_color_blend_inline.c
intern/math_color_inline.c
@@ -209,6 +210,7 @@ endif()
# no need to compile object files for inline headers.
set_source_files_properties(
intern/math_base_inline.c
+ intern/math_bits_inline.c
intern/math_color_blend_inline.c
intern/math_color_inline.c
intern/math_geom_inline.c
diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c
index 173effbc434..6c5dc5a7f1e 100644
--- a/source/blender/blenlib/intern/array_utils.c
+++ b/source/blender/blenlib/intern/array_utils.c
@@ -25,23 +25,28 @@
#include <string.h>
#include <stdlib.h>
+#include "MEM_guardedalloc.h"
+
#include "BLI_array_utils.h"
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
+#include "BLI_strict_flags.h"
+
void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride)
{
- const unsigned int arr_half_stride = (arr_len / 2) * arr_stride;
+ const unsigned int arr_stride_uint = (unsigned int)arr_stride;
+ const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint;
unsigned int i, i_end;
char *arr = arr_v;
char *buf = BLI_array_alloca(buf, arr_stride);
- for (i = 0, i_end = (arr_len - 1) * arr_stride;
+ for (i = 0, i_end = (arr_len - 1) * arr_stride_uint;
i < arr_half_stride;
- i += arr_stride, i_end -= arr_stride)
+ i += arr_stride_uint, i_end -= arr_stride_uint)
{
memcpy(buf, &arr[i], arr_stride);
memcpy(&arr[i], &arr[i_end], arr_stride);
@@ -69,6 +74,36 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d
}
}
+void _bli_array_permute(
+ void *arr_v, const unsigned int arr_len, const size_t arr_stride,
+ const unsigned int *order, void *arr_temp)
+{
+ const size_t len = arr_len * arr_stride;
+ const unsigned int arr_stride_uint = (unsigned int)arr_stride;
+ void *arr_orig;
+ unsigned int i;
+
+ if (arr_temp == NULL) {
+ arr_orig = MEM_mallocN(len, __func__);
+ }
+ else {
+ arr_orig = arr_temp;
+ }
+
+ memcpy(arr_orig, arr_v, len);
+
+ for (i = 0; i < arr_len; i++) {
+ BLI_assert(order[i] < arr_len);
+ memcpy(POINTER_OFFSET(arr_v, arr_stride_uint * i),
+ POINTER_OFFSET(arr_orig, arr_stride_uint * order[i]),
+ arr_stride);
+ }
+
+ if (arr_temp == NULL) {
+ MEM_freeN(arr_orig);
+ }
+}
+
/**
* \note Not efficient, use for error checks/asserts.
*/
diff --git a/source/blender/blenlib/intern/convexhull2d.c b/source/blender/blenlib/intern/convexhull2d.c
index 5f64088f433..f77beac1982 100644
--- a/source/blender/blenlib/intern/convexhull2d.c
+++ b/source/blender/blenlib/intern/convexhull2d.c
@@ -239,7 +239,7 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[])
*
* Intended to be used with #BLI_convexhull_2d
*
- * \param points Orded hull points
+ * \param points Ordered hull points
* (result of #BLI_convexhull_2d mapped to a contiguous array).
*
* \note we could return the index of the best edge too if its needed.
diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c
index cddfde371f5..0a1e9e8a8a1 100644
--- a/source/blender/blenlib/intern/math_base.c
+++ b/source/blender/blenlib/intern/math_base.c
@@ -31,6 +31,21 @@
#include "BLI_strict_flags.h"
+int pow_i(int base, int exp)
+{
+ int result = 1;
+ BLI_assert(exp >= 0);
+ while (exp) {
+ if (exp & 1) {
+ result *= base;
+ }
+ exp >>= 1;
+ base *= base;
+ }
+
+ return result;
+}
+
/* from python 3.1 floatobject.c
* ndigits must be between 0 and 21 */
double double_round(double x, int ndigits)
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index f5713824296..facee8b0a89 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -198,25 +198,6 @@ MINLINE int mod_i(int i, int n)
return (i % n + n) % n;
}
-MINLINE unsigned int highest_order_bit_i(unsigned int n)
-{
- n |= (n >> 1);
- n |= (n >> 2);
- n |= (n >> 4);
- n |= (n >> 8);
- n |= (n >> 16);
- return n - (n >> 1);
-}
-
-MINLINE unsigned short highest_order_bit_s(unsigned short n)
-{
- n |= (n >> 1);
- n |= (n >> 2);
- n |= (n >> 4);
- n |= (n >> 8);
- return (unsigned short)(n - (n >> 1));
-}
-
MINLINE float min_ff(float a, float b)
{
return (a < b) ? a : b;
diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c
new file mode 100644
index 00000000000..11ee6e7fa5b
--- /dev/null
+++ b/source/blender/blenlib/intern/math_bits_inline.c
@@ -0,0 +1,59 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * */
+
+/** \file blender/blenlib/intern/math_bits_inline.c
+ * \ingroup bli
+ */
+
+#ifndef __MATH_BITS_INLINE_C__
+#define __MATH_BITS_INLINE_C__
+
+#include "BLI_math_bits.h"
+
+MINLINE unsigned int highest_order_bit_i(unsigned int n)
+{
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ n |= (n >> 16);
+ return n - (n >> 1);
+}
+
+MINLINE unsigned short highest_order_bit_s(unsigned short n)
+{
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ return (unsigned short)(n - (n >> 1));
+}
+
+#ifndef __GNUC__
+MINLINE int count_bits_i(unsigned int i)
+{
+ /* variable-precision SWAR algorithm. */
+ i = i - ((i >> 1) & 0x55555555);
+ i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
+ return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
+}
+#endif
+
+#endif /* __MATH_BITS_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 1b4bbafdb04..a9afed7a63d 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -504,6 +504,16 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3])
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
}
+void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
+{
+ const float x = vec[0];
+ const float y = vec[1];
+
+ r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
+ r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
+ r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
+}
+
void mul_project_m4_v3(float mat[4][4], float vec[3])
{
const float w = mul_project_m4_v3_zfac(mat, vec);
@@ -1149,7 +1159,7 @@ bool is_orthogonal_m3(float m[3][3])
for (i = 0; i < 3; i++) {
for (j = 0; j < i; j++) {
- if (fabsf(dot_v3v3(m[i], m[j])) > 1.5f * FLT_EPSILON)
+ if (fabsf(dot_v3v3(m[i], m[j])) > 1e-5f)
return false;
}
}
@@ -1163,7 +1173,7 @@ bool is_orthogonal_m4(float m[4][4])
for (i = 0; i < 4; i++) {
for (j = 0; j < i; j++) {
- if (fabsf(dot_v4v4(m[i], m[j])) > 1.5f * FLT_EPSILON)
+ if (fabsf(dot_v4v4(m[i], m[j])) > 1e-5f)
return false;
}
@@ -1178,7 +1188,7 @@ bool is_orthonormal_m3(float m[3][3])
int i;
for (i = 0; i < 3; i++)
- if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
+ if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1e-5f)
return false;
return true;
@@ -1193,7 +1203,7 @@ bool is_orthonormal_m4(float m[4][4])
int i;
for (i = 0; i < 4; i++)
- if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON)
+ if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1e-5f)
return false;
return true;
@@ -1465,39 +1475,14 @@ float mat4_to_scale(float mat[4][4])
void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
{
- float mat3_n[3][3]; /* mat3 -> normalized, 3x3 */
- float imat3_n[3][3]; /* mat3 -> normalized & inverted, 3x3 */
-
- /* rotation & scale are linked, we need to create the mat's
- * for these together since they are related. */
-
- /* so scale doesn't interfere with rotation [#24291] */
- /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */
- normalize_m3_m3(mat3_n, mat3);
- if (is_negative_m3(mat3)) {
- negate_m3(mat3_n);
- }
-
- /* rotation */
/* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */
- copy_m3_m3(rot, mat3_n);
-
- /* scale */
- /* note: mat4_to_size(ob->size, mat) fails for negative scale */
- invert_m3_m3(imat3_n, mat3_n);
-
- /* better not edit mat3 */
-#if 0
- mul_m3_m3m3(mat3, imat3_n, mat3);
-
- size[0] = mat3[0][0];
- size[1] = mat3[1][1];
- size[2] = mat3[2][2];
-#else
- size[0] = dot_m3_v3_row_x(imat3_n, mat3[0]);
- size[1] = dot_m3_v3_row_y(imat3_n, mat3[1]);
- size[2] = dot_m3_v3_row_z(imat3_n, mat3[2]);
-#endif
+ size[0] = normalize_v3_v3(rot[0], mat3[0]);
+ size[1] = normalize_v3_v3(rot[1], mat3[1]);
+ size[2] = normalize_v3_v3(rot[2], mat3[2]);
+ if (UNLIKELY(is_negative_m3(rot))) {
+ negate_m3(rot);
+ negate_v3(size);
+ }
}
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4])
@@ -2251,7 +2236,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
{
- /* compute moon-penrose pseudo inverse of matrix, singular values
+ /* compute Moore-Penrose pseudo inverse of matrix, singular values
* below epsilon are ignored for stability (truncated SVD) */
float A[4][4], V[4][4], W[4], Wm[4][4], U[4][4];
int i;
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 1f0d68b09b2..5f039e89e89 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -1616,7 +1616,7 @@ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order
void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
{
- float *t, *q, dscale[3], scale[3], basequat[4];
+ float *t, *q, dscale[3], scale[3], basequat[4], mat3[3][3];
float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4];
float R[4][4], S[4][4];
@@ -1629,7 +1629,9 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
dscale[1] = scale[1] - 1.0f;
dscale[2] = scale[2] - 1.0f;
- if ((determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) {
+ copy_m3_m4(mat3, mat);
+
+ if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) {
/* extract R and S */
float tmp[4][4];
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index e9909cef29d..8f536bfe75c 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -897,6 +897,16 @@ void range_vn_i(int *array_tar, const int size, const int start)
}
}
+void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start)
+{
+ unsigned int *array_pt = array_tar + (size - 1);
+ unsigned int j = start + (unsigned int)(size - 1);
+ int i = size;
+ while (i--) {
+ *(array_pt--) = j--;
+ }
+}
+
void range_vn_fl(float *array_tar, const int size, const float start, const float step)
{
float *array_pt = array_tar + (size - 1);
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index 3aadbe5f1df..629bed10191 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -179,7 +179,7 @@ BLI_INLINE eSign signum_enum(float a)
* alternative version of #area_tri_signed_v2
* needed because of float precision issues
*
- * \note removes / 2 since its not needed since we only need ths sign.
+ * \note removes / 2 since its not needed since we only need the sign.
*/
BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2])
{
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index cc5a90dbc39..e41e52a7c6e 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -231,6 +231,30 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__rest
}
/**
+ * A version of #BLI_vsnprintf that returns ``strlen(buffer)``
+ */
+size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg)
+{
+ size_t n;
+
+ BLI_assert(buffer != NULL);
+ BLI_assert(maxncpy > 0);
+ BLI_assert(format != NULL);
+
+ n = (size_t)vsnprintf(buffer, maxncpy, format, arg);
+
+ if (n != -1 && n < maxncpy) {
+ /* pass */
+ }
+ else {
+ n = maxncpy - 1;
+ }
+ buffer[n] = '\0';
+
+ return n;
+}
+
+/**
* Portable replacement for #snprintf
*/
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
@@ -250,6 +274,25 @@ size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict
}
/**
+ * A version of #BLI_snprintf that returns ``strlen(dst)``
+ */
+size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...)
+{
+ size_t n;
+ va_list arg;
+
+#ifdef DEBUG_STRSIZE
+ memset(dst, 0xff, sizeof(*dst) * maxncpy);
+#endif
+
+ va_start(arg, format);
+ n = BLI_vsnprintf_rlen(dst, maxncpy, format, arg);
+ va_end(arg);
+
+ return n;
+}
+
+/**
* Print formatted string into a newly #MEM_mallocN'd string
* and return it.
*/
diff --git a/source/blender/blenlib/intern/timecode.c b/source/blender/blenlib/intern/timecode.c
index 0c8834008b6..7b98d7830ee 100644
--- a/source/blender/blenlib/intern/timecode.c
+++ b/source/blender/blenlib/intern/timecode.c
@@ -113,22 +113,22 @@ size_t BLI_timecode_string_from_time(
if (power <= 0) {
/* include "frames" in display */
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames);
}
else if (minutes) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%d+%02d", neg, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%d+%02d", neg, seconds, frames);
}
}
else {
/* don't include 'frames' in display */
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds);
}
}
break;
@@ -137,10 +137,10 @@ size_t BLI_timecode_string_from_time(
{
/* reduced SMPTE format that always shows minutes, seconds, frames. Hours only shown as needed. */
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames);
}
break;
}
@@ -156,10 +156,10 @@ size_t BLI_timecode_string_from_time(
const int s_pad = ms_dp + 3;
if (hours) {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time);
}
break;
}
@@ -168,10 +168,10 @@ size_t BLI_timecode_string_from_time(
/* only show the original seconds display */
/* round to whole numbers if power is >= 1 (i.e. scale is coarse) */
if (power <= 0) {
- rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds));
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds));
}
break;
}
@@ -179,7 +179,7 @@ size_t BLI_timecode_string_from_time(
default:
{
/* full SMPTE format */
- rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
break;
}
}
@@ -208,10 +208,10 @@ size_t BLI_timecode_string_from_time_simple(
/* round to whole numbers if power is >= 1 (i.e. scale is coarse) */
if (power <= 0) {
- rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds);
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds);
}
else {
- rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds));
+ rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds));
}
return rlen;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1b9cc0063a6..c9952926913 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2639,7 +2639,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
* New file versions already have input/output nodes with duplicate links,
* in that case just remove the invalid links.
*/
- int create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE);
+ const bool create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE) != 0;
float input_locx = 1000000.0f, input_locy = 0.0f;
float output_locx = -1000000.0f, output_locy = 0.0f;
@@ -3532,7 +3532,7 @@ static void direct_link_curve(FileData *fd, Curve *cu)
nu->bp = newdataadr(fd, nu->bp);
nu->knotsu = newdataadr(fd, nu->knotsu);
nu->knotsv = newdataadr(fd, nu->knotsv);
- if (cu->vfont == NULL) nu->charidx= nu->mat_nr;
+ if (cu->vfont == NULL) nu->charidx = 0;
if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
switch_endian_knots(nu);
@@ -5829,6 +5829,12 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->lastcursor = 0;
win->modalcursor = 0;
win->stereo3d_format = newdataadr(fd, win->stereo3d_format);
+
+ /* multiview always fallback to anaglyph at file opening
+ * otherwise quadbuffer saved files can break Blender */
+ if (win->stereo3d_format) {
+ win->stereo3d_format->display_mode = S3D_DISPLAY_ANAGLYPH;
+ }
}
BLI_listbase_clear(&wm->timers);
@@ -5979,6 +5985,9 @@ static void lib_link_screen(FileData *fd, Main *main)
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;
+ }
}
else if (sl->spacetype == SPACE_FILE) {
;
@@ -6308,6 +6317,9 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
else if (sl->spacetype == SPACE_BUTS) {
SpaceButs *sbuts = (SpaceButs *)sl;
sbuts->pinid = restore_pointer_by_name(newmain, sbuts->pinid, USER_IGNORE);
+ if (sbuts->pinid == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
/* TODO: restore path pointers: T40046
* (complicated because this contains data pointers too, not just ID)*/
@@ -7085,7 +7097,7 @@ static void direct_link_moviePlaneTracks(FileData *fd, ListBase *plane_tracks_ba
int i;
plane_track->point_tracks = newdataadr(fd, plane_track->point_tracks);
-
+ test_pointer_array(fd, (void**)&plane_track->point_tracks);
for (i = 0; i < plane_track->point_tracksnr; i++) {
plane_track->point_tracks[i] = newdataadr(fd, plane_track->point_tracks[i]);
}
@@ -7809,12 +7821,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if (G.debug & G_DEBUG) {
char build_commit_datetime[32];
time_t temp_time = main->build_commit_timestamp;
- struct tm *tm = gmtime(&temp_time);
+ struct tm *tm = (temp_time) ? gmtime(&temp_time) : NULL;
if (LIKELY(tm)) {
strftime(build_commit_datetime, sizeof(build_commit_datetime), "%Y-%m-%d %H:%M", tm);
}
else {
- BLI_strncpy(build_commit_datetime, "date-unknown", sizeof(build_commit_datetime));
+ BLI_strncpy(build_commit_datetime, "unknown", sizeof(build_commit_datetime));
}
printf("read file %s\n Version %d sub %d date %s hash %s\n",
@@ -9245,7 +9257,6 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
/* assign the group */
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
- rename_id(&ob->id, group->id.name + 2);
copy_v3_v3(ob->loc, scene->cursor);
}
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index c8862870b92..df985448ccd 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -799,4 +799,36 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(main, 274, 6)) {
+ bScreen *screen;
+
+ if (!DNA_struct_elem_find(fd->filesdna, "FileSelectParams", "int", "thumbnail_size")) {
+ for (screen = main->screen.first; screen; screen = screen->id.next) {
+ ScrArea *sa;
+
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_FILE) {
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ if (sfile->params) {
+ sfile->params->thumbnail_size = 128;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "short", "simplify_subsurf_render")) {
+ Scene *scene;
+ for (scene = main->scene.first; scene != NULL; scene = scene->id.next) {
+ scene->r.simplify_subsurf_render = scene->r.simplify_subsurf;
+ scene->r.simplify_particles_render = scene->r.simplify_particles;
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 12c4f4922dc..285c50a4049 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1903,26 +1903,35 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_
static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count)
{
- CustomData data_tmp;
int i;
- /* This copy will automatically ignore/remove layers set as NO_COPY (and TEMPORARY). */
- CustomData_copy(data, &data_tmp, CD_MASK_EVERYTHING, CD_REFERENCE, count);
+ int nofree_buff[128];
+ int *nofree;
/* write external customdata (not for undo) */
- if (data_tmp.external && !wd->current)
- CustomData_external_write(&data_tmp, id, CD_MASK_MESH, count, 0);
+ if (data->external && !wd->current)
+ CustomData_external_write(data, id, CD_MASK_MESH, count, 0);
- for (i = 0; i < data_tmp.totlayer; i++)
- data_tmp.layers[i].flag &= ~CD_FLAG_NOFREE;
+ if (data->totlayer > ARRAY_SIZE(nofree_buff)) {
+ nofree = MEM_mallocN(sizeof(*nofree) * (size_t)data->totlayer, __func__);
+ }
+ else {
+ nofree = nofree_buff;
+ }
- writestruct_at_address(wd, DATA, "CustomDataLayer", data_tmp.maxlayer, data->layers, data_tmp.layers);
+ for (i = 0; i < data->totlayer; i++) {
+ nofree[i] = (data->layers[i].flag & CD_FLAG_NOFREE);
+ data->layers[i].flag &= ~CD_FLAG_NOFREE;
+ }
+
+ writestruct(wd, DATA, "CustomDataLayer", data->maxlayer, data->layers);
- for (i = 0; i < data_tmp.totlayer; i++)
- data_tmp.layers[i].flag |= CD_FLAG_NOFREE;
+ for (i = 0; i < data->totlayer; i++) {
+ data->layers[i].flag |= nofree[i];
+ }
- for (i = 0; i < data_tmp.totlayer; i++) {
- CustomDataLayer *layer= &data_tmp.layers[i];
+ for (i = 0; i < data->totlayer; i++) {
+ CustomDataLayer *layer= &data->layers[i];
const char *structname;
int structnum, datasize;
@@ -1958,10 +1967,12 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data,
}
}
- if (data_tmp.external)
- writestruct_at_address(wd, DATA, "CustomDataExternal", 1, data->external, data_tmp.external);
+ if (data->external)
+ writestruct(wd, DATA, "CustomDataExternal", 1, data->external);
- CustomData_free(&data_tmp, count);
+ if (nofree != nofree_buff) {
+ MEM_freeN(nofree);
+ }
}
static void write_meshes(WriteData *wd, ListBase *idbase)
@@ -1978,23 +1989,32 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
if (mesh->id.us>0 || wd->current) {
/* write LibData */
if (!save_for_old_blender) {
-
-#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
/* 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));
+#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
+
+ /* Bummer! We need to do the copy *before* writing mesh's struct itself,
+ * because we eliminate NO_COPY & TEMPORARY layers here, which means
+ * **number of layers (data.totlayer) may be smaller!**
+ * If we do not do that, we can get crash by buffer-overflow on reading, see T44461. */
+ CustomData_copy(&old_mesh->vdata, &mesh->vdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totvert);
+ CustomData_copy(&old_mesh->edata, &mesh->edata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totedge);
+#ifndef USE_BMESH_SAVE_WITHOUT_MFACE /* Do not copy org fdata in this case!!! */
+ CustomData_copy(&old_mesh->fdata, &mesh->fdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totface);
+#endif
+ CustomData_copy(&old_mesh->ldata, &mesh->ldata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totloop);
+ CustomData_copy(&old_mesh->pdata, &mesh->pdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totpoly);
writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh);
-#else
- writestruct(wd, ID_ME, "Mesh", 1, mesh);
-#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
/* direct data */
if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd);
@@ -2010,11 +2030,16 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0);
write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0);
-#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
+ CustomData_free(&mesh->vdata, mesh->totvert);
+ CustomData_free(&mesh->edata, mesh->totedge);
+#ifndef USE_BMESH_SAVE_WITHOUT_MFACE
+ CustomData_free(&mesh->fdata, mesh->totface);
+#endif
+ CustomData_free(&mesh->ldata, mesh->totloop);
+ CustomData_free(&mesh->pdata, mesh->totpoly);
+
/* restore pointer */
mesh = old_mesh;
-#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
-
}
else {
@@ -2041,6 +2066,10 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
BKE_mesh_update_customdata_pointers(mesh, false);
+ /* See comment above. Note that loop/poly data are ignored here, and face ones are already handled. */
+ CustomData_copy(&old_mesh->vdata, &mesh->vdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totvert);
+ CustomData_copy(&old_mesh->edata, &mesh->edata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totedge);
+
writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh);
/* direct data */
@@ -2059,6 +2088,8 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0);
#endif
+ CustomData_free(&mesh->vdata, mesh->totvert);
+ CustomData_free(&mesh->edata, mesh->totedge);
CustomData_free(&mesh->fdata, mesh->totface);
/* restore pointer */
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 75de216898b..058fec548a3 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -256,12 +256,29 @@ enum {
#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
+/* args for _Generic */
+#define _BM_GENERIC_TYPE_ELEM_NONCONST \
+ void *, BMVert *, BMEdge *, BMLoop *, BMFace *, \
+ BMElem *, BMElemF *, BMHeader *
+
+#define _BM_GENERIC_TYPE_ELEM_CONST \
+ const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \
+ const BMElem *, const BMElemF *, const BMHeader *, \
+ void * const, BMVert * const, BMEdge * const, BMLoop * const, BMFace * const, \
+ BMElem * const, BMElemF * const, BMHeader * const
+
+#define BM_CHECK_TYPE_ELEM_CONST(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST)
+
+#define BM_CHECK_TYPE_ELEM_NONCONST(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
+
#define BM_CHECK_TYPE_ELEM(ele) \
- CHECK_TYPE_ANY(ele, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *, BMElemF *, BMHeader *)
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST)
#ifndef __cplusplus
#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \
- (BM_CHECK_TYPE_ELEM(ele), CHECK_TYPE_NONCONST(ele)), ele
+ (BM_CHECK_TYPE_ELEM(ele)), ele
#else
/* for C++: cast the lhs to a void*,
* because C++ does not allow implicit void* casting of the rhs
@@ -305,8 +322,17 @@ typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
#define BM_ELEM_CD_GET_INT(ele, offset) \
(assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
+ (assert(offset != -1), \
+ _Generic(ele, \
+ GENERIC_TYPE_ANY( POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_NONCONST), \
+ GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_CONST)) \
+ )
+#else
#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
(assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
+#endif
#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index e0348fea636..fb7f936318b 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -47,8 +47,9 @@
#define SELECT 1
/* prototypes */
-static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop);
+static void bm_loop_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMLoop *source_loop, BMLoop *target_loop);
/**
* \brief Make Quad/Triangle
@@ -64,9 +65,10 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
* of the vertices in the vertex array.
*/
-BMFace *BM_face_create_quad_tri(BMesh *bm,
- BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_quad_tri(
+ BMesh *bm,
+ BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMVert *vtar[4] = {v1, v2, v3, v4};
return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
@@ -81,8 +83,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm,
* this is done since the face may not be completely surrounded by faces,
* this way: a quad with 2 connected quads on either side will still get all 4 loops updated
*/
-void BM_face_copy_shared(BMesh *bm, BMFace *f,
- BMElemFilterFunc filter_fn, void *user_data)
+void BM_face_copy_shared(
+ BMesh *bm, BMFace *f,
+ BMElemFilterFunc filter_fn, void *user_data)
{
BMLoop *l_first;
BMLoop *l_iter;
@@ -132,155 +135,113 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f,
}
/**
- * \brief Make NGon
- *
- * Makes an ngon from an unordered list of edges. \a v1 and \a v2
- * must be the verts defining edges[0],
- * and define the winding of the new face.
- *
- * \a edges are not required to be ordered, simply to to form
- * a single closed loop as a whole.
+ * Given an array of edges,
+ * order them using the winding defined by \a v1 & \a v2
+ * into \a edges_sort & \a verts_sort.
*
- * \note While this function will work fine when the edges
- * are already sorted, if the edges are always going to be sorted,
- * #BM_face_create should be considered over this function as it
- * avoids some unnecessary work.
+ * All arrays must be \a len long.
*/
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+static bool bm_edges_sort_winding(
+ BMVert *v1, BMVert *v2,
+ BMEdge **edges, const int len,
+ BMEdge **edges_sort, BMVert **verts_sort)
{
- BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
- BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1);
- int esort_index = 0;
- int vsort_index = 0;
-
- BMFace *f = NULL;
- BMEdge *e;
- BMVert *v, *ev1, *ev2;
+ BMEdge *e_iter, *e_first;
+ BMVert *v_iter;
int i;
- bool is_v1_found, is_reverse;
-
- /* this code is hideous, yeek. I'll have to think about ways of
- * cleaning it up. basically, it now combines the old BM_face_create_ngon
- * _and_ the old bmesh_mf functions, so its kindof smashed together
- * - joeedh */
-
- BLI_assert(len && v1 && v2 && edges && bm);
-
- /* put edges in correct order */
+ /* all flags _must_ be cleared on exit! */
for (i = 0; i < len; i++) {
BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
}
- ev1 = edges[0]->v1;
- ev2 = edges[0]->v2;
-
- BLI_assert(ELEM(v1, ev1, ev2) && ELEM(v2, ev1, ev2));
-
- if (v1 == ev2) {
- /* Swapping here improves performance and consistency of face
- * structure in the special case that the edges are already in
- * the correct order and winding */
- SWAP(BMVert *, ev1, ev2);
- }
-
- verts_sort[vsort_index++] = ev1;
- v = ev2;
- e = edges[0];
+ /* find first edge */
+ i = 0;
+ v_iter = v1;
+ e_iter = e_first = v1->e;
do {
- BMEdge *e2 = e;
-
- /* vertex array is (len + 1) */
- if (UNLIKELY(vsort_index > len)) {
- goto err; /* vertex in loop twice */
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) &&
+ (BM_edge_other_vert(e_iter, v_iter) == v2))
+ {
+ i = 1;
+ break;
}
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
+ if (i == 0) {
+ goto error;
+ }
- verts_sort[vsort_index++] = v;
- edges_sort[esort_index++] = e;
-
- /* we only flag the verts to check if they are in the face more than once */
- BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV);
-
- do {
- e2 = bmesh_disk_edge_next(e2, v);
- if (e2 != e && BM_ELEM_API_FLAG_TEST(e2, _FLAG_MF)) {
- v = BM_edge_other_vert(e2, v);
- break;
+ i = 0;
+ do {
+ /* entering loop will always succeed */
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
+ if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
+ /* vert is in loop multiple times */
+ goto error;
}
- } while (e2 != e);
- if (UNLIKELY(e2 == e)) {
- goto err; /* the edges do not form a closed loop */
- }
+ BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF);
+ edges_sort[i] = e_iter;
- e = e2;
- } while (e != edges[0]);
+ BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV);
+ verts_sort[i] = v_iter;
- if (UNLIKELY(esort_index != len)) {
- goto err; /* we didn't use all edges in forming the boundary loop */
- }
+ i += 1;
- /* ok, edges are in correct order, now ensure they are going
- * in the correct direction */
- is_v1_found = is_reverse = false;
- for (i = 0; i < len; i++) {
- if (BM_vert_in_edge(edges_sort[i], v1)) {
- /* see if v1 and v2 are in the same edge */
- if (BM_vert_in_edge(edges_sort[i], v2)) {
- /* if v1 is shared by the *next* edge, then the winding
- * is incorrect */
- if (BM_vert_in_edge(edges_sort[(i + 1) % len], v1)) {
- is_reverse = true;
- break;
+ /* walk onto the next vertex */
+ v_iter = BM_edge_other_vert(e_iter, v_iter);
+ if (i == len) {
+ if (UNLIKELY(v_iter != verts_sort[0])) {
+ goto error;
}
+ break;
}
- is_v1_found = true;
+ e_first = e_iter;
}
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
- if ((is_v1_found == false) && BM_vert_in_edge(edges_sort[i], v2)) {
- is_reverse = true;
- break;
- }
- }
-
- if (is_reverse) {
- for (i = 0; i < len / 2; i++) {
- v = verts_sort[i];
- verts_sort[i] = verts_sort[len - i - 1];
- verts_sort[len - i - 1] = v;
- }
+ if (i == len) {
+ return true;
}
+error:
for (i = 0; i < len; i++) {
- edges_sort[i] = BM_edge_exists(verts_sort[i], verts_sort[(i + 1) % len]);
- if (UNLIKELY(edges_sort[i] == NULL)) {
- goto err;
- }
-
- /* check if vert is in face more than once. if the flag is disabled. we've already visited */
- if (UNLIKELY(!BM_ELEM_API_FLAG_TEST(verts_sort[i], _FLAG_MV))) {
- goto err;
- }
- BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV);
}
- f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
+ return false;
+}
- /* clean up flags */
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges_sort[i], _FLAG_MF);
- }
+/**
+ * \brief Make NGon
+ *
+ * Makes an ngon from an unordered list of edges.
+ * Verts \a v1 and \a v2 define the winding of the new face.
+ *
+ * \a edges are not required to be ordered, simply to to form
+ * a single closed loop as a whole.
+ *
+ * \note While this function will work fine when the edges
+ * are already sorted, if the edges are always going to be sorted,
+ * #BM_face_create should be considered over this function as it
+ * avoids some unnecessary work.
+ */
+BMFace *BM_face_create_ngon(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
+{
+ BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
+ BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
- return f;
+ BLI_assert(len && v1 && v2 && edges && bm);
-err:
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
- }
- for (i = 0; i < vsort_index; i++) {
- BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
+ if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
+ return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
}
return NULL;
@@ -294,9 +255,10 @@ err:
* - Optionally create edges between vertices.
* - Uses verts so no need to find edges (handy when you only have verts)
*/
-BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool calc_winding, const bool create_edges)
+BMFace *BM_face_create_ngon_verts(
+ BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool calc_winding, const bool create_edges)
{
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
unsigned int winding[2] = {0, 0};
@@ -375,8 +337,9 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
*
* \note Since this is a vcloud there is no direction.
*/
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_ngon_vcloud(
+ BMesh *bm, BMVert **vert_arr, int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
@@ -497,8 +460,9 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
/*************************************************************/
-static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMVert *source_vertex, BMVert *target_vertex)
+static void bm_vert_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMVert *source_vertex, BMVert *target_vertex)
{
if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
BLI_assert(!"BMVert: source and targer match");
@@ -510,8 +474,9 @@ static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_vertex->head.data, &target_vertex->head.data);
}
-static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMEdge *source_edge, BMEdge *target_edge)
+static void bm_edge_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMEdge *source_edge, BMEdge *target_edge)
{
if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
BLI_assert(!"BMEdge: source and targer match");
@@ -522,8 +487,9 @@ static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_edge->head.data, &target_edge->head.data);
}
-static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop)
+static void bm_loop_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMLoop *source_loop, BMLoop *target_loop)
{
if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
BLI_assert(!"BMLoop: source and targer match");
@@ -534,8 +500,9 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_loop->head.data, &target_loop->head.data);
}
-static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMFace *source_face, BMFace *target_face)
+static void bm_face_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMFace *source_face, BMFace *target_face)
{
if ((source_mesh == target_mesh) && (source_face == target_face)) {
BLI_assert(!"BMFace: source and targer match");
@@ -555,8 +522,9 @@ static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
* Copies attributes, e.g. customdata, header flags, etc, from one element
* to another of the same type.
*/
-void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
- const char hflag_mask)
+void BM_elem_attrs_copy_ex(
+ BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
+ const char hflag_mask)
{
const BMHeader *ele_src = ele_src_v;
BMHeader *ele_dst = ele_dst_v;
@@ -621,9 +589,10 @@ void BM_elem_select_copy(BMesh *bm_dst, BMesh *UNUSED(bm_src), void *ele_dst_v,
}
/* helper function for 'BM_mesh_copy' */
-static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old,
- BMVert **vtable, BMEdge **etable,
- BMFace *f)
+static BMFace *bm_mesh_copy_new_face(
+ BMesh *bm_new, BMesh *bm_old,
+ BMVert **vtable, BMEdge **etable,
+ BMFace *f)
{
BMLoop **loops = BLI_array_alloca(loops, f->len);
BMVert **verts = BLI_array_alloca(verts, f->len);
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 12d3a4bd474..0e3ca75681a 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -29,23 +29,29 @@
struct BMAllocTemplate;
-BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_quad_tri(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
-void BM_face_copy_shared(BMesh *bm, BMFace *f,
- BMElemFilterFunc filter_fn, void *user_data);
+void BM_face_copy_shared(
+ BMesh *bm, BMFace *f,
+ BMElemFilterFunc filter_fn, void *user_data);
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool calc_winding, const bool create_edges);
+BMFace *BM_face_create_ngon(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_ngon_verts(
+ BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool calc_winding, const bool create_edges);
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_ngon_vcloud(
+ BMesh *bm, BMVert **vert_arr, int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
-void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
- const char hflag_mask);
+void BM_elem_attrs_copy_ex(
+ BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
+ const char hflag_mask);
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v);
void BM_elem_select_copy(BMesh *bm_dst, BMesh *bm_src, void *ele_dst_v, const void *ele_src_v);
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 7b54fcbffde..2a69edd47b0 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -31,7 +31,7 @@
#include "BLI_math_vector.h"
#include "BLI_array.h"
#include "BLI_alloca.h"
-#include "BLI_smallhash.h"
+#include "BLI_linklist_stack.h"
#include "BLI_stackdefines.h"
#include "BLF_translation.h"
@@ -57,8 +57,9 @@
/**
* \brief Main function for creating a new vertex.
*/
-BMVert *BM_vert_create(BMesh *bm, const float co[3],
- const BMVert *v_example, const eBMCreateFlag create_flag)
+BMVert *BM_vert_create(
+ BMesh *bm, const float co[3],
+ const BMVert *v_example, const eBMCreateFlag create_flag)
{
BMVert *v = BLI_mempool_alloc(bm->vpool);
@@ -141,8 +142,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3],
* \note Duplicate edges are supported by the API however users should _never_ see them.
* so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true
*/
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
- const BMEdge *e_example, const eBMCreateFlag create_flag)
+BMEdge *BM_edge_create(
+ BMesh *bm, BMVert *v1, BMVert *v2,
+ const BMEdge *e_example, const eBMCreateFlag create_flag)
{
BMEdge *e;
@@ -204,8 +206,9 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
return e;
}
-static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
- const BMLoop *l_example, const eBMCreateFlag create_flag)
+static BMLoop *bm_loop_create(
+ BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
+ const BMLoop *l_example, const eBMCreateFlag create_flag)
{
BMLoop *l = NULL;
@@ -254,8 +257,9 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
return l;
}
-static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte,
- const eBMCreateFlag create_flag)
+static BMLoop *bm_face_boundary_add(
+ BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte,
+ const eBMCreateFlag create_flag)
{
#ifdef USE_BMESH_HOLES
BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
@@ -276,8 +280,9 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge
return l;
}
-BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
- const bool copy_verts, const bool copy_edges)
+BMFace *BM_face_copy(
+ BMesh *bm_dst, BMesh *bm_src, BMFace *f,
+ const bool copy_verts, const bool copy_edges)
{
BMVert **verts = BLI_array_alloca(verts, f->len);
BMEdge **edges = BLI_array_alloca(edges, f->len);
@@ -400,8 +405,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
* \param len Length of the face
* \param create_flag Options for creating the face
*/
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create(
+ BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMFace *f = NULL;
BMLoop *l, *startl, *lastl;
@@ -474,8 +480,9 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
/**
* Wrapper for #BM_face_create when you don't have an edge array
*/
-BMFace *BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
+BMFace *BM_face_create_verts(
+ BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
{
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
int i, i_prev = len - 1;
@@ -1046,8 +1053,9 @@ static bool disk_is_flagged(BMVert *v, const char api_flag)
return false;
}
- if (bmesh_radial_length(l) == 1)
+ if (BM_edge_is_boundary(l->e)) {
return false;
+ }
do {
if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag))
@@ -1327,14 +1335,14 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
*
* \return A BMFace pointer
*/
-BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
- BMLoop **r_l,
+BMFace *bmesh_sfme(
+ BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
+ BMLoop **r_l,
#ifdef USE_BMESH_HOLES
- ListBase *holes,
+ ListBase *holes,
#endif
- BMEdge *e_example,
- const bool no_double
- )
+ BMEdge *e_example,
+ const bool no_double)
{
#ifdef USE_BMESH_HOLES
BMLoopList *lst, *lst2;
@@ -1501,14 +1509,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
bmesh_disk_edge_remove(e_new, tv);
bmesh_disk_edge_remove(e_new, v_new);
- /* remove e from tv's disk cycle */
- bmesh_disk_edge_remove(e, tv);
-
- /* swap out tv for v_new in e */
- bmesh_edge_swapverts(e, tv, v_new);
-
- /* add e to v_new's disk cycle */
- bmesh_disk_edge_append(e, v_new);
+ bmesh_disk_vert_replace(e, v_new, tv);
/* add e_new to v_new's disk cycle */
bmesh_disk_edge_append(e_new, v_new);
@@ -1673,13 +1674,14 @@ 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(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_double)
+BMEdge *bmesh_jekv(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool check_edge_double)
{
BMEdge *e_old;
BMVert *v_old, *tv;
BMLoop *l_kill;
- int len, radlen = 0, i;
+ int radlen = 0, i;
bool halt = false;
#ifndef NDEBUG
bool edok;
@@ -1690,10 +1692,8 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
if (BM_vert_in_edge(e_kill, v_kill) == 0) {
return NULL;
}
-
- len = bmesh_disk_count(v_kill);
- if (len == 2) {
+ if (bmesh_disk_count_ex(v_kill, 3) == 2) {
#ifndef NDEBUG
int valence1, valence2;
BMLoop *l;
@@ -1720,12 +1720,8 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
e_splice = BM_edge_exists(tv, v_old);
}
- /* remove e_old from v_kill's disk cycle */
- bmesh_disk_edge_remove(e_old, v_kill);
- /* relink e_old->v_kill to be e_old->tv */
- bmesh_edge_swapverts(e_old, v_kill, tv);
- /* append e_old to tv's disk cycle */
- bmesh_disk_edge_append(e_old, tv);
+ bmesh_disk_vert_replace(e_old, tv, v_kill);
+
/* remove e_kill from tv's disk cycle */
bmesh_disk_edge_remove(e_kill, tv);
@@ -1809,7 +1805,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
if (check_edge_double) {
if (e_splice) {
/* removes e_splice */
- BM_edge_splice(bm, e_splice, e_old);
+ BM_edge_splice(bm, e_old, e_splice);
}
}
@@ -1983,27 +1979,38 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
BLI_assert(BM_edge_exists(v_a, v_b) == false);
if (v_a->e && v_b->e) {
- SmallHash visit;
BMEdge *e, *e_first;
- BLI_smallhash_init(&visit);
+#define VERT_VISIT _FLAG_WALK
+ /* tag 'v_a' */
e = e_first = v_a->e;
do {
BMVert *v_other = BM_edge_other_vert(e, v_a);
- BLI_smallhash_insert(&visit, (uintptr_t)v_other, NULL);
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT);
} while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+ /* check 'v_b' connects to 'v_a' edges */
e = e_first = v_b->e;
do {
BMVert *v_other = BM_edge_other_vert(e, v_b);
- if (BLI_smallhash_haskey(&visit, (uintptr_t)v_other)) {
+ if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) {
is_double = true;
break;
}
} while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first);
- BLI_smallhash_release(&visit);
+ /* cleanup */
+ e = e_first = v_a->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_a);
+ BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
+ BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+
+#undef VERT_VISIT
+
}
return is_double;
@@ -2012,7 +2019,8 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
/**
* \brief Splice Vert
*
- * Merges two verts into one (\a v into \a vtarget).
+ * Merges two verts into one
+ * (\a v_src into \a v_dst, removing \a v_src).
*
* \return Success
*
@@ -2020,49 +2028,42 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
* where \a v and \a vtarget are connected by an edge
* (assert checks for this case).
*/
-bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
+bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
{
BMEdge *e;
/* verts already spliced */
- if (v == v_target) {
+ if (v_src == v_dst) {
return false;
}
- BLI_assert(BM_vert_pair_share_face_check(v, v_target) == false);
+ BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false);
- /* move all the edges from v's disk to vtarget's disk */
- while ((e = v->e)) {
-
- /* loop */
- BMLoop *l_first;
- if ((l_first = e->l)) {
- BMLoop *l_iter = l_first;
- do {
- if (l_iter->v == v) {
- l_iter->v = v_target;
- }
- /* else if (l_iter->prev->v == v) {...}
- * (this case will be handled by a different edge) */
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-
- /* disk */
- bmesh_disk_edge_remove(e, v);
- bmesh_edge_swapverts(e, v, v_target);
- bmesh_disk_edge_append(e, v_target);
+ /* move all the edges from 'v_src' disk to 'v_dst' */
+ while ((e = v_src->e)) {
+ bmesh_edge_vert_swap(e, v_dst, v_src);
BLI_assert(e->v1 != e->v2);
}
- BM_CHECK_ELEMENT(v);
- BM_CHECK_ELEMENT(v_target);
+ BM_CHECK_ELEMENT(v_src);
+ BM_CHECK_ELEMENT(v_dst);
- /* v is unused now, and can be killed */
- BM_vert_kill(bm, v);
+ /* 'v_src' is unused now, and can be killed */
+ BM_vert_kill(bm, v_src);
return true;
}
+
+/** \name BM_vert_separate, bmesh_vert_separate and friends
+ * \{ */
+
+/* BM_edge_face_count(e) >= 1 */
+BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e)
+{
+ return (e->l && e->l->radial_next != e->l);
+}
+
/**
* \brief Separate Vert
*
@@ -2074,167 +2075,252 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
*
* \return Success
*/
-void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- const bool copy_select)
+void bmesh_vert_separate(
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+ const bool copy_select)
{
- const int v_edgetot = BM_vert_face_count(v);
- BMEdge **stack = BLI_array_alloca(stack, v_edgetot);
- STACK_DECLARE(stack);
+ int v_edges_num = 0;
- SmallHash visithash;
- BMVert **verts = NULL;
- BMIter eiter, liter;
- BMLoop *l;
- BMEdge *e;
- int i, maxindex;
- BMLoop *l_new;
+ /* Detailed notes on array use since this is stack memory, we have to be careful */
- BLI_smallhash_init_ex(&visithash, v_edgetot);
+ /* newly created vertices, only use when 'r_vout' is set
+ * (total size will be number of fans) */
+ BLI_SMALLSTACK_DECLARE(verts_new, BMVert *);
+ /* fill with edges from the face-fan, clearing on completion
+ * (total size will be max fan edge count) */
+ BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
+ /* temp store edges to walk over when filling 'edges',
+ * (total size will be max radial edges of any edge) */
+ BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *);
- STACK_INIT(stack, v_edgetot);
+ /* number of resulting verts, include self */
+ int verts_num = 1;
+ /* track the total number of edges handled, so we know when we've found the last fan */
+ int edges_found = 0;
- maxindex = 0;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BLI_smallhash_haskey(&visithash, (uintptr_t)e)) {
- continue;
- }
+#define EDGE_VISIT _FLAG_WALK
+
+ /* count and flag at once */
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v->e;
+ do {
+ v_edges_num += 1;
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT);
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+
+ while (true) {
/* Considering only edges and faces incident on vertex v, walk
- * the edges & faces and assign an index to each connected set */
- BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex));
+ * the edges & collect in the 'edges' list for splitting */
+
+ BMEdge *e = v->e;
+ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+
do {
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
+ BLI_SMALLSTACK_PUSH(edges, e);
+ edges_found += 1;
+
if (e->l) {
BMLoop *l_iter, *l_first;
l_iter = l_first = e->l;
do {
- l_new = (l_iter->v == v) ? l_iter->prev : l_iter->next;
- BLI_assert(BM_vert_in_edge(l_new->e, v));
- if (!BLI_smallhash_haskey(&visithash, (uintptr_t)l_new->e)) {
- BLI_smallhash_insert(&visithash, (uintptr_t)l_new->e, SET_INT_IN_POINTER(maxindex));
- STACK_PUSH(stack, l_new->e);
+ BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next;
+ BLI_assert(BM_vert_in_edge(l_adjacent->e, v));
+ if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) {
+ BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT);
+ BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e);
}
} while ((l_iter = l_iter->radial_next) != l_first);
}
- } while ((e = STACK_POP(stack)));
+ } while ((e = BLI_SMALLSTACK_POP(edges_search)));
- maxindex++;
- }
+ /* now we have all edges connected to 'v->e' */
- /* Make enough verts to split v for each group */
- if (r_vout != NULL) {
- verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__);
- }
- else {
- verts = BLI_array_alloca(verts, maxindex);
- }
+ BLI_assert(edges_found <= v_edges_num);
- verts[0] = v;
- for (i = 1; i < maxindex; i++) {
- verts[i] = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
- if (copy_select) {
- BM_elem_select_copy(bm, bm, verts[i], v);
- }
- }
-
- /* Replace v with the new verts in each group */
-#if 0
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- /* call first since its faster then a hash lookup */
- if (l->v != v) {
- continue;
- }
- i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e));
- if (i == 0) {
- continue;
+ if (edges_found == v_edges_num) {
+ /* We're done! The remaining edges in 'edges' form the last fan,
+ * which can be left as is.
+ * if 'edges' were alloc'd it'd be freed here. */
+ break;
}
+ else {
+ BMVert *v_new;
- /* Loops here should always refer to an edge that has v as an
- * endpoint. For each appearance of this vert in a face, there
- * will actually be two iterations: one for the loop heading
- * towards vertex v, and another for the loop heading out from
- * vertex v. Only need to swap the vertex on one of those times,
- * on the outgoing loop. */
+ v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
+ if (copy_select) {
+ BM_elem_select_copy(bm, bm, v_new, v);
+ }
- /* XXX - because this clobbers the iterator, this *whole* block is commented, see below */
- l->v = verts[i];
- }
-#else
- /* note: this is the same as the commented code above *except* that it doesn't break iterator
- * by modifying data it loops over [#30632], this re-uses the 'stack' variable which is a bit
- * bad practice but save alloc'ing a new array - note, the comment above is useful, keep it
- * if you are tidying up code - campbell */
- STACK_INIT(stack, v_edgetot);
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (l->v == v) {
- STACK_PUSH(stack, (BMEdge *)l);
- }
- }
- while ((l = (BMLoop *)(STACK_POP(stack)))) {
- if ((i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)l->e)))) {
- l->v = verts[i];
- }
- }
-#endif
+ while ((e = BLI_SMALLSTACK_POP(edges))) {
+ bmesh_edge_vert_swap(e, v_new, v);
+ }
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)e));
- if (i == 0) {
- continue;
+ if (r_vout) {
+ BLI_SMALLSTACK_PUSH(verts_new, v_new);
+ }
+ verts_num += 1;
}
-
- BLI_assert(e->v1 == v || e->v2 == v);
- bmesh_disk_edge_remove(e, v);
- bmesh_edge_swapverts(e, v, verts[i]);
- bmesh_disk_edge_append(e, verts[i]);
}
- BLI_smallhash_release(&visithash);
+#undef EDGE_VISIT
- for (i = 0; i < maxindex; i++) {
- BM_CHECK_ELEMENT(verts[i]);
- }
+ /* flags are clean now, handle return values */
if (r_vout_len != NULL) {
- *r_vout_len = maxindex;
+ *r_vout_len = verts_num;
}
if (r_vout != NULL) {
+ BMVert **verts;
+
+ verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__);
*r_vout = verts;
+
+ verts[0] = v;
+ BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]);
}
}
/**
+ * Utility function for #BM_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.
+ *
+ * \param edges_seperate
+ * A list-of-lists, each list is from a single original edge (the first edge is the original),
+ * Check for duplicates (not just with the first) but between all.
+ * This is O(n2) but radial edges are very rarely >2 and almost never >~10.
+ *
+ * \note typically its best to avoid createing the data in the first place,
+ * but inspecting all loops connectivity is quite involved.
+ *
+ * \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)
+{
+ do {
+ LinkNode *n_orig = edges_separate->link;
+ do {
+ BMEdge *e_orig = n_orig->link;
+ LinkNode *n_step = n_orig->next;
+ LinkNode *n_prev = n_orig;
+ 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);
+ n_prev->next = n_step->next;
+ n_step = n_prev;
+ }
+ } 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
*/
-void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- BMEdge **e_in, int e_in_len)
+void BM_vert_separate(
+ BMesh *bm, BMVert *v,
+ BMEdge **e_in, int e_in_len,
+ const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len)
{
+ LinkNode *edges_separate = NULL;
int i;
for (i = 0; i < e_in_len; i++) {
BMEdge *e = e_in[i];
- if (e->l && BM_vert_in_edge(e, v)) {
- bmesh_edge_separate(bm, e, e->l, false);
+ if (bm_edge_supports_separate(e)) {
+ LinkNode *edges_orig = NULL;
+ do {
+ BMLoop *l_sep = e->l;
+ bmesh_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));
+ BLI_linklist_prepend_alloca(&edges_orig, e);
+ BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
}
}
- bmesh_vert_separate(bm, v, r_vout, r_vout_len, false);
+ bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+
+ if (edges_separate) {
+ bmesh_vert_separate__cleanup(bm, edges_separate);
+ }
}
+
+/**
+ * A version of #BM_vert_separate which takes a flag.
+ */
+void BM_vert_separate_hflag(
+ BMesh *bm, BMVert *v,
+ const char hflag,
+ const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len)
+{
+ LinkNode *edges_separate = NULL;
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
+ do {
+ if (BM_elem_flag_test(e_iter, hflag)) {
+ BMEdge *e = e_iter;
+ if (bm_edge_supports_separate(e)) {
+ LinkNode *edges_orig = NULL;
+ do {
+ BMLoop *l_sep = e->l;
+ bmesh_edge_separate(bm, e, l_sep, copy_select);
+ /* trick to avoid looping over seperated edges */
+ if (edges_separate == NULL && edges_orig == NULL) {
+ e_first = l_sep->e;
+ }
+ BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
+ BLI_assert(e != l_sep->e);
+ } while (bm_edge_supports_separate(e));
+ BLI_linklist_prepend_alloca(&edges_orig, e);
+ BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
+
+ bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+
+ if (edges_separate) {
+ bmesh_vert_separate__cleanup(bm, edges_separate);
+ }
+}
+
+/** \} */
+
+
/**
* \brief Splice Edge
*
* Splice two unique edges which share the same two vertices into one edge.
+ * (\a e_src into \a e_dst, removing e_src).
*
* \return Success
*
* \note Edges must already have the same vertices.
*/
-bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
+bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
{
BMLoop *l;
- if (!BM_vert_in_edge(e, e_target->v1) || !BM_vert_in_edge(e, e_target->v2)) {
+ if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) {
/* not the same vertices can't splice */
/* the caller should really make sure this doesn't happen ever
@@ -2244,21 +2330,21 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
return false;
}
- while (e->l) {
- l = e->l;
- BLI_assert(BM_vert_in_edge(e_target, l->v));
- BLI_assert(BM_vert_in_edge(e_target, l->next->v));
- bmesh_radial_loop_remove(l, e);
- bmesh_radial_append(e_target, l);
+ while (e_src->l) {
+ l = e_src->l;
+ BLI_assert(BM_vert_in_edge(e_dst, l->v));
+ BLI_assert(BM_vert_in_edge(e_dst, l->next->v));
+ bmesh_radial_loop_remove(l, e_src);
+ bmesh_radial_append(e_dst, l);
}
- BLI_assert(bmesh_radial_length(e->l) == 0);
+ BLI_assert(bmesh_radial_length(e_src->l) == 0);
- BM_CHECK_ELEMENT(e);
- BM_CHECK_ELEMENT(e_target);
+ BM_CHECK_ELEMENT(e_src);
+ BM_CHECK_ELEMENT(e_dst);
/* removes from disks too */
- BM_edge_kill(bm, e);
+ BM_edge_kill(bm, e_src);
return true;
}
@@ -2274,8 +2360,9 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
* \note Does nothing if \a l_sep is already the only loop in the
* edge radial.
*/
-void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
- const bool copy_select)
+void bmesh_edge_separate(
+ BMesh *bm, BMEdge *e, BMLoop *l_sep,
+ const bool copy_select)
{
BMEdge *e_new;
#ifndef NDEBUG
@@ -2286,7 +2373,7 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
BLI_assert(e->l);
if (BM_edge_is_boundary(e)) {
- /* no cut required */
+ BLI_assert(0); /* no cut required */
return;
}
@@ -2319,72 +2406,245 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
*/
BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
{
- BMVert **vtar;
- int len, i;
BMVert *v_new = NULL;
BMVert *v_sep = l_sep->v;
+ BMEdge *e_iter;
+ BMEdge *edges[2];
+ int i;
/* peel the face from the edge radials on both sides of the
* loop vert, disconnecting the face from its fan */
bmesh_edge_separate(bm, l_sep->e, l_sep, false);
bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
- if (bmesh_disk_count(v_sep) == 2) {
- /* If there are still only two edges out of v_sep, then
- * this whole URMV was just a no-op, so exit now. */
+ /* do inline, below */
+#if 0
+ if (BM_vert_edge_count_is_equal(v_sep, 2)) {
return v_sep;
}
+#endif
- /* Update the disk start, so that v->e points to an edge
- * not touching the split loop. This is so that BM_vert_split
- * will leave the original v_sep on some *other* fan (not the
- * one-face fan that holds the unglue face). */
- while (v_sep->e == l_sep->e || v_sep->e == l_sep->prev->e) {
- v_sep->e = bmesh_disk_edge_next(v_sep->e, v_sep);
+ /* Search for an edge unattached to this loop */
+ e_iter = v_sep->e;
+ while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) {
+ e_iter = bmesh_disk_edge_next(e_iter, v_sep);
+
+ /* We've come back around to the initial edge, all touch this loop.
+ * If there are still only two edges out of v_sep,
+ * then this whole URMV was just a no-op, so exit now. */
+ if (e_iter == v_sep->e) {
+ BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2));
+ return v_sep;
+ }
}
- /* Split all fans connected to the vert, duplicating it for
- * each fans. */
- bmesh_vert_separate(bm, v_sep, &vtar, &len, false);
+ v_sep->e = l_sep->e;
- /* There should have been at least two fans cut apart here,
- * otherwise the early exit would have kicked in. */
- BLI_assert(len >= 2);
+ v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
- v_new = l_sep->v;
+ edges[0] = l_sep->e;
+ edges[1] = l_sep->prev->e;
- /* Desired result here is that a new vert should always be
- * created for the unglue face. This is so we can glue any
- * extras back into the original vert. */
- BLI_assert(v_new != v_sep);
- BLI_assert(v_sep == vtar[0]);
+ for (i = 0; i < ARRAY_SIZE(edges); i++) {
+ BMEdge *e = edges[i];
+ bmesh_edge_vert_swap(e, v_new, v_sep);
+ }
- /* If there are more than two verts as a result, glue together
- * all the verts except the one this URMV intended to create */
- if (len > 2) {
- for (i = 0; i < len; i++) {
- if (vtar[i] == v_new) {
- break;
+ BLI_assert(v_sep != l_sep->v);
+ BLI_assert(v_sep->e != l_sep->v->e);
+
+ BM_CHECK_ELEMENT(l_sep);
+ BM_CHECK_ELEMENT(v_sep);
+ BM_CHECK_ELEMENT(edges[0]);
+ BM_CHECK_ELEMENT(edges[1]);
+ BM_CHECK_ELEMENT(v_new);
+
+ return v_new;
+}
+
+/**
+ * A version of #bmesh_urmv_loop that disconnects multiple loops at once.
+ *
+ * Handles the task of finding fans boundaris.
+ */
+BMVert *bmesh_urmv_loop_multi(
+ BMesh *bm, BMLoop **larr, int larr_len)
+{
+ BMVert *v_sep = larr[0]->v;
+ BMVert *v_new;
+ int i;
+ bool is_mixed_any = false;
+
+ BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
+
+#define LOOP_VISIT _FLAG_WALK
+#define EDGE_VISIT _FLAG_WALK
+
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ /* all must be from the same vert! */
+ BLI_assert(v_sep == l_sep->v);
+
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT);
+
+ /* weak! but it makes it simpler to check for edges to split
+ * while doing a radial loop (where loops may be adjacent) */
+ BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT);
+ BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT);
+ }
+
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ BMLoop *loop_pair[2] = {l_sep, l_sep->prev};
+ int j;
+ for (j = 0; j < ARRAY_SIZE(loop_pair); j++) {
+ BMEdge *e = loop_pair[j]->e;
+ if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) {
+ BMLoop *l_iter, *l_first;
+ bool is_mixed = false;
+
+ BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
+
+ l_iter = l_first = e->l;
+ do {
+ if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ is_mixed = true;
+ is_mixed_any = true;
+ break;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+
+ if (is_mixed) {
+ /* ensure the first loop is one we don't own so we can do a quick check below
+ * on the edge's loop-flag to see if the edge is mixed or not. */
+ e->l = l_iter;
+ }
+ BLI_SMALLSTACK_PUSH(edges, e);
}
}
+ }
- if (i != len) {
- /* Swap the single vert that was needed for the
- * unglue into the last array slot */
- SWAP(BMVert *, vtar[i], vtar[len - 1]);
+ if (is_mixed_any == false) {
+ /* all loops in 'larr' are the soul owners of their edges.
+ * nothing to split away from, this is a no-op */
+ v_new = v_sep;
+ }
+ else {
+ BMEdge *e;
+
+ BLI_assert(!BLI_SMALLSTACK_IS_EMPTY(edges));
+
+ v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
+ while ((e = BLI_SMALLSTACK_POP(edges))) {
+ BMLoop *l_iter, *l_first, *l_next;
+ BMEdge *e_new;
+
+ /* disable so copied edge isn't left dirty (loop edges are cleared last too) */
+ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+
+ if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) {
+ /* edge has some loops owned by us, some owned by other loops */
+ BMVert *e_new_v_pair[2];
+
+ if (e->v1 == v_sep) {
+ e_new_v_pair[0] = v_new;
+ e_new_v_pair[1] = e->v2;
+ }
+ else {
+ BLI_assert(v_sep == e->v2);
+ e_new_v_pair[0] = e->v1;
+ e_new_v_pair[1] = v_new;
+ }
+
+ e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP);
- /* And then glue the rest back together */
- for (i = 1; i < len - 1; i++) {
- BM_vert_splice(bm, vtar[i], vtar[0]);
+ /* now moved all loops from 'larr' to this newly created edge */
+ l_iter = l_first = e->l;
+ do {
+ l_next = l_iter->radial_next;
+ if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ bmesh_radial_loop_remove(l_iter, e);
+ bmesh_radial_append(e_new, l_iter);
+ l_iter->e = e_new;
+ }
+ } while ((l_iter = l_next) != l_first);
}
+ else {
+ /* we own the edge entirely, replace the vert */
+ bmesh_disk_vert_replace(e, v_new, v_sep);
+ }
+
+ /* loop vert is handled last! */
}
}
- MEM_freeN(vtar);
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ l_sep->v = v_new;
+
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT));
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT));
+ BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT);
+
+
+ BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT);
+ }
+
+#undef LOOP_VISIT
+#undef EDGE_VISIT
return v_new;
}
+static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_src)
+{
+ BMLoop *l_iter, *l_first;
+
+ BLI_assert(ELEM(v_src, e->v1, e->v2));
+ bmesh_disk_vert_replace(e, v_dst, v_src);
+
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v_src) {
+ l_iter->v = v_dst;
+ if (BM_vert_in_edge(l_iter->prev->e, v_src)) {
+ bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src);
+ }
+ }
+ else if (l_iter->next->v == v_src) {
+ l_iter->next->v = v_dst;
+ if (BM_vert_in_edge(l_iter->next->e, v_src)) {
+ bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src);
+ }
+ }
+ else {
+ BLI_assert(l_iter->prev->v != v_src);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+}
+
+/**
+ * This function assumes l_sep is apart of a larger fan which has already been
+ * isolated by calling bmesh_edge_separate to segragate it radially.
+ */
+BMVert *bmesh_urmv_loop_region(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 */
+ bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v);
+ BLI_assert(l_sep->v == v_new);
+ return v_new;
+}
+
+
/**
* \brief Unglue Region Make Vert (URMV)
*
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index ab847fc82eb..2b100eb7b8d 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -27,8 +27,9 @@
* \ingroup bmesh
*/
-BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f,
- const bool copy_verts, const bool copy_edges);
+BMFace *BM_face_copy(
+ BMesh *bm_dst, BMesh *bm_src, BMFace *f,
+ const bool copy_verts, const bool copy_edges);
typedef enum eBMCreateFlag {
BM_CREATE_NOP = 0,
@@ -40,15 +41,19 @@ typedef enum eBMCreateFlag {
BM_CREATE_SKIP_CD = (1 << 2),
} eBMCreateFlag;
-BMVert *BM_vert_create(BMesh *bm, const float co[3],
- const BMVert *v_example, const eBMCreateFlag create_flag);
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
- const BMEdge *e_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create_verts(BMesh *bm, BMVert **verts, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool create_edges);
+BMVert *BM_vert_create(
+ BMesh *bm, const float co[3],
+ const BMVert *v_example, const eBMCreateFlag create_flag);
+BMEdge *BM_edge_create(
+ BMesh *bm, BMVert *v1, BMVert *v2,
+ const BMEdge *e_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create(
+ BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_verts(
+ BMesh *bm, BMVert **verts, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool create_edges);
void BM_face_edges_kill(BMesh *bm, BMFace *f);
void BM_face_verts_kill(BMesh *bm, BMFace *f);
@@ -57,25 +62,32 @@ 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, BMEdge *e_target);
-bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target);
+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_vert_separate(
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+ const bool copy_select);
bool bmesh_loop_reverse(BMesh *bm, BMFace *f);
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del);
-void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- BMEdge **e_in, int e_in_len);
+void BM_vert_separate(
+ BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len);
+void BM_vert_separate_hflag(
+ BMesh *bm, BMVert *v, const char hflag, const bool copy_select,
+ BMVert ***r_vout, int *r_vout_len);
/* EULER API - For modifying structure */
-BMFace *bmesh_sfme(BMesh *bm, BMFace *f,
- BMLoop *l1, BMLoop *l2,
- BMLoop **r_l,
+BMFace *bmesh_sfme(
+ BMesh *bm, BMFace *f,
+ BMLoop *l1, BMLoop *l2,
+ BMLoop **r_l,
#ifdef USE_BMESH_HOLES
ListBase *holes,
#endif
@@ -84,11 +96,15 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f,
);
BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
-BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_splice);
+BMEdge *bmesh_jekv(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool check_edge_splice);
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);
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index aa1f511e8d7..eaa070151a6 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -52,8 +52,9 @@ typedef struct BMEdgeLoopStore {
/* -------------------------------------------------------------------- */
/* BM_mesh_edgeloops_find & Util Functions */
-static int bm_vert_other_tag(BMVert *v, BMVert *v_prev,
- BMEdge **r_e)
+static int bm_vert_other_tag(
+ BMVert *v, BMVert *v_prev,
+ BMEdge **r_e)
{
BMIter iter;
BMEdge *e, *e_next = NULL;
@@ -125,8 +126,9 @@ static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v,
/**
* \return listbase of listbases, each linking to a vertex.
*/
-int BM_mesh_edgeloops_find(BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data)
+int BM_mesh_edgeloops_find(
+ BMesh *bm, ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data)
{
BMIter iter;
BMEdge *e;
@@ -183,8 +185,9 @@ struct VertStep {
BMVert *v;
};
-static void vs_add(BLI_mempool *vs_pool, ListBase *lb,
- BMVert *v, BMEdge *e_prev, const int iter_tot)
+static void vs_add(
+ BLI_mempool *vs_pool, ListBase *lb,
+ BMVert *v, BMEdge *e_prev, const int iter_tot)
{
struct VertStep *vs_new = BLI_mempool_alloc(vs_pool);
vs_new->v = v;
@@ -256,9 +259,10 @@ static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const in
return (BLI_listbase_is_empty(lb) == false);
}
-bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
- BMVert *v_src, BMVert *v_dst)
+bool BM_mesh_edgeloops_find_path(
+ BMesh *bm, ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
+ BMVert *v_src, BMVert *v_dst)
{
BMIter iter;
BMEdge *e;
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h
index 527dba120e1..5df4ee5848e 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.h
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.h
@@ -32,17 +32,20 @@ struct ListBase;
struct BMEdgeLoopStore;
/* multiple edgeloops (ListBase) */
-int BM_mesh_edgeloops_find(BMesh *bm, struct ListBase *r_lb,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data);
-bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
- BMVert *v_src, BMVert *v_dst);
+int BM_mesh_edgeloops_find(
+ BMesh *bm, struct ListBase *r_lb,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data);
+bool BM_mesh_edgeloops_find_path(
+ BMesh *bm, ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
+ BMVert *v_src, BMVert *v_dst);
void BM_mesh_edgeloops_free(struct ListBase *eloops);
void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops);
void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops);
-void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, struct ListBase *eloops,
- const float no_align[3]);
+void BM_mesh_edgeloops_calc_normal_aligned(
+ BMesh *bm, struct ListBase *eloops,
+ const float no_align[3]);
void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals);
@@ -59,8 +62,9 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store);
void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr);
void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store);
bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store);
-bool BM_edgeloop_calc_normal_aligned(BMesh *bm, struct BMEdgeLoopStore *el_store,
- const float no_align[3]);
+bool BM_edgeloop_calc_normal_aligned(
+ BMesh *bm, struct BMEdgeLoopStore *el_store,
+ const float no_align[3]);
void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store);
void BM_edgeloop_expand(BMesh *bm, struct BMEdgeLoopStore *el_store, int el_store_len);
diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h
index 96b2cd396a2..4b55060875b 100644
--- a/source/blender/bmesh/intern/bmesh_inline.h
+++ b/source/blender/bmesh/intern/bmesh_inline.h
@@ -39,11 +39,13 @@
#define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head)
#define BM_elem_flag_merge_into(ele, ele_a, ele_b)_bm_elem_flag_merge_into (&(ele)->head, &(ele_a)->head, &(ele_b)->head)
+ATTR_WARN_UNUSED_RESULT
BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag)
{
return head->hflag & hflag;
}
+ATTR_WARN_UNUSED_RESULT
BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag)
{
return (head->hflag & hflag) != 0;
@@ -116,6 +118,7 @@ BLI_INLINE void _bm_elem_index_set(BMHeader *head, const int index)
head->index = index;
}
+ATTR_WARN_UNUSED_RESULT
BLI_INLINE int _bm_elem_index_get(const BMHeader *head)
{
return head->index;
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 4ca0da53af6..e53e8ec0e4d 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -241,8 +241,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con
* y
* </pre>
*/
-static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3],
- float e1[3], float e2[3])
+static int compute_mdisp_quad(
+ BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3],
+ float e1[3], float e2[3])
{
float cent[3], n[3], p[3];
@@ -302,9 +303,10 @@ static float quad_coord(const float aa[3], const float bb[3], const float cc[3],
return f1;
}
-static int quad_co(float *x, float *y,
- const float v1[3], const float v2[3], const float v3[3], const float v4[3],
- const float p[3], const float n[3])
+static int quad_co(
+ float *r_x, float *r_y,
+ const float v1[3], const float v2[3], const float v3[3], const float v4[3],
+ const float p[3], const float n[3])
{
float projverts[5][3], n2[3];
float dprojverts[4][3], origin[3] = {0.0f, 0.0f, 0.0f};
@@ -340,14 +342,15 @@ static int quad_co(float *x, float *y,
return 0;
}
- *y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1);
- *x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1);
+ *r_y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1);
+ *r_x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1);
return 1;
}
-static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3],
- float axis_x[3], float axis_y[3])
+static void mdisp_axis_from_quad(
+ float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3],
+ float axis_x[3], float axis_y[3])
{
sub_v3_v3v3(axis_x, v4, v1);
sub_v3_v3v3(axis_y, v2, v1);
@@ -358,8 +361,9 @@ static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]),
/* tl is loop to project onto, l is loop whose internal displacement, co, is being
* projected. x and y are location in loop's mdisps grid of point co. */
-static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float *y,
- int res, float axis_x[3], float axis_y[3])
+static bool mdisp_in_mdispquad(
+ BMLoop *l, BMLoop *tl, float p[3], float *x, float *y,
+ int res, float axis_x[3], float axis_y[3])
{
float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
float eps = FLT_EPSILON * 4000;
@@ -392,8 +396,9 @@ static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, floa
return 1;
}
-static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3],
- const float coord[3], int i, int j)
+static float bm_loop_flip_equotion(
+ float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3],
+ const float coord[3], int i, int j)
{
mat[0][0] = target_axis_x[i];
mat[0][1] = target_axis_y[i];
@@ -405,8 +410,9 @@ static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float targ
return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
}
-static void bm_loop_flip_disp(const float source_axis_x[3], const float source_axis_y[3],
- const float target_axis_x[3], const float target_axis_y[3], float disp[3])
+static void bm_loop_flip_disp(
+ const float source_axis_x[3], const float source_axis_y[3],
+ const float target_axis_x[3], const float target_axis_y[3], float disp[3])
{
float vx[3], vy[3], coord[3];
float n[3], vec[3];
@@ -453,8 +459,8 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
/* if no disps data allocate a new grid, the size of the first grid in f_src. */
if (!md_dst->totdisp) {
- MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
-
+ const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
+
md_dst->totdisp = md_src->totdisp;
md_dst->level = md_src->level;
if (md_dst->totdisp) {
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 4dc27d75a55..0abf41709a0 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -136,8 +136,9 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons
*
* Sometimes its convenient to get the iterator as an array.
*/
-int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- void **array, const int len)
+int BMO_iter_as_array(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ void **array, const int len)
{
int i = 0;
@@ -169,9 +170,10 @@ int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam
*
* Caller needs to free the array.
*/
-void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size)
+void *BM_iter_as_arrayN(
+ BMesh *bm, const char itype, void *data, int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array, int stack_array_size)
{
BMIter iter;
@@ -212,10 +214,11 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
}
}
-void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size)
+void *BMO_iter_as_arrayN(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array, int stack_array_size)
{
BMOIter iter;
BMElem *ele;
@@ -273,8 +276,9 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons
*
* Counts how many flagged / unflagged items are found in this element.
*/
-int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data,
- const short oflag, const bool value)
+int BMO_iter_elem_count_flag(
+ BMesh *bm, const char itype, void *data,
+ const short oflag, const bool value)
{
BMIter iter;
BMElemF *ele;
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 49e511bdcb5..c4b184ef8b8 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -197,14 +197,17 @@ typedef struct BMIter {
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT;
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
-void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
- void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT;
-int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- void **array, const int len);
-void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size);
+void *BM_iter_as_arrayN(
+ BMesh *bm, const char itype, void *data, int *r_len,
+ void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT;
+int BMO_iter_as_array(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ void **array, const int len);
+void *BMO_iter_as_arrayN(
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
+ int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array, int stack_array_size);
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value);
int BM_iter_mesh_count(const char itype, BMesh *bm);
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index d46c14bf423..43b054d7845 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -39,6 +39,7 @@
*
* Calls an iterators step function to return the next element.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BM_iter_step(BMIter *iter)
{
return iter->step(iter);
@@ -51,6 +52,7 @@ BLI_INLINE void *BM_iter_step(BMIter *iter)
* it with the appropriate function pointers based
* upon its type.
*/
+ATTR_NONNULL(1)
BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
{
/* int argtype; */
@@ -170,6 +172,7 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da
* to return the first element of the iterator.
*
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data)
{
if (LIKELY(BM_iter_init(iter, bm, itype, data))) {
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 8aa64906019..a735f3955fc 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -626,8 +626,9 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode)
/**
* counts number of elements with flag enabled/disabled
*/
-static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool test_for_enabled)
+static int bm_mesh_flag_count(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool test_for_enabled)
{
BMElem *ele;
BMIter iter;
@@ -1013,8 +1014,9 @@ GHash *BM_select_history_map_create(BMesh *bm)
return map;
}
-void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test)
+void BM_mesh_elem_hflag_disable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -1084,8 +1086,9 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl
}
}
-void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test)
+void BM_mesh_elem_hflag_enable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -1139,15 +1142,17 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla
}
}
-void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide)
+void BM_mesh_elem_hflag_disable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide)
{
/* call with 0 hflag_test */
BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0);
}
-void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide)
+void BM_mesh_elem_hflag_enable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide)
{
/* call with 0 hflag_test */
BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0);
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 15f972c6435..0d86567c06e 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -43,15 +43,19 @@ void BM_face_hide_set(BMFace *f, const bool hide);
/* Selection code */
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select);
-void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test);
-void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test);
-
-void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide);
-void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag,
- const bool respecthide);
+void BM_mesh_elem_hflag_enable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test);
+void BM_mesh_elem_hflag_disable_test(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide, const bool overwrite, const char hflag_test);
+
+void BM_mesh_elem_hflag_enable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide);
+void BM_mesh_elem_hflag_disable_all(
+ BMesh *bm, const char htype, const char hflag,
+ const bool respecthide);
/* individual element select functions, BM_elem_select_set is a shortcut for these
* that automatically detects which one to use*/
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 9a2869b64ef..2a6c98bce2e 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -303,8 +303,9 @@ static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const flo
bm->elem_index_dirty &= ~BM_EDGE;
}
-static void bm_mesh_verts_calc_normals(BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3],
- const float (*vcos)[3], float (*vnos)[3])
+static void bm_mesh_verts_calc_normals(
+ BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3],
+ const float (*vcos)[3], float (*vnos)[3])
{
BM_mesh_elem_index_ensure(bm, (vnos) ? (BM_EDGE | BM_VERT) : BM_EDGE);
@@ -437,8 +438,9 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*
/**
* Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos
*/
-static void bm_mesh_edges_sharp_tag(BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle,
- float (*r_lnos)[3])
+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;
@@ -1131,8 +1133,9 @@ finally:
* These functions ensure its correct and are called more often in debug mode.
*/
-void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func,
- const char *msg_a, const char *msg_b)
+void BM_mesh_elem_index_validate(
+ BMesh *bm, const char *location, const char *func,
+ const char *msg_a, const char *msg_b)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -1379,6 +1382,41 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index)
return BLI_mempool_findelem(bm->fpool, index);
}
+/**
+ * Use lookup table when available, else use slower find functions.
+ *
+ * \note Try to use #BM_mesh_elem_table_ensure instead.
+ */
+BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index)
+{
+ if ((bm->elem_table_dirty & BM_VERT) == 0) {
+ return (index < bm->totvert) ? bm->vtable[index] : NULL;
+ }
+ else {
+ return BM_vert_at_index_find(bm, index);
+ }
+}
+
+BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index)
+{
+ if ((bm->elem_table_dirty & BM_EDGE) == 0) {
+ return (index < bm->totedge) ? bm->etable[index] : NULL;
+ }
+ else {
+ return BM_edge_at_index_find(bm, index);
+ }
+}
+
+BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index)
+{
+ if ((bm->elem_table_dirty & BM_FACE) == 0) {
+ return (index < bm->totface) ? bm->ftable[index] : NULL;
+ }
+ else {
+ return BM_face_at_index_find(bm, index);
+ }
+}
+
/**
* Return the amount of element of type 'type' in a given bmesh.
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index bac5da8347e..b157237c7d0 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -49,8 +49,9 @@ void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag);
-void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func,
- const char *msg_a, const char *msg_b);
+void BM_mesh_elem_index_validate(
+ BMesh *bm, const char *location, const char *func,
+ const char *msg_a, const char *msg_b);
#ifndef NDEBUG
bool BM_mesh_elem_table_check(BMesh *bm);
@@ -68,6 +69,10 @@ BMVert *BM_vert_at_index_find(BMesh *bm, const int index);
BMEdge *BM_edge_at_index_find(BMesh *bm, const int index);
BMFace *BM_face_at_index_find(BMesh *bm, const int index);
+BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index);
+BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index);
+BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index);
+
// XXX
int BM_mesh_elem_count(BMesh *bm, const char htype);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 98521137816..a0ef12c28db 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -203,8 +203,9 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm)
}
/* Static function for alloc (duplicate in modifiers_bmesh.c) */
-static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
- BMesh *bm, BMVert **vtable, BMEdge **etable)
+static BMFace *bm_face_create_from_mpoly(
+ MPoly *mp, MLoop *ml,
+ BMesh *bm, BMVert **vtable, BMEdge **etable)
{
BMVert **verts = BLI_array_alloca(verts, mp->totloop);
BMEdge **edges = BLI_array_alloca(edges, mp->totloop);
@@ -224,8 +225,9 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml,
*
* \warning This function doesn't calculate face normals.
*/
-void BM_mesh_bm_from_me(BMesh *bm, Mesh *me,
- const bool calc_face_normal, const bool set_key, int act_key_nr)
+void BM_mesh_bm_from_me(
+ BMesh *bm, Mesh *me,
+ const bool calc_face_normal, const bool set_key, int act_key_nr)
{
BM_mesh_bm_from_me_ex(bm, me, CD_MASK_BMESH, calc_face_normal, set_key, act_key_nr);
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h
index f910c696fb6..0d235a128ab 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h
@@ -42,8 +42,9 @@ void BM_mesh_cd_flag_ensure(BMesh *bm, struct Mesh *mesh, const char cd_flag);
void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag);
char BM_mesh_cd_flag_from_bmesh(BMesh *bm);
-void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me,
- const bool calc_face_normal, const bool set_key, int act_key_nr);
+void BM_mesh_bm_from_me(
+ BMesh *bm, struct Mesh *me,
+ const bool calc_face_normal, const bool set_key, int act_key_nr);
void BM_mesh_bm_from_me_ex(BMesh *bm, struct Mesh *me, CustomDataMask mask,
const bool calc_face_normal, const bool set_key, int act_key_nr);
void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, bool do_tessface);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c
index 494da3b889b..478194735f3 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_validate.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c
@@ -195,7 +195,7 @@ bool BM_mesh_validate(BMesh *bm)
ERRMSG("Finished - errors %d", errtot);
- return true;
+ return (errtot == 0);
}
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 85e9ec3aa24..5891876c22c 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -276,10 +276,11 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f_a, BMFace *f_b, BMEdge *e, const
* if the split is successful (and the original original face will be the
* other side). NULL if the split fails.
*/
-BMFace *BM_face_split(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- BMLoop **r_l, BMEdge *example,
- const bool no_double)
+BMFace *BM_face_split(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ BMLoop **r_l, BMEdge *example,
+ const bool no_double)
{
const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS);
BMFace *f_new, *f_tmp;
@@ -357,10 +358,11 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f,
* if the split is successful (and the original original face will be the
* other side). NULL if the split fails.
*/
-BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- float cos[][3], int n,
- BMLoop **r_l, BMEdge *example)
+BMFace *BM_face_split_n(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ float cos[][3], int n,
+ BMLoop **r_l, BMEdge *example)
{
BMFace *f_new, *f_tmp;
BMLoop *l_dummy;
@@ -991,8 +993,9 @@ bool BM_face_split_edgenet(
*
* \returns The New Edge
*/
-BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
- const bool do_del, const bool join_faces, const bool kill_degenerate_faces)
+BMEdge *BM_vert_collapse_faces(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
+ const bool do_del, const bool join_faces, const bool kill_degenerate_faces)
{
BMEdge *e_new = NULL;
BMVert *tv = BM_edge_other_vert(e_kill, v_kill);
@@ -1104,8 +1107,9 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float
*
* \return The New Edge
*/
-BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces)
+BMEdge *BM_vert_collapse_edge(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool kill_degenerate_faces)
{
/* nice example implementation but we want loops to have their customdata
* accounted for */
@@ -1354,8 +1358,9 @@ bool BM_face_validate(BMFace *face, FILE *err)
*
* \note #BM_edge_rotate_check must have already run.
*/
-void BM_edge_calc_rotate(BMEdge *e, const bool ccw,
- BMLoop **r_l1, BMLoop **r_l2)
+void BM_edge_calc_rotate(
+ BMEdge *e, const bool ccw,
+ BMLoop **r_l1, BMLoop **r_l2)
{
BMVert *v1, *v2;
BMFace *fa, *fb;
@@ -1517,8 +1522,9 @@ bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
return true;
}
-bool BM_edge_rotate_check_beauty(BMEdge *e,
- BMLoop *l1, BMLoop *l2)
+bool BM_edge_rotate_check_beauty(
+ BMEdge *e,
+ BMLoop *l1, BMLoop *l2)
{
/* Stupid check for now:
* Could compare angles of surrounding edges
@@ -1644,3 +1650,9 @@ BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl)
{
return bmesh_urmv_loop(bm, sl);
}
+
+BMVert *BM_face_loop_separate_multi(
+ BMesh *bm, BMLoop **larr, int larr_len)
+{
+ return bmesh_urmv_loop_multi(bm, larr, larr_len);
+}
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 59aee323bba..1b826b1e0b2 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -35,24 +35,29 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v);
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del);
-BMFace *BM_face_split(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- BMLoop **r_l,
- BMEdge *example, const bool no_double);
-
-BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- float cos[][3], int n,
- BMLoop **r_l, BMEdge *example);
-
-bool BM_face_split_edgenet(BMesh *bm, BMFace *f,
- BMEdge **edge_net, const int edge_net_len,
- BMFace ***r_face_arr, int *r_face_arr_len);
-
-BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
- const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
-BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces);
+BMFace *BM_face_split(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ BMLoop **r_l,
+ BMEdge *example, const bool no_double);
+
+BMFace *BM_face_split_n(
+ BMesh *bm, BMFace *f,
+ BMLoop *l_a, BMLoop *l_b,
+ float cos[][3], int n,
+BMLoop **r_l, BMEdge *example);
+
+bool BM_face_split_edgenet(
+ BMesh *bm, BMFace *f,
+ BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len);
+
+BMEdge *BM_vert_collapse_faces(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
+ const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
+BMEdge *BM_vert_collapse_edge(
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool do_del, const bool kill_degenerate_faces);
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent);
@@ -61,13 +66,16 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr);
bool BM_face_validate(BMFace *face, FILE *err);
-void BM_edge_calc_rotate(BMEdge *e, const bool ccw,
- BMLoop **r_l1, BMLoop **r_l2);
+void BM_edge_calc_rotate(
+ BMEdge *e, const bool ccw,
+ BMLoop **r_l1, BMLoop **r_l2);
bool BM_edge_rotate_check(BMEdge *e);
-bool BM_edge_rotate_check_degenerate(BMEdge *e,
- BMLoop *l1, BMLoop *l2);
-bool BM_edge_rotate_check_beauty(BMEdge *e,
- BMLoop *l1, BMLoop *l2);
+bool BM_edge_rotate_check_degenerate(
+ BMEdge *e,
+ BMLoop *l1, BMLoop *l2);
+bool BM_edge_rotate_check_beauty(
+ BMEdge *e,
+ BMLoop *l1, BMLoop *l2);
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag);
/* flags for BM_edge_rotate */
@@ -81,5 +89,7 @@ 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);
#endif /* __BMESH_MODS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index d0679b9919a..2ba65f5a1e7 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -359,6 +359,7 @@ static BMOpDefine bmo_collapse_def = {
"collapse",
/* slots_in */
{{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */
{{'\0'}},
},
{{{'\0'}}}, /* no output */
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 33a956b652f..96f954f8ee7 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -273,9 +273,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
(op_dst)->slots_dst, slot_name_dst, \
(op_dst)->arena)
-void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- struct MemArena *arena_dst);
+void _bmo_slot_copy(
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ struct MemArena *arena_dst);
/* del "context" slot values, used for operator too */
enum {
@@ -335,11 +336,12 @@ void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
-void BMO_mesh_selected_remap(BMesh *bm,
- BMOpSlot *slot_vert_map,
- BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map,
- const bool check_select);
+void BMO_mesh_selected_remap(
+ BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map,
+ const bool check_select);
/* copies the values from another slot to the end of the output slot */
#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
@@ -347,53 +349,62 @@ void BMO_mesh_selected_remap(BMesh *bm,
_bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \
(op_dst)->slots_dst, slot_name_dst, \
(op_dst)->arena)
-void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- struct MemArena *arena_dst);
+void _bmo_slot_buffer_append(
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ struct MemArena *arena_dst);
/* puts every element of type 'type' (which is a bitmask) with tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_from_enabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* puts every element of type 'type' (which is a bitmask) without tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_from_disabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_flag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_flag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_flag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_flag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_hflag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush);
+void BMO_slot_buffer_hflag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_hflag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush);
+void BMO_slot_buffer_hflag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush);
/* puts every element of type 'type' (which is a bitmask) with header
* flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
-void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag);
+void BMO_slot_buffer_from_enabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag);
/* puts every element of type 'type' (which is a bitmask) without
* header flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
-void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag);
+void BMO_slot_buffer_from_disabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag);
void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len);
@@ -405,19 +416,23 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot);
int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data);
+void BMO_slot_map_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, const void *data);
/* flags all elements in a mapping. note that the mapping must only have
* bmesh elements in it.*/
-void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char hflag, const short oflag);
+void BMO_slot_map_to_flag(
+ BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char hflag, const short oflag);
-void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const int len);
+void *BMO_slot_buffer_alloc(
+ BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const int len);
-void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char htype);
+void BMO_slot_buffer_from_all(
+ BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char htype);
/**
* This part of the API is used to iterate over element buffer or
@@ -466,9 +481,10 @@ typedef struct BMOIter {
void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void *BMO_iter_new(BMOIter *iter,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char restrictmask);
+void *BMO_iter_new(
+ BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char restrictmask);
void *BMO_iter_step(BMOIter *iter);
void **BMO_iter_map_value_p(BMOIter *iter);
diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
index 2b78b775723..4f995e08b9c 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
@@ -38,55 +38,67 @@
* ghash or a mapping slot to do it. */
/* flags 15 and 16 (1 << 14 and 1 << 15) are reserved for bmesh api use */
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
return oflags[bm->stackdepth - 1].f & oflag;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
return (oflags[bm->stackdepth - 1].f & oflag) != 0;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
oflags[bm->stackdepth - 1].f |= oflag;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
oflags[bm->stackdepth - 1].f &= (short)~oflag;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val)
{
if (val) oflags[bm->stackdepth - 1].f |= oflag;
else oflags[bm->stackdepth - 1].f &= (short)~oflag;
}
+ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
oflags[bm->stackdepth - 1].f ^= oflag;
}
-BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot,
- void *element, const int val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_int_insert(
+ BMOperator *op, BMOpSlot *slot,
+ void *element, const int val)
{
union { void *ptr; int val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr));
}
-BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot,
- void *element, const bool val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_bool_insert(
+ BMOperator *op, BMOpSlot *slot,
+ void *element, const bool val)
{
union { void *ptr; bool val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr));
}
-BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot,
- void *element, const float val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_float_insert(
+ BMOperator *op, BMOpSlot *slot,
+ void *element, const float val)
{
union { void *ptr; float val; } t = {NULL};
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
@@ -99,15 +111,19 @@ BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot,
* do NOT use these for non-operator-api-allocated memory! instead
* use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */
-BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, void *val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_ptr_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, void *val)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
BMO_slot_map_insert(op, slot, element, val);
}
-BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, void *val)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_elem_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, void *val)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
BMO_slot_map_insert(op, slot, element, val);
@@ -115,25 +131,30 @@ BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot,
/* no values */
-BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot,
- const void *element)
+ATTR_NONNULL(1, 2)
+BLI_INLINE void BMO_slot_map_empty_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY);
BMO_slot_map_insert(op, slot, element, NULL);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element)
{
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
return BLI_ghash_haskey(slot->data.ghash, element);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
{
return BLI_ghash_lookup_p(slot->data.ghash, element);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
{
void **data;
@@ -148,6 +169,7 @@ BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
}
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
{
void **data;
@@ -162,6 +184,7 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
}
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
{
void **data;
@@ -176,6 +199,7 @@ BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
}
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
{
void **val = BMO_slot_map_data_get(slot, element);
@@ -185,6 +209,7 @@ BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
return NULL;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element)
{
void **val = (void **) BMO_slot_map_data_get(slot, element);
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index ba154b04838..dda1f2fe30a 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -281,9 +281,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
* define used.
* Copies data from one slot to another.
*/
-void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- struct MemArena *arena_dst)
+void _bmo_slot_copy(
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ struct MemArena *arena_dst)
{
BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
@@ -543,8 +544,9 @@ void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam
*
*/
-static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag,
- const bool test_for_enabled)
+static int bmo_mesh_flag_count(
+ BMesh *bm, const char htype, const short oflag,
+ const bool test_for_enabled)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -602,11 +604,12 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
}
}
-void BMO_mesh_selected_remap(BMesh *bm,
- BMOpSlot *slot_vert_map,
- BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map,
- const bool check_select)
+void BMO_mesh_selected_remap(
+ BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map,
+ const bool check_select)
{
if (bm->selected.first) {
BMEditSelection *ese, *ese_next;
@@ -663,8 +666,9 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
/* inserts a key/value mapping into a mapping slot. note that it copies the
* value, it doesn't store a reference to it. */
-void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data)
+void BMO_slot_map_insert(
+ BMOperator *op, BMOpSlot *slot,
+ const void *element, const void *data)
{
(void) op; /* Ignored in release builds. */
@@ -717,8 +721,9 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd)
}
#endif
-void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_map_to_flag(
+ BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
GHashIterator gh_iter;
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
@@ -759,8 +764,9 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS]
*
* Copies all elements of a certain type into an operator slot.
*/
-void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char htype)
+void BMO_slot_buffer_from_all(
+ BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char htype)
{
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
@@ -809,9 +815,10 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_
* Copies elements of a certain type, which have a certain header flag
* enabled/disabled into a slot for an operator.
*/
-static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag,
- const bool test_for_enabled)
+static void bmo_slot_buffer_from_hflag(
+ BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag,
+ const bool test_for_enabled)
{
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
@@ -872,16 +879,18 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_
}
}
-void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag)
+void BMO_slot_buffer_from_enabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag)
{
bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true);
}
-void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag)
+void BMO_slot_buffer_from_disabled_hflag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag)
{
bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false);
}
@@ -927,9 +936,10 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot)
/**
* Copies the values from another slot to the end of the output slot.
*/
-void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- struct MemArena *arena_dst)
+void _bmo_slot_buffer_append(
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ struct MemArena *arena_dst)
{
BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
@@ -964,10 +974,11 @@ void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const cha
* Copies elements of a certain type, which have a certain flag set
* into an output slot for an operator.
*/
-static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag,
- const bool test_for_enabled)
+static void bmo_slot_buffer_from_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag,
+ const bool test_for_enabled)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
int totelement, i = 0;
@@ -1026,16 +1037,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op,
}
}
-void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_from_enabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true);
}
-void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_from_disabled_flag(
+ BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
}
@@ -1046,9 +1059,10 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
* Header Flags elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush)
+void BMO_slot_buffer_hflag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMElem **data = (BMElem **)slot->data.buf;
@@ -1082,9 +1096,10 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm,
* Removes flags from elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush)
+void BMO_slot_buffer_hflag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const char hflag, const bool do_flush)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMElem **data = (BMElem **)slot->data.buf;
@@ -1116,9 +1131,10 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm,
*
* Flags elements in a slots buffer
*/
-void BMO_slot_buffer_flag_enable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_flag_enable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMHeader **data = slot->data.p;
@@ -1140,9 +1156,10 @@ void BMO_slot_buffer_flag_enable(BMesh *bm,
*
* Removes flags from elements in a slots buffer
*/
-void BMO_slot_buffer_flag_disable(BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_flag_disable(
+ BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char htype, const short oflag)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMHeader **data = (BMHeader **)slot->data.buf;
@@ -1394,9 +1411,10 @@ void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char
* \param restrictmask restricts the iteration to certain element types
* (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
* over an element buffer (not a mapping). */
-void *BMO_iter_new(BMOIter *iter,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char restrictmask)
+void *BMO_iter_new(
+ BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char restrictmask)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index f39fe29b596..d9961e589da 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -46,6 +46,7 @@ enum {
SUBD_FALLOFF_ROOT,
SUBD_FALLOFF_SHARP,
SUBD_FALLOFF_LIN,
+ SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */
};
enum {
@@ -130,14 +131,15 @@ extern const BMOpDefine *bmo_opdefines[];
extern const int bmo_opdefines_total;
/*------specific operator helper functions-------*/
-void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
- const float smooth, const short smooth_falloff, const bool use_smooth_even,
- const float fractal, const float along_normal,
- const int numcuts,
- const int seltype, const int cornertype,
- const short use_single_edge, const short use_grid_fill,
- const short use_only_quads,
- const int seed);
+void BM_mesh_esubdivide(
+ BMesh *bm, const char edge_hflag,
+ const float smooth, const short smooth_falloff, const bool use_smooth_even,
+ const float fractal, const float along_normal,
+ const int numcuts,
+ const int seltype, const int cornertype,
+ const short use_single_edge, const short use_grid_fill,
+ const short use_only_quads,
+ const int seed);
#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 bc06ba2c9b1..d2d31d6a562 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -102,8 +102,9 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
* Same as #calc_poly_normal and #bm_face_calc_poly_normal
* but takes an array of vertex locations.
*/
-static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3],
- float const (*vertexCos)[3])
+static float bm_face_calc_poly_normal_vertex_cos(
+ BMFace *f, float r_no[3],
+ float const (*vertexCos)[3])
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter = l_first;
@@ -127,8 +128,9 @@ static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3],
/**
* \brief COMPUTE POLY CENTER (BMFace)
*/
-static void bm_face_calc_poly_center_mean_vertex_cos(BMFace *f, float r_cent[3],
- float const (*vertexCos)[3])
+static void bm_face_calc_poly_center_mean_vertex_cos(
+ BMFace *f, float r_cent[3],
+ float const (*vertexCos)[3])
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_iter = l_first;
@@ -548,8 +550,9 @@ void BM_face_normal_update(BMFace *f)
}
/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
-float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3],
- float const (*vertexCos)[3])
+float BM_face_calc_normal_vcos(
+ BMesh *bm, BMFace *f, float r_no[3],
+ float const (*vertexCos)[3])
{
BMLoop *l;
@@ -607,8 +610,9 @@ float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3])
}
/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
-void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3],
- float const (*vertexCos)[3])
+void BM_face_calc_center_mean_vcos(
+ BMesh *bm, BMFace *f, float r_cent[3],
+ float const (*vertexCos)[3])
{
/* must have valid index data */
BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 9980b59a298..582b4248c7d 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -36,16 +36,18 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_loopt
void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]);
float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
-float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3],
- float const (*vertexCos)[3]) ATTR_NONNULL();
+float BM_face_calc_normal_vcos(
+ BMesh *bm, BMFace *f, float r_no[3],
+ float const (*vertexCos)[3]) ATTR_NONNULL();
float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) ATTR_NONNULL();
float BM_face_calc_area(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_face_calc_perimeter(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_face_calc_plane(BMFace *f, float r_plane[3]) ATTR_NONNULL();
void BM_face_calc_center_bounds(BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_calc_center_mean(BMFace *f, float center[3]) ATTR_NONNULL();
-void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3],
- float const (*vertexCos)[3]) ATTR_NONNULL();
+void BM_face_calc_center_mean_vcos(
+ BMesh *bm, BMFace *f, float r_cent[3],
+ float const (*vertexCos)[3]) ATTR_NONNULL();
void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 4d3dd580ab3..031fc68e66f 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -501,10 +501,10 @@ bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
/**
* Returns whether or not a given edge is part of a given face.
*/
-bool BM_edge_in_face(BMEdge *e, BMFace *f)
+bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
{
if (e->l) {
- BMLoop *l_iter, *l_first;
+ const BMLoop *l_iter, *l_first;
l_iter = l_first = e->l;
do {
@@ -861,9 +861,9 @@ bool BM_vert_is_wire(const BMVert *v)
*/
bool BM_vert_is_manifold(const BMVert *v)
{
- BMEdge *e, *e_old;
- BMLoop *l;
- int len, count, flag;
+ BMEdge *e_iter, *e_first, *e_prev;
+ BMLoop *l_iter, *l_first;
+ int loop_num = 0, loop_num_region = 0, boundary_num = 0;
if (v->e == NULL) {
/* loose vert */
@@ -871,51 +871,50 @@ bool BM_vert_is_manifold(const BMVert *v)
}
/* count edges while looking for non-manifold edges */
- len = 0;
- e_old = e = v->e;
+ e_first = e_iter = v->e;
+ l_first = e_iter->l ? e_iter->l : NULL;
do {
/* loose edge or edge shared by more than two faces,
* edges with 1 face user are OK, otherwise we could
* use BM_edge_is_manifold() here */
- if (e->l == NULL || bmesh_radial_length(e->l) > 2) {
+ if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) {
return false;
}
- len++;
- } while ((e = bmesh_disk_edge_next(e, v)) != e_old);
-
- count = 1;
- flag = 1;
- e = NULL;
- e_old = v->e;
- l = e_old->l;
- while (e != e_old) {
- l = (l->v == v) ? l->prev : l->next;
- e = l->e;
- count++; /* count the edges */
-
- if (flag && l->radial_next == l) {
- /* we've hit the edge of an open mesh, reset once */
- flag = 0;
- count = 1;
- e_old = e;
- e = NULL;
- l = e_old->l;
+
+ /* count radial loops */
+ if (e_iter->l->v == v) {
+ loop_num += 1;
}
- else if (l->radial_next == l) {
- /* break the loop */
- e = e_old;
+
+ if (!BM_edge_is_boundary(e_iter)) {
+ /* non boundary check opposite loop */
+ if (e_iter->l->radial_next->v == v) {
+ loop_num += 1;
+ }
}
else {
- l = l->radial_next;
+ /* start at the boundary */
+ l_first = e_iter->l;
+ boundary_num += 1;
+ /* >2 boundaries cant be manifold */
+ if (boundary_num == 3) {
+ return false;
+ }
}
- }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- if (count < len) {
- /* vert shared by multiple regions */
- return false;
- }
+ e_first = l_first->e;
+ l_first = (l_first->v == v) ? l_first : l_first->next;
+ BLI_assert(l_first->v == v);
- return true;
+ l_iter = l_first;
+ e_prev = e_first;
+
+ do {
+ loop_num_region += 1;
+ } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL));
+
+ return (loop_num == loop_num_region);
}
/**
@@ -1184,8 +1183,9 @@ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e)
* \note This is in fact quite a simple check, mainly include this function so the intent is more obvious.
* We know these 2 verts will _always_ make up the loops edge
*/
-void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop)
+void BM_edge_ordered_verts_ex(
+ const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
+ const BMLoop *edge_loop)
{
BLI_assert(edge_loop->e == edge);
(void)edge; /* quiet warning in release build */
@@ -1220,7 +1220,7 @@ bool BM_loop_is_convex(const BMLoop *l)
*
* \return angle in radians
*/
-float BM_loop_calc_face_angle(BMLoop *l)
+float BM_loop_calc_face_angle(const BMLoop *l)
{
return angle_v3v3v3(l->prev->v->co,
l->v->co,
@@ -1235,7 +1235,7 @@ float BM_loop_calc_face_angle(BMLoop *l)
* \param l The loop to calculate the normal at
* \param r_normal Resulting normal
*/
-void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
+void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
{
if (normal_tri_v3(r_normal,
l->prev->v->co,
@@ -1257,7 +1257,7 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
* \param l The loop to calculate the direction at
* \param r_dir Resulting direction
*/
-void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3])
+void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
{
float v_prev[3];
float v_next[3];
@@ -1281,7 +1281,7 @@ void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3])
* \param l The loop to calculate the tangent at
* \param r_tangent Resulting tangent
*/
-void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3])
+void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
{
float v_prev[3];
float v_next[3];
@@ -1393,7 +1393,7 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta
*
* \returns the angle in radians
*/
-float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback)
+float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback)
{
BMEdge *e1, *e2;
@@ -1415,7 +1415,7 @@ float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback)
}
}
-float BM_vert_calc_edge_angle(BMVert *v)
+float BM_vert_calc_edge_angle(const BMVert *v)
{
return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f));
}
@@ -1424,14 +1424,14 @@ float BM_vert_calc_edge_angle(BMVert *v)
* \note this isn't optimal to run on an array of verts,
* see 'solidify_add_thickness' for a function which runs on an array.
*/
-float BM_vert_calc_shell_factor(BMVert *v)
+float BM_vert_calc_shell_factor(const BMVert *v)
{
BMIter iter;
BMLoop *l;
float accum_shell = 0.0f;
float accum_angle = 0.0f;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
const float face_angle = BM_loop_calc_face_angle(l);
accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle;
accum_angle += face_angle;
@@ -1446,15 +1446,15 @@ float BM_vert_calc_shell_factor(BMVert *v)
}
/* alternate version of #BM_vert_calc_shell_factor which only
* uses 'hflag' faces, but falls back to all if none found. */
-float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag)
+float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag)
{
BMIter iter;
- BMLoop *l;
+ const BMLoop *l;
float accum_shell = 0.0f;
float accum_angle = 0.0f;
int tot_sel = 0, tot = 0;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */
const float face_angle = BM_loop_calc_face_angle(l);
accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle;
@@ -1483,15 +1483,15 @@ float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hfla
* \note quite an obscure function.
* used in bmesh operators that have a relative scale options,
*/
-float BM_vert_calc_mean_tagged_edge_length(BMVert *v)
+float BM_vert_calc_mean_tagged_edge_length(const BMVert *v)
{
BMIter iter;
BMEdge *e;
int tot;
float length = 0.0f;
- BM_ITER_ELEM_INDEX (e, &iter, v, BM_EDGES_OF_VERT, tot) {
- BMVert *v_other = BM_edge_other_vert(e, v);
+ BM_ITER_ELEM_INDEX (e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) {
+ const BMVert *v_other = BM_edge_other_vert(e, v);
if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
length += BM_edge_calc_length(e);
}
@@ -2128,9 +2128,10 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed)
* (having both set is supported too).
* \return The number of groups found.
*/
-int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step)
+int BM_mesh_calc_face_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test, const char htype_step)
{
#ifdef DEBUG
int group_index_len = 1;
@@ -2285,9 +2286,10 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde
* \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument,
* since we always walk over verts.
*/
-int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test)
+int BM_mesh_calc_edge_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test)
{
#ifdef DEBUG
int group_index_len = 1;
@@ -2416,6 +2418,9 @@ float bmesh_subd_falloff_calc(const int falloff, float val)
break;
case SUBD_FALLOFF_LIN:
break;
+ case SUBD_FALLOFF_INVSQUARE:
+ val = val * (2.0f - val);
+ break;
default:
BLI_assert(0);
break;
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 6d25d9fbfec..e4f7c78bdc1 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -31,7 +31,7 @@ bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNU
int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_in_face(BMEdge *e, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -96,10 +96,10 @@ BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_W
float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_loop_calc_face_angle(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) ATTR_NONNULL();
-void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]);
-void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]);
+float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
+void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -107,11 +107,11 @@ float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback)
float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL();
-float BM_vert_calc_edge_angle(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_shell_factor(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_mean_tagged_edge_length(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_mean_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -142,8 +142,9 @@ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT AT
BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL();
-void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop) ATTR_NONNULL();
+void BM_edge_ordered_verts_ex(
+ const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
+ const BMLoop *edge_loop) ATTR_NONNULL();
bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -157,12 +158,16 @@ bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNU
float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
-int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+int BM_mesh_calc_face_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test, const char htype_step)
+ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+int BM_mesh_calc_edge_groups(
+ BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
+ BMElemFilterFunc filter_fn, void *user_data,
+ const char hflag_test)
+ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
/* not really any good place to put this */
float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/bmesh/intern/bmesh_queries_inline.h b/source/blender/bmesh/intern/bmesh_queries_inline.h
index 1ca56beb746..430ba10fb42 100644
--- a/source/blender/bmesh/intern/bmesh_queries_inline.h
+++ b/source/blender/bmesh/intern/bmesh_queries_inline.h
@@ -30,6 +30,7 @@
* Returns whether or not a given vertex is
* is part of a given edge.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v)
{
return (ELEM(v, e->v1, e->v2));
@@ -38,6 +39,7 @@ BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v)
/**
* Returns whether or not a given edge is part of a given loop.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l)
{
return (l->e == e || l->prev->e == e);
@@ -47,6 +49,7 @@ BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l)
* Returns whether or not two vertices are in
* a given edge
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3)
BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e)
{
return ((e->v1 == v1 && e->v2 == v2) ||
@@ -57,6 +60,7 @@ BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdg
* Given a edge and one of its vertices, returns
* the other vertex.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v)
{
if (e->v1 == v) {
@@ -72,6 +76,7 @@ BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v)
* Tests whether or not the edge is part of a wire.
* (ie: has no faces attached to it)
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e)
{
return (e->l == NULL);
@@ -83,6 +88,7 @@ BLI_INLINE bool BM_edge_is_wire(const BMEdge *e)
*/
#if 1 /* fast path for checking manifold */
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e)
{
const BMLoop *l = e->l;
@@ -100,6 +106,7 @@ BLI_INLINE int BM_edge_is_manifold(BMEdge *e)
* Tests that the edge is manifold and
* that both its faces point the same way.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e)
{
const BMLoop *l = e->l;
@@ -115,6 +122,7 @@ BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e)
*/
#if 1 /* fast path for checking boundary */
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e)
{
const BMLoop *l = e->l;
@@ -130,6 +138,7 @@ BLI_INLINE int BM_edge_is_boundary(BMEdge *e)
/**
* Tests whether one loop is next to another within the same face.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b)
{
BLI_assert(l_a->f == l_b->f);
@@ -140,6 +149,7 @@ BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b)
/**
* Check if we have a single wire edge user.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v)
{
const BMEdge *e = v->e;
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index cf56c3b4b83..cb302139a4c 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -40,19 +40,56 @@
* MISC utility functions.
*/
-bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new)
+void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
{
- if (e->v1 == v_orig) {
- e->v1 = v_new;
+ if (e->v1 == v_src) {
+ e->v1 = v_dst;
e->v1_disk_link.next = e->v1_disk_link.prev = NULL;
- return true;
}
- else if (e->v2 == v_orig) {
- e->v2 = v_new;
+ else if (e->v2 == v_src) {
+ e->v2 = v_dst;
e->v2_disk_link.next = e->v2_disk_link.prev = NULL;
- return true;
}
- return false;
+ else {
+ BLI_assert(0);
+ }
+}
+
+/**
+ * Handles all connected data, use with care.
+ *
+ * Assumes caller has setup correct state before the swap is done.
+ */
+void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
+{
+ /* swap out loops */
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v_src) {
+ l_iter->v = v_dst;
+ }
+ else if (l_iter->next->v == v_src) {
+ l_iter->next->v = v_dst;
+ }
+ else {
+ BLI_assert(l_iter->prev->v != v_src);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ /* swap out edges */
+ bmesh_disk_vert_replace(e, v_dst, v_src);
+}
+
+void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src)
+{
+ BLI_assert(e->v1 == v_src || e->v2 == v_src);
+ bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */
+ bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */
+ bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */
+ BLI_assert(e->v1 != e->v2);
}
/**
@@ -88,6 +125,7 @@ bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new)
* the disk cycle has no problems dealing with non-manifold conditions involving faces.
*
* Functions relating to this cycle:
+ * - #bmesh_disk_vert_replace
* - #bmesh_disk_edge_append
* - #bmesh_disk_edge_remove
* - #bmesh_disk_edge_next
@@ -228,7 +266,7 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
if (!BM_vert_in_edge(e, v))
return false;
- if (bmesh_disk_count(v) != len || len == 0)
+ if (bmesh_disk_count_ex(v, len + 1) != len || len == 0)
return false;
e_iter = e;
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index 4a6247d7165..07f94796bb2 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -70,7 +70,9 @@ BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_W
bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* EDGE UTILITIES */
-bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) ATTR_NONNULL();
+void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_structure_inline.h b/source/blender/bmesh/intern/bmesh_structure_inline.h
index 5b7e890f5ea..64292194ae7 100644
--- a/source/blender/bmesh/intern/bmesh_structure_inline.h
+++ b/source/blender/bmesh/intern/bmesh_structure_inline.h
@@ -27,6 +27,7 @@
#ifndef __BMESH_STRUCTURE_INLINE_H__
#define __BMESH_STRUCTURE_INLINE_H__
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v)
{
BLI_assert(BM_vert_in_edge(e, v));
@@ -40,6 +41,7 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMV
*
* \return Pointer to the next edge in the disk cycle for the vertex v.
*/
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v)
{
if (v == e->v1)
@@ -49,6 +51,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v)
return NULL;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v)
{
if (v == e->v1)
@@ -58,11 +61,13 @@ BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v)
return NULL;
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v)
{
return BM_DISK_EDGE_NEXT(e, v);
}
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v)
{
return BM_DISK_EDGE_PREV(e, v);
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index 20b56632099..d16eb572540 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -74,10 +74,11 @@ void *BMW_begin(BMWalker *walker, void *start)
* a given type. The elements visited are filtered
* by the bitmask 'searchmask'.
*/
-void BMW_init(BMWalker *walker, BMesh *bm, int type,
- short mask_vert, short mask_edge, short mask_face,
- BMWFlag flag,
- int layer)
+void BMW_init(
+ BMWalker *walker, BMesh *bm, int type,
+ short mask_vert, short mask_edge, short mask_face,
+ BMWFlag flag,
+ int layer)
{
memset(walker, 0, sizeof(BMWalker));
diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h
index d551ea9fba9..e84880dc61e 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.h
+++ b/source/blender/bmesh/intern/bmesh_walkers.h
@@ -76,10 +76,11 @@ typedef struct BMWalker {
/* initialize a walker. searchmask restricts some (not all) walkers to
* elements with a specific tool flag set. flags is specific to each walker.*/
-void BMW_init(struct BMWalker *walker, BMesh *bm, int type,
- short mask_vert, short mask_edge, short mask_face,
- BMWFlag flag,
- int layer);
+void BMW_init(
+ struct BMWalker *walker, BMesh *bm, int type,
+ short mask_vert, short mask_edge, short mask_face,
+ BMWFlag flag,
+ int layer);
void *BMW_begin(BMWalker *walker, void *start);
void *BMW_step(struct BMWalker *walker);
void BMW_end(struct BMWalker *walker);
diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c
index a00f65bd10f..107aead6994 100644
--- a/source/blender/bmesh/operators/bmo_connect_concave.c
+++ b/source/blender/bmesh/operators/bmo_connect_concave.c
@@ -79,8 +79,8 @@ static bool bm_face_split_by_concave(
struct Heap *pf_heap, struct EdgeHash *pf_ehash)
{
const int f_base_len = f_base->len;
- int faces_array_tot = f_base->len - 3;
- int edges_array_tot = f_base->len - 3;
+ int faces_array_tot = f_base_len - 3;
+ int edges_array_tot = f_base_len - 3;
BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot);
const int quad_method = 0, ngon_method = 0; /* beauty */
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index ecb41363761..ac0466a74d2 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -494,7 +494,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
static void bm_mesh_edge_collapse_flagged(BMesh *bm, const int flag, const short oflag)
{
- BMO_op_callf(bm, flag, "collapse edges=%fe", oflag);
+ BMO_op_callf(bm, flag, "collapse edges=%fe uvs=%b", oflag, true);
}
void bmo_dissolve_degenerate_exec(BMesh *bm, BMOperator *op)
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 27e140eb990..3d899bdef28 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -974,7 +974,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
v_glue = v_split;
}
else {
- BM_vert_splice(bm, v_split, v_glue);
+ BM_vert_splice(bm, v_glue, v_split);
}
}
}
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 871bee64c19..73b6268e78b 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -380,8 +380,11 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
float min[3], max[3], center[3];
unsigned int i, tot;
BMOpSlot *slot_targetmap;
-
- BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
+
+ if (BMO_slot_bool_get(op->slots_in, "uvs")) {
+ BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
+ }
+
BMO_op_init(bm, &weldop, op->flag, "weld_verts");
slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 003c27671a5..410da65f828 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -163,10 +163,11 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace
return NULL;
}
/* calculates offset for co, based on fractal, sphere or smooth settings */
-static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc,
- BMVert *vsta, BMVert *vend)
+static void alter_co(
+ BMVert *v, BMEdge *UNUSED(e_orig),
+ const SubDParams *params, const float perc,
+ const BMVert *v_a, const BMVert *v_b)
{
- float tvec[3], fac;
float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
int i;
@@ -178,28 +179,26 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
}
else if (params->use_smooth) {
/* we calculate an offset vector vec1[], to be added to *co */
- float len, nor[3], nor1[3], nor2[3], val;
+ float dir[3], tvec[3];
+ float fac, len, val;
- sub_v3_v3v3(nor, vsta->co, vend->co);
- len = 0.5f * normalize_v3(nor);
-
- copy_v3_v3(nor1, vsta->no);
- copy_v3_v3(nor2, vend->no);
+ sub_v3_v3v3(dir, v_a->co, v_b->co);
+ len = M_SQRT1_2 * normalize_v3(dir);
/* cosine angle */
- fac = dot_v3v3(nor, nor1);
- mul_v3_v3fl(tvec, nor1, fac);
+ fac = dot_v3v3(dir, v_a->no);
+ mul_v3_v3fl(tvec, v_a->no, fac);
/* cosine angle */
- fac = -dot_v3v3(nor, nor2);
- madd_v3_v3fl(tvec, nor2, fac);
+ fac = -dot_v3v3(dir, v_b->no);
+ madd_v3_v3fl(tvec, v_b->no, fac);
/* falloff for multi subdivide */
val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
val = bmesh_subd_falloff_calc(params->smooth_falloff, val);
if (params->use_smooth_even) {
- val *= BM_vert_calc_shell_factor(v);
+ val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
}
mul_v3_fl(tvec, params->smooth * val * len);
@@ -208,12 +207,13 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
}
if (params->use_fractal) {
- const float len = len_v3v3(vsta->co, vend->co);
- float normal[3], co2[3], base1[3], base2[3];
+ float normal[3], co2[3], base1[3], base2[3], tvec[3];
+ const float len = len_v3v3(v_a->co, v_b->co);
+ float fac;
fac = params->fractal * len;
- mid_v3_v3v3(normal, vsta->no, vend->no);
+ mid_v3_v3v3(normal, v_a->no, v_b->no);
ortho_basis_v3v3_v3(base1, base2, normal);
add_v3_v3v3(co2, v->co, params->fractal_ofs);
@@ -234,9 +234,12 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
* this by getting the normals and coords for each shape key and
* re-calculate the smooth value for each but this is quite involved.
* for now its ok to simply apply the difference IMHO - campbell */
- sub_v3_v3v3(tvec, v->co, co);
if (params->shape_info.totlayer > 1) {
+ float tvec[3];
+
+ sub_v3_v3v3(tvec, v->co, co);
+
/* skip the last layer since its the temp */
i = params->shape_info.totlayer - 1;
co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
@@ -250,19 +253,21 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params
/* assumes in the edge is the correct interpolated vertices already */
/* percent defines the interpolation, rad and flag are for special options */
/* results in new vertex with correct coordinate, vertex normal and weight group info */
-static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge,
- const SubDParams *params, float percent,
- float percent2,
- BMEdge **out, BMVert *vsta, BMVert *vend)
+static BMVert *bm_subdivide_edge_addvert(
+ BMesh *bm, BMEdge *edge, BMEdge *e_orig,
+ const SubDParams *params,
+ const float factor_edge_split, const float factor_subd,
+ BMVert *v_a, BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *ev;
+ BMVert *v_new;
- ev = BM_edge_split(bm, edge, edge->v1, out, percent);
+ v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split);
- BMO_elem_flag_enable(bm, ev, ELE_INNER);
+ BMO_elem_flag_enable(bm, v_new, ELE_INNER);
/* offset for smooth or sphere or fractal */
- alter_co(ev, oedge, params, percent2, vsta, vend);
+ alter_co(v_new, e_orig, params, factor_subd, v_a, v_b);
#if 0 //BMESH_TODO
/* clip if needed by mirror modifier */
@@ -279,35 +284,40 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge,
}
#endif
- interp_v3_v3v3(ev->no, vsta->no, vend->no, percent2);
- normalize_v3(ev->no);
+ interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd);
+ normalize_v3(v_new->no);
- return ev;
+ return v_new;
}
-static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
- int curpoint, int totpoint, const SubDParams *params,
- BMEdge **newe, BMVert *vsta, BMVert *vend)
+static BMVert *subdivide_edge_num(
+ BMesh *bm, BMEdge *edge, BMEdge *e_orig,
+ int curpoint, int totpoint, const SubDParams *params,
+ BMVert *v_a, BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *ev;
- float percent, percent2 = 0.0f;
+ BMVert *v_new;
+ float factor_edge_split, factor_subd;
if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) {
- percent = BMO_slot_map_float_get(params->slot_edge_percents, edge);
+ factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge);
+ factor_subd = 0.0f;
}
else {
- percent = 1.0f / (float)(totpoint + 1 - curpoint);
- percent2 = (float)(curpoint + 1) / (float)(totpoint + 1);
-
+ factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint);
+ factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1);
}
- ev = bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
- percent2, newe, vsta, vend);
- return ev;
+ v_new = bm_subdivide_edge_addvert(
+ bm, edge, e_orig, params,
+ factor_edge_split, factor_subd,
+ v_a, v_b, r_edge);
+ return v_new;
}
-static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params,
- BMVert *vsta, BMVert *vend)
+static void bm_subdivide_multicut(
+ BMesh *bm, BMEdge *edge, const SubDParams *params,
+ BMVert *v_a, BMVert *v_b)
{
BMEdge *eed = edge, *e_new, e_tmp = *edge;
BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
@@ -317,7 +327,7 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par
e_tmp.v2 = &v2_tmp;
for (i = 0; i < numcuts; i++) {
- v = subdivideedgenum(bm, eed, &e_tmp, i, params->numcuts, params, &e_new, vsta, vend);
+ v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new);
BMO_elem_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT);
BMO_elem_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT);
@@ -434,7 +444,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert *
e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
e_tmp = *e;
- v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2);
+ v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new);
if (i != numcuts - 1) {
connect_smallest_face(bm, v_last, v, &f_new);
@@ -577,8 +587,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
e_tmp = *e;
for (a = 0; a < numcuts; a++) {
- v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new,
- v1, v2);
+ v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new);
BMESH_ASSERT(v != NULL);
@@ -685,8 +694,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
e_tmp.v1 = &v1_tmp;
e_tmp.v2 = &v2_tmp;
for (j = 0; j < i; j++) {
- v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new,
- verts[a], verts[b]);
+ v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new);
lines[i + 1][j + 1] = v;
BMO_elem_flag_enable(bm, e_new, ELE_INNER);
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index da1991a187d..964d0b1dfc6 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -208,7 +208,7 @@ static void bmo_region_extend_expand(
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_ORIG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
found = true;
break;
}
@@ -221,7 +221,7 @@ static void bmo_region_extend_expand(
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
BMO_elem_flag_enable(bm, e, SEL_FLAG);
BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
}
@@ -232,7 +232,7 @@ static void bmo_region_extend_expand(
BMFace *f;
BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, f, SEL_FLAG)) {
+ if (!BMO_elem_flag_test(bm, f, SEL_FLAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
bmo_face_flag_set_flush(bm, f, SEL_FLAG, true);
}
}
@@ -243,7 +243,7 @@ static void bmo_region_extend_expand(
BMEdge *e;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
if (BM_edge_is_wire(e)) {
- if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
BMO_elem_flag_enable(bm, e, SEL_FLAG);
BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
}
@@ -267,7 +267,9 @@ static void bmo_region_extend_expand(
BMFace *f_other;
BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) {
- if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG)) {
+ if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
+ !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN))
+ {
BMO_elem_flag_enable(bm, f_other, SEL_FLAG);
}
}
@@ -277,7 +279,9 @@ static void bmo_region_extend_expand(
BMFace *f_other;
BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG)) {
+ if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
+ !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN))
+ {
BMO_elem_flag_enable(bm, f_other, SEL_FLAG);
}
}
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index b64c3aab5d7..19fe492c670 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -274,11 +274,12 @@ BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const
}
/* recalc an edge in the heap (surrounding geometry has changed) */
-static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
- /* only for testing the edge is in the array */
- const BMEdge **edge_array, const int edge_array_len,
+static void bm_edge_update_beauty_cost_single(
+ BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
+ /* only for testing the edge is in the array */
+ const BMEdge **edge_array, const int edge_array_len,
- const short flag, const short method)
+ const short flag, const short method)
{
if (edge_in_array(e, edge_array, edge_array_len)) {
const int i = BM_elem_index_get(e);
@@ -316,10 +317,11 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode *
}
/* we have rotated an edge, tag other edges and clear this one */
-static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
- const BMEdge **edge_array, const int edge_array_len,
- /* only for testing the edge is in the array */
- const short flag, const short method)
+static void bm_edge_update_beauty_cost(
+ BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
+ const BMEdge **edge_array, const int edge_array_len,
+ /* only for testing the edge is in the array */
+ const short flag, const short method)
{
int i;
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index a2a0f974a79..252c16e8919 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -244,8 +244,9 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
}
-static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto,
- int ifrom, int jfrom, int kfrom)
+static void copy_mesh_vert(
+ VMesh *vm, int ito, int jto, int kto,
+ int ifrom, int jfrom, int kfrom)
{
NewVert *nvto, *nvfrom;
@@ -361,8 +362,9 @@ static BMFace *boundvert_rep_face(BoundVert *v)
*
* \note ALL face creation goes through this function, this is important to keep!
*/
-static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
- BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp)
+static BMFace *bev_create_ngon(
+ BMesh *bm, BMVert **vert_arr, const int totv,
+ BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp)
{
BMIter iter;
BMLoop *l;
@@ -402,15 +404,17 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv,
return f;
}
-static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *facerep, int mat_nr, bool do_interp)
+static BMFace *bev_create_quad_tri(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ BMFace *facerep, int mat_nr, bool do_interp)
{
BMVert *varr[4] = {v1, v2, v3, v4};
return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, mat_nr, do_interp);
}
-static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr)
+static BMFace *bev_create_quad_tri_ex(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr)
{
BMVert *varr[4] = {v1, v2, v3, v4};
BMFace *farr[4] = {f1, f2, f3, f4};
@@ -419,8 +423,9 @@ static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert
/* Is Loop layer layer_index contiguous across shared vertex of l1 and l2? */
-static bool contig_ldata_across_loops(BMesh *bm, BMLoop *l1, BMLoop *l2,
- int layer_index)
+static bool contig_ldata_across_loops(
+ BMesh *bm, BMLoop *l1, BMLoop *l2,
+ int layer_index)
{
const int offset = bm->ldata.layers[layer_index].offset;
const int type = bm->ldata.layers[layer_index].type;
@@ -478,7 +483,10 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
return true;
}
-/* Like bev_create_quad_tri, but when verts straddle an old edge.
+/**
+ * Like #bev_create_quad_tri, but when verts straddle an old edge.
+ *
+ * <pre>
* e
* |
* v1+---|---+v4
@@ -487,13 +495,16 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f
* v2+---|---+v3
* |
* f1 | f2
+ * </pre>
*
* Most CustomData for loops can be interpolated in their respective
* faces' loops, but for UVs and other 'has_math_cd' layers, only
* do this if the UVs are continuous across the edge e, otherwise pick
* one side (f1, arbitrarily), and interpolate them all on that side.
- * For face data, use f1 (arbitrarily) as face representative. */
-static BMFace *bev_create_quad_straddle(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ * For face data, use f1 (arbitrarily) as face representative.
+ */
+static BMFace *bev_create_quad_straddle(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
BMFace *f1, BMFace *f2, int mat_nr, bool is_seam)
{
BMFace *f, *facerep;
@@ -737,8 +748,9 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc
* already, prefer to keep the offset the same on this end.
* Otherwise, pick a point between the two intersection points on emid that minimizes
* the sum of squares of errors from desired offset. */
-static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
- BMVert *v, float meetco[3])
+static void offset_on_edge_between(
+ BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
+ BMVert *v, float meetco[3])
{
float d, ang1, ang2, sina1, sina2, lambda;
float meet1[3], meet2[3];
@@ -793,8 +805,9 @@ static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2,
* Viewed from the vertex normal side, the CCW order of the edges is e1, emid, e2.
* The offset lines may not meet exactly: the lines may be angled so that they can't meet.
* In that case, pick the offset_on_edge_between. */
-static void offset_in_two_planes(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
- BMVert *v, float meetco[3])
+static void offset_in_two_planes(
+ BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
+ BMVert *v, float meetco[3])
{
float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3],
off1a[3], off1b[3], off2a[3], off2b[3], isect2[3],
@@ -1079,8 +1092,9 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
* and B has the right side as columns - both extended into homogeneous coords.
* So M = B*(Ainverse). Doing Ainverse by hand gives the code below.
*/
-static bool make_unit_square_map(const float va[3], const float vmid[3], const float vb[3],
- float r_mat[4][4])
+static bool make_unit_square_map(
+ const float va[3], const float vmid[3], const float vb[3],
+ float r_mat[4][4])
{
float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3];
@@ -1128,8 +1142,9 @@ static bool make_unit_square_map(const float va[3], const float vmid[3], const f
* and 1/2{va+vb+vc-vd}
* and Blender matrices have cols at m[i][*].
*/
-static void make_unit_cube_map(const float va[3], const float vb[3], const float vc[3],
- const float vd[3], float r_mat[4][4])
+static void make_unit_cube_map(
+ const float va[3], const float vb[3], const float vc[3],
+ const float vd[3], float r_mat[4][4])
{
copy_v3_v3(r_mat[0], va);
sub_v3_v3(r_mat[0], vb);
@@ -1861,9 +1876,10 @@ static void vmesh_center(VMesh *vm, float r_cent[3])
}
}
-static void avg4(float co[3],
- const NewVert *v0, const NewVert *v1,
- const NewVert *v2, const NewVert *v3)
+static void avg4(
+ float co[3],
+ const NewVert *v0, const NewVert *v1,
+ const NewVert *v2, const NewVert *v3)
{
add_v3_v3v3(co, v0->co, v1->co);
add_v3_v3(co, v2->co);
@@ -3755,10 +3771,11 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
*
* \warning all tagged edges _must_ be manifold.
*/
-void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type,
- const float segments, const float profile,
- const bool vertex_only, const bool use_weights, const bool limit_offset,
- const struct MDeformVert *dvert, const int vertex_group, const int mat)
+void BM_mesh_bevel(
+ BMesh *bm, const float offset, const int offset_type,
+ const float segments, const float profile,
+ const bool vertex_only, const bool use_weights, const bool limit_offset,
+ const struct MDeformVert *dvert, const int vertex_group, const int mat)
{
BMIter iter;
BMVert *v, *v_next;
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index 52d8faa5401..b4bb6c56b7d 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -29,9 +29,10 @@
struct MDeformVert;
-void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments,
- const float profile, const bool vertex_only, const bool use_weights,
- const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group,
- const int mat);
+void BM_mesh_bevel(
+ BMesh *bm, const float offset, const int offset_type, const float segments,
+ const float profile, const bool vertex_only, const bool use_weights,
+ const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group,
+ const int mat);
#endif /* __BMESH_BEVEL_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h
index a1b26990587..1efa829c60d 100644
--- a/source/blender/bmesh/tools/bmesh_decimate.h
+++ b/source/blender/bmesh/tools/bmesh_decimate.h
@@ -32,13 +32,15 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c
void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only);
void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations);
-void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len,
- const short oflag_out);
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit);
+void BM_mesh_decimate_dissolve_ex(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit,
+ BMVert **vinput_arr, const int vinput_len,
+ BMEdge **einput_arr, const int einput_len,
+ const short oflag_out);
+void BM_mesh_decimate_dissolve(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit);
/* these weights are accumulated so too high values may reach 'inf' too quickly */
#define BM_MESH_DECIM_WEIGHT_MAX 100000.0f
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 811a144fc39..47c41c44d81 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -112,18 +112,19 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics)
}
-static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3],
- const Quadric *vquadrics)
+static void bm_decim_calc_target_co(
+ BMEdge *e, float optimize_co[3],
+ const Quadric *vquadrics)
{
/* compute an edge contraction target for edge 'e'
* this is computed by summing it's vertices quadrics and
* optimizing the result. */
Quadric q;
- BLI_quadric_add_qu_ququ(&q,
- &vquadrics[BM_elem_index_get(e->v1)],
- &vquadrics[BM_elem_index_get(e->v2)]);
-
+ BLI_quadric_add_qu_ququ(
+ &q,
+ &vquadrics[BM_elem_index_get(e->v1)],
+ &vquadrics[BM_elem_index_get(e->v2)]);
if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) {
return; /* all is good */
@@ -183,9 +184,10 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_
return false;
}
-static void bm_decim_build_edge_cost_single(BMEdge *e,
- const Quadric *vquadrics, const float *vweights,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_build_edge_cost_single(
+ BMEdge *e,
+ const Quadric *vquadrics, const float *vweights,
+ Heap *eheap, HeapNode **eheap_table)
{
const Quadric *q1, *q2;
float optimize_co[3];
@@ -258,16 +260,18 @@ static void bm_decim_build_edge_cost_single(BMEdge *e,
/* use this for degenerate cases - add back to the heap with an invalid cost,
* this way it may be calculated again if surrounding geometry changes */
-static void bm_decim_invalid_edge_cost_single(BMEdge *e,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_invalid_edge_cost_single(
+ BMEdge *e,
+ Heap *eheap, HeapNode **eheap_table)
{
BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL);
eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e);
}
-static void bm_decim_build_edge_cost(BMesh *bm,
- const Quadric *vquadrics, const float *vweights,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_build_edge_cost(
+ BMesh *bm,
+ const Quadric *vquadrics, const float *vweights,
+ Heap *eheap, HeapNode **eheap_table)
{
BMIter iter;
BMEdge *e;
@@ -442,8 +446,9 @@ static void bm_decim_triangulate_end(BMesh *bm)
/**
* \param v is the target to merge into.
*/
-static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other,
- const float customdata_fac)
+static void bm_edge_collapse_loop_customdata(
+ BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other,
+ const float customdata_fac)
{
/* disable seam check - the seam check would have to be done per layer, its not really that important */
//#define USE_SEAM
@@ -698,15 +703,16 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
* \param e_clear_other let caller know what edges we remove besides \a e_clear
* \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other')
*/
-static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
+static bool bm_edge_collapse(
+ BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
#ifdef USE_CUSTOMDATA
- const CD_UseFlag customdata_flag,
- const float customdata_fac
+ const CD_UseFlag customdata_flag,
+ const float customdata_fac
#else
- const CD_UseFlag UNUSED(customdata_flag),
- const float UNUSED(customdata_fac)
+ const CD_UseFlag UNUSED(customdata_flag),
+ const float UNUSED(customdata_fac)
#endif
- )
+ )
{
BMVert *v_other;
@@ -782,12 +788,12 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_
BM_edge_kill(bm, e_clear);
v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_clear, v_other);
+ BM_vert_splice(bm, v_other, v_clear);
e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
- BM_edge_splice(bm, e_b_other[0], e_b_other[1]);
+ BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
+ BM_edge_splice(bm, e_b_other[1], e_b_other[0]);
// BM_mesh_validate(bm);
@@ -831,10 +837,10 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_
BM_edge_kill(bm, e_clear);
v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_clear, v_other);
+ BM_vert_splice(bm, v_other, v_clear);
e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
+ BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
// BM_mesh_validate(bm);
@@ -847,10 +853,11 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_
/* collapse e the edge, removing e->v2 */
-static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
- Quadric *vquadrics, float *vweights,
- Heap *eheap, HeapNode **eheap_table,
- const CD_UseFlag customdata_flag)
+static void bm_decim_edge_collapse(
+ BMesh *bm, BMEdge *e,
+ Quadric *vquadrics, float *vweights,
+ Heap *eheap, HeapNode **eheap_table,
+ const CD_UseFlag customdata_flag)
{
int e_clear_other[2];
BMVert *v_other = e->v1;
diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
index 096349e8e9c..09c7b932b7a 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
@@ -98,11 +98,12 @@ fail:
}
-void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len,
- const short oflag_out)
+void BM_mesh_decimate_dissolve_ex(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit,
+ BMVert **vinput_arr, const int vinput_len,
+ BMEdge **einput_arr, const int einput_len,
+ const short oflag_out)
{
const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len);
void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__);
@@ -316,8 +317,9 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
MEM_freeN(_heap_table);
}
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit)
+void BM_mesh_decimate_dissolve(
+ BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit)
{
int vinput_len;
int einput_len;
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index 1328b81b746..e93ffe6b141 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -450,8 +450,9 @@ static LinkNode *bm_edgenet_path_calc_best(
* \param use_edge_tag Only fill tagged edges.
* \param face_oflag if nonzero, apply all new faces with this bmo flag.
*/
-void BM_mesh_edgenet(BMesh *bm,
- const bool use_edge_tag, const bool use_new_face_tag)
+void BM_mesh_edgenet(
+ BMesh *bm,
+ const bool use_edge_tag, const bool use_new_face_tag)
{
VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__);
BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.h b/source/blender/bmesh/tools/bmesh_edgenet.h
index 327a7f5aa23..1ad5cadae7c 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.h
+++ b/source/blender/bmesh/tools/bmesh_edgenet.h
@@ -27,7 +27,8 @@
* \ingroup bmesh
*/
-void BM_mesh_edgenet(BMesh *bm,
- const bool use_edge_tag, const bool use_new_face_tag);
+void BM_mesh_edgenet(
+ BMesh *bm,
+ const bool use_edge_tag, const bool use_new_face_tag);
#endif /* __BMESH_EDGENET_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
index 947b77675d8..74b1660080b 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.c
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -35,70 +35,16 @@
#include "bmesh_edgesplit.h" /* own include */
-
/**
- * Remove the BM_ELEM_TAG flag for edges we cant split
- *
- * un-tag edges not connected to other tagged edges,
- * unless they are on a boundary
+ * \param use_verts Use flagged verts instead of edges.
+ * \param use_non_manifold Split non-manifold edges (a little slower, must check for doubles).
+ * \param tag_only Only split tagged edges.
+ * \param copy_select Copy selection history.
*/
-static void bm_edgesplit_validate_seams(BMesh *bm)
-{
- BMIter iter;
- BMEdge *e;
-
- unsigned char *vtouch;
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- vtouch = MEM_callocN(sizeof(char) * bm->totvert, __func__);
-
- /* tag all boundary verts so as not to untag an edge which is inbetween only 2 faces [] */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
-
- /* unrelated to flag assignment in this function - since this is the
- * only place we loop over all edges, disable tag */
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
-
- if (e->l == NULL) {
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- else if (BM_edge_is_boundary(e)) {
- unsigned char *vt;
- vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++;
- vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++;
-
- /* while the boundary verts need to be tagged,
- * the edge its self can't be split */
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- }
-
- /* single marked edges unconnected to any other marked edges
- * are illegal, go through and unmark them */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- /* lame, but we don't want the count to exceed 255,
- * so just count to 2, its all we need */
- unsigned char *vt;
- vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++;
- vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++;
- }
- }
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- if (vtouch[BM_elem_index_get(e->v1)] == 1 &&
- vtouch[BM_elem_index_get(e->v2)] == 1)
- {
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- }
- }
-
- MEM_freeN(vtouch);
-}
-
-void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select)
+void BM_mesh_edgesplit(
+ BMesh *bm,
+ const bool use_verts,
+ const bool tag_only, const bool copy_select)
{
BMIter iter;
BMEdge *e;
@@ -142,43 +88,13 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
}
}
- bm_edgesplit_validate_seams(bm);
-
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- /* this flag gets copied so we can be sure duplicate edges get it too (important) */
- BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
-
- /* keep splitting until each loop has its own edge */
- while (!BM_edge_is_boundary(e)) {
- BMLoop *l_sep = e->l;
- bmesh_edge_separate(bm, e, l_sep, copy_select);
- BLI_assert(l_sep->e != e);
-
- if (use_ese) {
- BMEditSelection *ese = BLI_ghash_lookup(ese_gh, e);
- if (UNLIKELY(ese)) {
- BM_select_history_store_after_notest(bm, ese, l_sep->e);
- }
- }
- }
-
BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
}
}
- if (use_verts) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) {
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- }
- if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false) {
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- }
- }
- }
-
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
unsigned int i;
@@ -191,7 +107,7 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
BMVert **vtar;
int vtar_len;
- bmesh_vert_separate(bm, v, &vtar, &vtar_len, copy_select);
+ BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, &vtar, &vtar_len);
/* first value is always in 'v' */
if (vtar_len > 1) {
@@ -208,13 +124,22 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
MEM_freeN(vtar);
}
else {
- bmesh_vert_separate(bm, v, NULL, NULL, copy_select);
+ BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, NULL, NULL);
}
}
}
}
}
+#ifndef NDEBUG
+ /* ensure we don't have any double edges! */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BLI_assert(BM_edge_find_double(e) == NULL);
+ }
+ }
+#endif
+
if (use_ese) {
BLI_ghash_free(ese_gh, NULL, NULL);
}
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h
index bd66f6a9e2f..26040077f43 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.h
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.h
@@ -27,6 +27,9 @@
* \ingroup bmesh
*/
-void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select);
+void BM_mesh_edgesplit(
+ BMesh *bm,
+ const bool use_verts,
+ const bool tag_only, const bool copy_select);
#endif /* __BMESH_EDGESPLIT_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index ceb6ded5a43..fc12bce8563 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -1006,7 +1006,7 @@ bool BM_mesh_intersect(
!BM_vert_splice_check_double(v_prev, vi) &&
!BM_vert_pair_share_face_check(v_prev, vi))
{
- BM_vert_splice(bm, v_prev, vi);
+ BM_vert_splice(bm, vi, v_prev);
}
else {
copy_v3_v3(v_prev->co, vi->co);
@@ -1228,7 +1228,7 @@ bool BM_mesh_intersect(
if (!BM_edge_exists(UNPACK2(splice_ls[i])) &&
!BM_vert_splice_check_double(UNPACK2(splice_ls[i])))
{
- BM_vert_splice(bm, UNPACK2(splice_ls[i]));
+ BM_vert_splice(bm, splice_ls[i][1], splice_ls[i][0]);
}
}
}
@@ -1267,10 +1267,8 @@ bool BM_mesh_intersect(
face_edges_split(bm, f, e_ls_base);
}
}
-#else
- (void)totface_orig;
#endif /* USE_NET */
-
+ (void)totface_orig;
#ifdef USE_SEPARATE
if (use_separate) {
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index 484eea73bbe..72c3bc90599 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -190,14 +190,16 @@ static bool ghashutil_bmelem_indexcmp(const void *a, const void *b)
return (a != b);
}
-static GHash *ghash_bmelem_new_ex(const char *info,
- const unsigned int nentries_reserve)
+static GHash *ghash_bmelem_new_ex(
+ const char *info,
+ const unsigned int 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)
+static GSet *gset_bmelem_new_ex(
+ const char *info,
+ const unsigned int nentries_reserve)
{
return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
}
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.h b/source/blender/bmesh/tools/bmesh_triangulate.h
index 550109ffef9..c6a5e04dfb2 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.h
+++ b/source/blender/bmesh/tools/bmesh_triangulate.h
@@ -30,7 +30,8 @@
#ifndef __BMESH_TRIANGULATE_H__
#define __BMESH_TRIANGULATE_H__
-void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
- BMOperator *op, BMOpSlot *slot_facemap_out);
+void BM_mesh_triangulate(
+ BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only,
+ BMOperator *op, BMOpSlot *slot_facemap_out);
#endif /* __BMESH_TRIANGULATE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c
index 79fea3e5da1..87e571a49aa 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.c
+++ b/source/blender/bmesh/tools/bmesh_wireframe.c
@@ -55,8 +55,9 @@ static BMLoop *bm_edge_tag_faceloop(BMEdge *e)
return NULL;
}
-static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3],
- BMVert **r_va_other, BMVert **r_vb_other)
+static void bm_vert_boundary_tangent(
+ BMVert *v, float r_no[3], float r_no_face[3],
+ BMVert **r_va_other, BMVert **r_vb_other)
{
BMIter iter;
BMEdge *e_iter;
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index b2d9aed579b..ac8ac2b9867 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -150,7 +150,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
if (!instance_controller_created) {
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);
instGeom.add();
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index f15efa89ea6..d3813e2fb7a 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -131,7 +131,7 @@ Object *bc_add_object(Scene *scene, int type, const char *name)
{
Object *ob = BKE_object_add_only_object(G.main, type, name);
- ob->data = BKE_object_obdata_add_from_type(G.main, type);
+ ob->data = BKE_object_obdata_add_from_type(G.main, type, name);
ob->lay = scene->lay;
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index fdd75033aea..572e63a2ced 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -79,7 +79,6 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
int numberOfOutputs = this->getNumberOfOutputSockets();
bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0;
BKE_image_user_frame_calc(imageuser, context.getFramenumber(), 0);
- NodeOperation *combined_operation = NULL;
/* force a load, we assume iuser index will be set OK anyway */
if (image && image->type == IMA_TYPE_MULTILAYER) {
bool is_multilayer_ok = false;
@@ -124,44 +123,40 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
}
}
- if (STREQ(bnodeSocket->identifier, "Alpha")) {
- BLI_assert(combined_operation != NULL);
- NodeOutput *outputSocket = this->getOutputSocket(index);
- SeparateChannelOperation *separate_operation;
- separate_operation = new SeparateChannelOperation();
- separate_operation->setChannel(3);
- converter.addOperation(separate_operation);
- converter.addLink(combined_operation->getOutputSocket(), separate_operation->getInputSocket(0));
- converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket());
- operation = separate_operation;
- }
- else {
- if (rpass) {
- switch (rpass->channels) {
- case 1:
- operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
- rpass->passtype, view, COM_DT_VALUE);
- break;
- /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
- /* XXX any way to detect actual vector images? */
- case 3:
- operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
- rpass->passtype, view, COM_DT_VECTOR);
- break;
- case 4:
- operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
- rpass->passtype, view, COM_DT_COLOR);
- break;
- default:
- /* dummy operation is added below */
- break;
- }
- if (index == 0 && operation) {
- converter.addPreview(operation->getOutputSocket());
- }
- if (STREQ(rpass->chan_id, "RGBA")) {
- combined_operation = operation;
- }
+ if (rpass) {
+ switch (rpass->channels) {
+ case 1:
+ operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
+ rpass->passtype, view, COM_DT_VALUE);
+ break;
+ /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
+ /* XXX any way to detect actual vector images? */
+ case 3:
+ operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
+ rpass->passtype, view, COM_DT_VECTOR);
+ break;
+ case 4:
+ operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
+ rpass->passtype, view, COM_DT_COLOR);
+ break;
+ default:
+ /* dummy operation is added below */
+ break;
+ }
+ 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++;
}
}
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp
index cbf9bb211c1..ce42de7a149 100644
--- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp
@@ -133,6 +133,9 @@ float *BlurBaseOperation::make_dist_fac_inverse(float rad, int size, int falloff
case PROP_SHARP:
val = val * val;
break;
+ case PROP_INVSQUARE:
+ val = val * (2.0f - val);
+ break;
case PROP_LIN:
/* fall-through */
#ifndef NDEBUG
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp
index eacbdf91be2..76f74c144f6 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cpp
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp
@@ -82,7 +82,7 @@ void CompositorOperation::deinitExecution()
RenderResult *rr = RE_AcquireResultWrite(re);
if (rr) {
- RenderView *rv = (RenderView *)BLI_findstring(&rr->views, this->m_viewName, offsetof(RenderView, name));
+ RenderView *rv = RE_RenderViewGetByName(rr, this->m_viewName);
if (rv->rectf != NULL) {
MEM_freeN(rv->rectf);
diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp
index 9bcc6fb2541..e5427589fce 100644
--- a/source/blender/compositor/operations/COM_CropOperation.cpp
+++ b/source/blender/compositor/operations/COM_CropOperation.cpp
@@ -36,27 +36,28 @@ void CropBaseOperation::updateArea()
SocketReader *inputReference = this->getInputSocketReader(0);
float width = inputReference->getWidth();
float height = inputReference->getHeight();
+ NodeTwoXYs local_settings = *this->m_settings;
if (width > 0.0f && height > 0.0f) {
if (this->m_relative) {
- this->m_settings->x1 = width * this->m_settings->fac_x1;
- this->m_settings->x2 = width * this->m_settings->fac_x2;
- this->m_settings->y1 = height * this->m_settings->fac_y1;
- this->m_settings->y2 = height * this->m_settings->fac_y2;
+ local_settings.x1 = width * local_settings.fac_x1;
+ local_settings.x2 = width * local_settings.fac_x2;
+ local_settings.y1 = height * local_settings.fac_y1;
+ local_settings.y2 = height * local_settings.fac_y2;
}
- if (width <= this->m_settings->x1 + 1)
- this->m_settings->x1 = width - 1;
- if (height <= this->m_settings->y1 + 1)
- this->m_settings->y1 = height - 1;
- if (width <= this->m_settings->x2 + 1)
- this->m_settings->x2 = width - 1;
- if (height <= this->m_settings->y2 + 1)
- this->m_settings->y2 = height - 1;
+ if (width <= local_settings.x1 + 1)
+ local_settings.x1 = width - 1;
+ if (height <= local_settings.y1 + 1)
+ local_settings.y1 = height - 1;
+ if (width <= local_settings.x2 + 1)
+ local_settings.x2 = width - 1;
+ if (height <= local_settings.y2 + 1)
+ local_settings.y2 = height - 1;
- this->m_xmax = max(this->m_settings->x1, this->m_settings->x2) + 1;
- this->m_xmin = min(this->m_settings->x1, this->m_settings->x2);
- this->m_ymax = max(this->m_settings->y1, this->m_settings->y2) + 1;
- this->m_ymin = min(this->m_settings->y1, this->m_settings->y2);
+ this->m_xmax = max(local_settings.x1, local_settings.x2) + 1;
+ this->m_xmin = min(local_settings.x1, local_settings.x2);
+ this->m_ymax = max(local_settings.y1, local_settings.y2) + 1;
+ this->m_ymin = min(local_settings.y1, local_settings.y2);
}
else {
this->m_xmax = 0;
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 4828343fa0e..67485248bf1 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -2496,12 +2496,13 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot)
/* ******************* Rename Operator ***************************** */
/* Allow renaming some channels by clicking on them */
-static void rename_anim_channels(bAnimContext *ac, int channel_index)
+static bool rename_anim_channels(bAnimContext *ac, int channel_index)
{
ListBase anim_data = {NULL, NULL};
const bAnimChannelType *acf;
bAnimListElem *ale;
int filter;
+ bool success = false;
/* get the channel that was clicked on */
/* filter channels */
@@ -2516,7 +2517,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
ANIM_animdata_freelist(&anim_data);
- return;
+ return false;
}
/* check that channel can be renamed */
@@ -2536,6 +2537,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
*/
if (ac->ads) {
ac->ads->renameIndex = channel_index + 1;
+ success = true;
}
}
}
@@ -2543,22 +2545,18 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
/* free temp data and tag for refresh */
ANIM_animdata_freelist(&anim_data);
ED_region_tag_redraw(ac->ar);
+ return success;
}
-static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
{
- bAnimContext ac;
ARegion *ar;
View2D *v2d;
int channel_index;
float x, y;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
/* get useful pointers from animation context data */
- ar = ac.ar;
+ ar = ac->ar;
v2d = &ar->v2d;
/* figure out which channel user clicked in
@@ -2566,20 +2564,36 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const
* so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
* ACHANNEL_HEIGHT_HALF.
*/
- UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
- if (ac.datatype == ANIMCONT_NLA) {
- SpaceNla *snla = (SpaceNla *)ac.sl;
+ if (ac->datatype == ANIMCONT_NLA) {
+ SpaceNla *snla = (SpaceNla *)ac->sl;
UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
}
else {
UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
}
-
+
+ return channel_index;
+}
+
+static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ bAnimContext ac;
+ int channel_index;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ channel_index = animchannels_channel_get(&ac, event->mval);
+
/* handle click */
- rename_anim_channels(&ac, channel_index);
-
- return OPERATOR_FINISHED;
+ if (rename_anim_channels(&ac, channel_index))
+ return OPERATOR_FINISHED;
+ else
+ /* allow event to be handled by selectall operator */
+ return OPERATOR_PASS_THROUGH;
}
static void ANIM_OT_channels_rename(wmOperatorType *ot)
@@ -3008,6 +3022,105 @@ static void ANIM_OT_channels_click(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool success = false;
+ FCurve *fcu;
+ int i;
+
+ /* get the channel that was clicked on */
+ /* filter channels */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* get channel from index */
+ ale = BLI_findlink(&anim_data, channel_index);
+ if (ale == NULL) {
+ /* channel not found */
+ if (G.debug & G_DEBUG)
+ printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index);
+
+ ANIM_animdata_freelist(&anim_data);
+ return false;
+ }
+
+ fcu = (FCurve *)ale->key_data;
+ success = (fcu != NULL);
+
+ ANIM_animdata_freelist(&anim_data);
+
+ /* F-Curve may not have any keyframes */
+ if (fcu->bezt) {
+ BezTriple *bezt;
+
+ if (!extend) {
+ filter = (ANIMFILTER_DATA_VISIBLE);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu_inner = (FCurve *)ale->key_data;
+
+ if (fcu_inner) {
+ for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) {
+ bezt->f2 = bezt->f1 = bezt->f3 = 0;
+ }
+ }
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+ }
+
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ bezt->f2 = bezt->f1 = bezt->f3 = SELECT;
+ }
+ }
+
+ /* free temp data and tag for refresh */
+ ED_region_tag_redraw(ac->ar);
+ return success;
+}
+
+static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ bAnimContext ac;
+ int channel_index;
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ channel_index = animchannels_channel_get(&ac, event->mval);
+
+ /* handle click */
+ if (select_anim_channel_keys(&ac, channel_index, extend)) {
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else
+ /* allow event to be handled by selectall operator */
+ return OPERATOR_PASS_THROUGH;
+}
+
+static void ANIM_OT_channel_select_keys(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Channel keyframes";
+ ot->idname = "ANIM_OT_channel_select_keys";
+ ot->description = "Select all keyframes of channel under mouse";
+
+ /* api callbacks */
+ ot->invoke = animchannels_channel_select_keys_invoke;
+ ot->poll = animedit_poll_channels_active;
+
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
/* ************************************************************************** */
/* Operator Registration */
@@ -3017,8 +3130,9 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_select_border);
WM_operatortype_append(ANIM_OT_channels_click);
+ WM_operatortype_append(ANIM_OT_channel_select_keys);
WM_operatortype_append(ANIM_OT_channels_rename);
-
+
WM_operatortype_append(ANIM_OT_channels_find);
WM_operatortype_append(ANIM_OT_channels_setting_enable);
@@ -3058,7 +3172,9 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
/* rename */
WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
-
+ WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, KM_SHIFT, 0)->ptr, "extend", true);
+
/* find (i.e. a shortcut for setting the name filter) */
WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index aa06740ed0e..45663371ae3 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -962,7 +962,7 @@ static void MARKER_OT_move(wmOperatorType *ot)
ot->cancel = ed_marker_move_cancel;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna storage */
RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 47eafcbaed1..2de42933dc0 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -247,7 +247,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->poll = change_frame_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR;
/* rna */
ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 64ced437142..092408d7de5 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1696,7 +1696,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
char *path;
float cfra = (float)CFRA;
short success = 0;
- int a, index, length;
+ int index;
const bool all = RNA_boolean_get(op->ptr, "all");
short flag = 0;
@@ -1715,7 +1715,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
NlaStrip *strip = (NlaStrip *)ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag);
- success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0);
+ success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0);
}
else {
/* standard properties */
@@ -1723,16 +1723,11 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
if (path) {
if (all) {
- length = RNA_property_array_length(&ptr, prop);
-
- if (length) index = 0;
- else length = 1;
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
}
- else
- length = 1;
- for (a = 0; a < length; a++)
- success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag);
+ success = insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, flag);
MEM_freeN(path);
}
@@ -1795,7 +1790,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
char *path;
float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
short success = 0;
- int a, index, length;
+ int index;
const bool all = RNA_boolean_get(op->ptr, "all");
/* try to insert keyframe using property retrieved from UI */
@@ -1806,17 +1801,11 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
if (path) {
if (all) {
- length = RNA_property_array_length(&ptr, prop);
-
- if (length) index = 0;
- else length = 1;
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
}
- else
- length = 1;
-
- for (a = 0; a < length; a++)
- success += delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, 0);
+ success = delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0);
MEM_freeN(path);
}
else if (G.debug & G_DEBUG)
@@ -1865,7 +1854,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = NULL;
char *path;
short success = 0;
- int a, index, length;
+ int index;
const bool all = RNA_boolean_get(op->ptr, "all");
/* try to insert keyframe using property retrieved from UI */
@@ -1876,17 +1865,11 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
if (path) {
if (all) {
- length = RNA_property_array_length(&ptr, prop);
-
- if (length) index = 0;
- else length = 1;
+ /* -1 indicates operating on the entire array (or the property itself otherwise) */
+ index = -1;
}
- else
- length = 1;
-
- for (a = 0; a < length; a++)
- success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0);
+ success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, 0);
MEM_freeN(path);
}
else if (G.debug & G_DEBUG)
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
index 413a74d24b5..4d9df06f33f 100644
--- a/source/blender/editors/armature/pose_group.c
+++ b/source/blender/editors/armature/pose_group.c
@@ -130,6 +130,7 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
{
Object *ob = ED_pose_object_from_context(C);
bPose *pose;
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
uiPopupMenu *pup;
uiLayout *layout;
@@ -140,6 +141,17 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
pose = ob->pose;
+
+ /* If group index is set, try to use it! */
+ if (RNA_property_is_set(op->ptr, prop)) {
+ const int num_groups = BLI_listbase_count(&pose->agroups);
+ const int group = RNA_property_int_get(op->ptr, prop);
+
+ /* just use the active group index, and call the exec callback for the calling operator */
+ if (group > 0 && group <= num_groups) {
+ return op->type->exec(C, op);
+ }
+ }
/* if there's no active group (or active is invalid), create a new menu to find it */
if (pose->active_group <= 0) {
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index 7c53896b969..555a53ae532 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -121,7 +121,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type
const float grid = 1.0f;
const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
const int stype = (type & CU_PRIMITIVE);
- const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */
+ const bool force_3d = (((Curve *)obedit->data)->flag & CU_3D) != 0; /* could be adding to an existing 3D curve */
unit_m4(umat);
unit_m4(viewmat);
@@ -488,9 +488,10 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
if (!isSurf) { /* adding curve */
if (obedit == NULL || obedit->type != OB_CURVE) {
+ const char *name = get_curve_defname(type);
Curve *cu;
- obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer);
+ obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, layer);
newob = true;
cu = (Curve *)obedit->data;
@@ -505,7 +506,8 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
}
else { /* adding surface */
if (obedit == NULL || obedit->type != OB_SURF) {
- obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer);
+ const char *name = get_surf_defname(type);
+ obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, layer);
newob = true;
}
else {
@@ -513,18 +515,6 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
}
}
- /* rename here, the undo stack checks name for valid undo pushes */
- if (newob) {
- if (obedit->type == OB_CURVE) {
- rename_id((ID *)obedit, get_curve_defname(type));
- rename_id((ID *)obedit->data, get_curve_defname(type));
- }
- else {
- rename_id((ID *)obedit, get_surf_defname(type));
- rename_id((ID *)obedit->data, get_surf_defname(type));
- }
- }
-
/* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */
if (newob && enter_editmode)
ED_undo_push(C, "Enter Editmode");
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 4297344e6fe..b67ae228b25 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -526,7 +526,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
int a;
float rot[3] = {0.f, 0.f, 0.f};
- obedit = BKE_object_add(bmain, scene, OB_FONT);
+ obedit = BKE_object_add(bmain, scene, OB_FONT, NULL);
base = scene->basact;
/* seems to assume view align ? TODO - look into this, could be an operator option */
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 0d35d3ce716..ffcd204135f 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -761,7 +761,7 @@ static void gp_draw_strokes_edit(bGPDframe *gpf, int offsx, int offsy, int winx,
{
bGPDstroke *gps;
- const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
+ const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0;
int mask_orig = 0;
/* set up depth masks... */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 778f98d212e..e902f9552b5 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -48,6 +48,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "BKE_tracking.h"
#include "DNA_object_types.h"
@@ -1030,6 +1031,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
/* set current area
* - must verify that region data is 3D-view (and not something else)
*/
+ /* CAUTION: If this is the "toolbar", then this will change on the first stroke */
p->sa = curarea;
p->ar = ar;
@@ -1252,6 +1254,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
/* when drawing in the camera view, in 2D space, set the subrect */
+ p->subrect = NULL;
if (!(p->gpd->flag & GP_DATA_VIEWALIGN)) {
if (p->sa->spacetype == SPACE_VIEW3D) {
View3D *v3d = p->sa->spacedata.first;
@@ -1777,6 +1780,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
else {
/* toolbar invoked - don't start drawing yet... */
/* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
@@ -1814,8 +1818,10 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
if (gp_session_initdata(C, p))
gp_paint_initstroke(p, p->paintmode);
- if (p->status != GP_STATUS_ERROR)
+ if (p->status != GP_STATUS_ERROR) {
p->status = GP_STATUS_PAINTING;
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
return op->customdata;
}
@@ -1831,6 +1837,7 @@ static void gpencil_stroke_end(wmOperator *op)
gp_session_cleanup(p);
p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
p->gpd = NULL;
p->gpl = NULL;
@@ -1856,6 +1863,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* in 3D space.
*/
+ if (p->status == GP_STATUS_IDLING) {
+ ARegion *ar = CTX_wm_region(C);
+ p->ar = ar;
+ }
+
/* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
if (ISKEYBOARD(event->type)) {
if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) {
@@ -1938,29 +1950,88 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
else if (event->val == KM_PRESS) {
- /* Switch paintmode (temporarily if need be) based on which button was used
- * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
+ bool in_bounds = false;
+
+ /* Check if we're outside the bounds of the active region
+ * NOTE: An exception here is that if launched from the toolbar,
+ * whatever region we're now in should become the new region
*/
- if (event->type == LEFTMOUSE) {
- /* restore drawmode to default */
- p->paintmode = RNA_enum_get(op->ptr, "mode");
+ if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) {
+ /* Change to whatever region is now under the mouse */
+ ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y);
+
+ if (G.debug & G_DEBUG) {
+ printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
+ current_region, p->ar, event->x, event->y,
+ p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax);
+ }
+
+ if (current_region) {
+ /* Assume that since we found the cursor in here, it is in bounds
+ * and that this should be the region that we begin drawing in
+ */
+ p->ar = current_region;
+ in_bounds = true;
+ }
+ else {
+ /* Out of bounds, or invalid in some other way */
+ p->status = GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
+ }
}
- else if (event->type == RIGHTMOUSE) {
- /* turn on eraser */
- p->paintmode = GP_PAINTMODE_ERASER;
+ else if (p->ar) {
+ rcti region_rect;
+
+ /* Perform bounds check using */
+ ED_region_visible_rect(p->ar, &region_rect);
+ in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
}
-
- gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
-
- /* not painting, so start stroke (this should be mouse-button down) */
- p = gpencil_stroke_begin(C, op);
-
- if (p->status == GP_STATUS_ERROR) {
+ else {
+ /* No region */
+ p->status = GP_STATUS_ERROR;
estate = OPERATOR_CANCELLED;
+
+ if (G.debug & G_DEBUG)
+ printf("%s: No active region found in GP Paint session data\n", __func__);
+ }
+
+ if (in_bounds) {
+ /* Switch paintmode (temporarily if need be) based on which button was used
+ * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
+ */
+ if (event->type == LEFTMOUSE) {
+ /* restore drawmode to default */
+ p->paintmode = RNA_enum_get(op->ptr, "mode");
+ }
+ else if (event->type == RIGHTMOUSE) {
+ /* turn on eraser */
+ p->paintmode = GP_PAINTMODE_ERASER;
+ }
+
+ gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+
+ /* not painting, so start stroke (this should be mouse-button down) */
+ p = gpencil_stroke_begin(C, op);
+
+ if (p->status == GP_STATUS_ERROR) {
+ estate = OPERATOR_CANCELLED;
+ }
+ }
+ else if (p->status != GP_STATUS_ERROR) {
+ /* User clicked outside bounds of window while idling, so exit paintmode
+ * NOTE: Don't eter this case if an error occurred while finding the
+ * region (as above)
+ */
+ p->status = GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
}
}
else {
p->status = GP_STATUS_IDLING;
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
}
diff --git a/source/blender/editors/hair/hair_edit.c b/source/blender/editors/hair/hair_edit.c
index 67059912e92..a637673369e 100644
--- a/source/blender/editors/hair/hair_edit.c
+++ b/source/blender/editors/hair/hair_edit.c
@@ -270,7 +270,7 @@ void hair_init_viewdata(bContext *C, HairViewData *viewdata)
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- view3d_validate_backbuf(&viewdata->vc);
+ ED_view3d_backbuf_validate(&viewdata->vc);
/* we may need to force an update here by setting the rv3d as dirty
* for now it seems ok, but take care!:
* rv3d->depths->dirty = 1; */
diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h
index 64c16605dec..9a987d7618c 100644
--- a/source/blender/editors/include/ED_buttons.h
+++ b/source/blender/editors/include/ED_buttons.h
@@ -37,4 +37,6 @@ bool ED_texture_context_check_particles(const struct bContext *C);
bool ED_texture_context_check_linestyle(const struct bContext *C);
bool ED_texture_context_check_others(const struct bContext *C);
+void ED_buttons_id_unref(struct SpaceButs *sbuts, const struct ID *id);
+
#endif /* __ED_BUTTONS_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 8fb6fcbd0d7..ea544135d3b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -137,9 +137,27 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2]
short xmin, short ymin, short xmax, short ymax);
bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
-struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist, const bool sel, const bool strict);
-struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist);
-struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist);
+struct BMVert *EDBM_vert_find_nearest_ex(
+ struct ViewContext *vc, float *r_dist,
+ const bool use_select_bias, bool use_cycle);
+struct BMVert *EDBM_vert_find_nearest(
+ struct ViewContext *vc, float *r_dist);
+
+struct BMEdge *EDBM_edge_find_nearest_ex(
+ struct ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ struct BMEdge **r_eed_zbuf);
+struct BMEdge *EDBM_edge_find_nearest(
+ struct ViewContext *vc, float *r_dist);
+
+struct BMFace *EDBM_face_find_nearest_ex(
+ struct ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ struct BMFace **r_efa_zbuf);
+struct BMFace *EDBM_face_find_nearest(
+ struct ViewContext *vc, float *r_dist);
bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index b02ebeb650b..1445308c485 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -103,6 +103,8 @@ void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNod
void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, struct Scene *scene_owner);
+void ED_node_id_unref(struct SpaceNode *snode, const ID *id);
+
/* node_ops.c */
void ED_operatormacros_node(void);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 3b7157bd465..c52174c8f2d 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -138,8 +138,10 @@ bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, c
bool *enter_editmode, unsigned int *layer, bool *is_view_aligned);
struct Object *ED_object_add_type(
- struct bContext *C, int type, const float loc[3], const float rot[3],
- bool enter_editmode, unsigned int layer) ATTR_RETURNS_NONNULL;
+ struct bContext *C,
+ int type, const char *name, const float loc[3], const float rot[3],
+ bool enter_editmode, unsigned int layer)
+ ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
void ED_object_single_users(struct Main *bmain, struct Scene *scene, const bool full, const bool copy_groups);
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h
new file mode 100644
index 00000000000..af4af8e2f5d
--- /dev/null
+++ b/source/blender/editors/include/ED_outliner.h
@@ -0,0 +1,36 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ED_outliner.h
+ * \ingroup editors
+ */
+
+#ifndef __ED_OUTLINER_H__
+#define __ED_OUTLINER_H__
+
+struct ID;
+struct SpaceOops;
+
+/* Used to check whether a given texture context is valid in current context. */
+void ED_outliner_id_unref(struct SpaceOops *so, const struct ID *id);
+
+#endif /* __ED_OUTLINER_H__ */
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index 822dab61a06..e46f4b966c0 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -58,7 +58,7 @@ void ED_undo_paint_push_end(int type);
void ED_image_undo_restore(struct bContext *C, struct ListBase *lb);
void ED_image_undo_free(struct ListBase *lb);
void ED_imapaint_clear_partial_redraw(void);
-void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old);
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
#endif /* __ED_PAINT_H__ */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 90b0b3510bc..7f6679b827b 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -66,6 +66,7 @@ void ED_region_header_init(struct ARegion *ar);
void ED_region_header(const struct bContext *C, struct ARegion *ar);
void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar);
void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float fill_color[4]);
+void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, rctf frame, float zoomx, float zoomy);
void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy);
float ED_region_blend_factor(struct ARegion *ar);
void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
@@ -75,7 +76,6 @@ void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco);
-
/* areas */
void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
void ED_area_exit(struct bContext *C, struct ScrArea *sa);
@@ -85,6 +85,7 @@ void ED_area_tag_redraw(ScrArea *sa);
void ED_area_tag_redraw_regiontype(ScrArea *sa, int type);
void ED_area_tag_refresh(ScrArea *sa);
void ED_area_do_refresh(struct bContext *C, ScrArea *sa);
+void ED_area_azones_update(ScrArea *sa, const int mouse_xy[]);
void ED_area_headerprint(ScrArea *sa, const char *str);
void ED_area_newspace(struct bContext *C, ScrArea *sa, int type);
void ED_area_prevspace(struct bContext *C, ScrArea *sa);
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 356c2f70029..ba5449eefa4 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -42,6 +42,8 @@ void ED_editors_exit(struct bContext *C);
bool ED_editors_flush_edits(const struct bContext *C, bool for_render);
+void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+
/* ************** Undo ************************ */
/* undo.c */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index ff4b8a5b631..be4204e7cb7 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -219,6 +219,7 @@ void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], floa
bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_end[3], const bool do_clip);
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
+void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]);
void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z);
/* end */
@@ -267,12 +268,13 @@ float ED_view3d_radius_to_dist(
void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4]);
/* backbuffer select and draw support */
-void view3d_validate_backbuf(struct ViewContext *vc);
-struct ImBuf *view3d_read_backbuf(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
-unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *dist, short strict,
- void *handle, bool (*indextest)(void *handle, unsigned int index));
-unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y);
+void ED_view3d_backbuf_validate(struct ViewContext *vc);
+struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+unsigned int ED_view3d_backbuf_sample_rect(
+ struct ViewContext *vc, const int mval[2], int size,
+ unsigned int min, unsigned int max, float *r_dist);
+int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
+unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y);
/* draws and does a 4x4 sample */
bool ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
@@ -343,8 +345,6 @@ bool ED_view3d_lock(struct RegionView3D *rv3d);
uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d);
uint64_t ED_view3d_screen_datamask(const struct bScreen *screen);
-bool ED_view3d_view_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
-
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
/* camera lock functions */
@@ -391,4 +391,7 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx,
void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar);
void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa);
+#define V3D_IS_ZBUF(v3d) \
+ (((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->drawtype > OB_WIRE))
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 4ca0be7c80d..1e0cc972ef8 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -483,6 +483,14 @@ bool UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock
void UI_but_execute(const struct bContext *C, uiBut *but);
+bool UI_but_online_manual_id(
+ const uiBut *but,
+ char *r_str, size_t maxlength)
+ ATTR_WARN_UNUSED_RESULT;
+bool UI_but_online_manual_id_from_active(
+ const struct bContext *C,
+ char *r_str, size_t maxlength)
+ ATTR_WARN_UNUSED_RESULT;
/* Buttons
*
@@ -675,6 +683,7 @@ void UI_but_func_drawextra_set(
void *arg1, void *arg2);
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN);
+void UI_but_tooltip_timer_remove(struct bContext *C, uiBut *but);
bool UI_textbutton_activate_rna(const struct bContext *C, struct ARegion *ar,
const void *rna_poin_data, const char *rna_prop_id);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 3923c5c4432..2b19b6180e5 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -294,7 +294,10 @@ enum {
TH_INFO_DEBUG_TEXT,
TH_VIEW_OVERLAY,
- TH_V3D_CLIPPING_BORDER
+ TH_V3D_CLIPPING_BORDER,
+
+ TH_METADATA_BG,
+ TH_METADATA_TEXT
};
/* XXX WARNING: previous is saved in file, so do not change order! */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 5714a40d508..5c548d3afd5 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -37,6 +37,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@@ -1951,6 +1952,56 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but)
return but_iter;
}
+/** \name Check to show extra icons
+ *
+ * Extra icons are shown on the right hand side of buttons.
+ * \{ */
+
+static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
+{
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
+ return ((but->editstr == NULL) &&
+ (but->drawstr[0] != '\0') &&
+ (but->flag & UI_BUT_SEARCH_UNLINK));
+}
+
+static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but)
+{
+ StructRNA *type;
+ short idcode;
+
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK));
+
+ if (but->rnaprop == NULL) {
+ return false;
+ }
+
+ type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+ idcode = RNA_type_to_ID_code(type);
+
+
+ return ((but->editstr == NULL) &&
+ (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
+}
+
+uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
+{
+ if ((but->flag & UI_BUT_SEARCH_UNLINK) == 0) {
+ /* pass */
+ }
+ else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return UI_BUT_ICONEXTRA_UNLINK;
+ }
+ else if (ui_but_icon_extra_is_visible_eyedropper(but)) {
+ return UI_BUT_ICONEXTRA_EYEDROPPER;
+ }
+
+ return UI_BUT_ICONEXTRA_NONE;
+}
+
+/** \} */
+
+
static double ui_get_but_scale_unit(uiBut *but, double value)
{
UnitSettings *unit = but->block->unit;
@@ -2714,11 +2765,11 @@ void ui_but_update(uiBut *but)
}
else {
const int prec = ui_but_calc_float_precision(but, value);
- slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value);
+ slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value);
}
}
else {
- slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value);
+ slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value);
}
if (but->rnaprop) {
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index f5847a9d701..44e06bab4ab 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -176,8 +176,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
if (sa) {
if (sa->spacetype == SPACE_IMAGE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
SpaceImage *sima = sa->spacedata.first;
int mval[2] = {mx - ar->winrct.xmin,
my - ar->winrct.ymin};
@@ -188,8 +188,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
}
}
else if (sa->spacetype == SPACE_NODE) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
SpaceNode *snode = sa->spacedata.first;
int mval[2] = {mx - ar->winrct.xmin,
my - ar->winrct.ymin};
@@ -200,8 +200,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int
}
}
else if (sa->spacetype == SPACE_CLIP) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
SpaceClip *sc = sa->spacedata.first;
int mval[2] = {mx - ar->winrct.xmin,
my - ar->winrct.ymin};
@@ -456,6 +456,8 @@ static void datadropper_exit(bContext *C, wmOperator *op)
op->customdata = NULL;
}
+
+ WM_event_add_mousemove(C);
}
static void datadropper_cancel(bContext *C, wmOperator *op)
@@ -482,8 +484,8 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
if (sa) {
if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
const int mval[2] = {
mx - ar->winrct.xmin,
my - ar->winrct.ymin};
@@ -765,8 +767,8 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
if (sa) {
if (sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+ ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
+ if (ar) {
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
/* weak, we could pass in some reference point */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index bc35fde633c..1d71a5db350 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -332,7 +332,6 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da
const bool mousemove, const bool onfree);
static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata);
static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
-static void button_timers_tooltip_remove(bContext *C, uiBut *but);
#ifdef USE_DRAG_MULTINUM
static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block);
@@ -3301,9 +3300,11 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
+ uiButExtraIconType extra_icon_type;
+
/* unlink icon is on right */
- if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS &&
- ui_but_is_search_unlink_visible(but))
+ if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) &&
+ ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
{
ARegion *ar = data->region;
rcti rect;
@@ -3314,14 +3315,29 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa
BLI_rcti_rctf_copy(&rect, &but->rect);
rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect));
+ /* handle click on unlink/eyedropper icon */
if (BLI_rcti_isect_pt(&rect, x, y)) {
- /* most likely NULL, but let's check, and give it temp zero string */
- if (data->str == NULL)
- data->str = MEM_callocN(1, "temp str");
- data->str[0] = 0;
+ /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
+ if (event->val == KM_RELEASE) {
+ /* unlink */
+ if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
+ /* most likely NULL, but let's check, and give it temp zero string */
+ if (data->str == NULL) {
+ data->str = MEM_callocN(1, "temp str");
+ }
+ data->str[0] = 0;
- ui_apply_but_TEX(C, but, data);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ ui_apply_but_TEX(C, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ /* eyedropper */
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
return WM_UI_HANDLER_BREAK;
}
@@ -5939,7 +5955,7 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
UI_popup_block_invoke(C, menu_change_shortcut, but);
}
@@ -5960,7 +5976,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;
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but);
}
@@ -6009,7 +6025,7 @@ static bool ui_but_menu(bContext *C, uiBut *but)
return false;
}
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
/* highly unlikely getting the label ever fails */
UI_but_string_info_get(C, but, &label, NULL);
@@ -6237,14 +6253,9 @@ static bool ui_but_menu(bContext *C, uiBut *but)
char buf[512];
PointerRNA ptr_props;
- if (but->rnapoin.data && but->rnaprop) {
- BLI_snprintf(buf, sizeof(buf), "%s.%s",
- RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop));
-
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
- RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
- ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
+ if (UI_but_online_manual_id(but, buf, sizeof(buf))) {
+ uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
+ ICON_NONE, "WM_OT_doc_view_manual_ui_context");
WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
RNA_string_set(&ptr_props, "doc_id", buf);
@@ -6260,30 +6271,6 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
#endif
}
- else if (but->optype) {
- WM_operator_py_idname(buf, but->optype->idname);
-
-
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
- RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
- ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
- RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_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");
- RNA_string_set(&ptr_props, "doc_id", buf);
- RNA_string_set(&ptr_props, "doc_new", but->optype->description);
-
- uiItemFullO(layout, "WM_OT_doc_edit", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Submit Description"),
- ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
-#endif
- }
}
/* perhaps we should move this into (G.debug & G_DEBUG) - campbell */
@@ -6861,14 +6848,6 @@ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
return true;
}
-bool ui_but_is_search_unlink_visible(const uiBut *but)
-{
- BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
- return ((but->editstr == NULL) &&
- (but->drawstr[0] != '\0') &&
- (but->flag & UI_BUT_SEARCH_UNLINK));
-}
-
/* x and y are only used in case event is NULL... */
static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit)
{
@@ -6956,7 +6935,8 @@ static bool button_modal_state(uiHandleButtonState state)
BUTTON_STATE_MENU_OPEN);
}
-static void button_timers_tooltip_remove(bContext *C, uiBut *but)
+/* removes tooltip timer from active but (meaning tooltip is disabled until it's reenabled again) */
+void UI_but_tooltip_timer_remove(bContext *C, uiBut *but)
{
uiHandleButtonData *data;
@@ -7040,7 +7020,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
}
else {
but->flag |= UI_SELECT;
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
}
/* text editing */
@@ -7669,7 +7649,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
case WHEELDOWNMOUSE:
case MIDDLEMOUSE:
case MOUSEPAN:
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
/* fall-through */
default:
/* handle button type specific events */
@@ -8644,7 +8624,7 @@ static int ui_handle_menu_event(
{
if (!but || !ui_but_contains_point_px(ar, but, event->x, event->y)) {
if (but) {
- button_timers_tooltip_remove(C, but);
+ UI_but_tooltip_timer_remove(C, but);
}
menu->is_grab = true;
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index d7b6824f812..d9558af5f71 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -121,6 +121,14 @@ enum {
/* warn: rest of uiBut->flag in UI_interface.h */
};
+/* some buttons display icons only under special conditions
+ * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */
+typedef enum uiButExtraIconType {
+ UI_BUT_ICONEXTRA_NONE = 1,
+ UI_BUT_ICONEXTRA_UNLINK,
+ UI_BUT_ICONEXTRA_EYEDROPPER,
+} uiButExtraIconType;
+
/* but->pie_dir */
typedef enum RadialDirection {
UI_RADIAL_NONE = -1,
@@ -456,6 +464,7 @@ extern bool ui_but_string_set(struct bContext *C, uiBut *but, const char *str) A
extern bool ui_but_string_set_eval_num(struct bContext *C, uiBut *but, const char *str, double *value) ATTR_NONNULL();
extern int ui_but_string_get_max_length(uiBut *but);
extern uiBut *ui_but_drag_multi_edit_get(uiBut *but);
+extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but);
extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc);
@@ -466,7 +475,6 @@ extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
-extern bool ui_but_is_search_unlink_visible(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 5aee8e18ba0..239d6f7c493 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -82,6 +82,14 @@
/* only show pin header button for pinned panels */
#define USE_PIN_HIDDEN
+/* the state of the mouse position relative to the panel */
+typedef enum uiPanelMouseState {
+ PANEL_MOUSE_OUTSIDE, /* mouse is not in the panel */
+ PANEL_MOUSE_INSIDE_CONTENT, /* mouse is in the actual panel content */
+ PANEL_MOUSE_INSIDE_HEADER, /* mouse is in the panel header */
+ PANEL_MOUSE_INSIDE_SCALE, /* mouse is inside panel scale widget */
+} uiPanelMouseState;
+
typedef enum uiHandlePanelState {
PANEL_STATE_DRAG,
PANEL_STATE_DRAG_SCALE,
@@ -1128,6 +1136,158 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
/******************* region level panel interaction *****************/
+static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, const Panel *pa, const int mx, const int my)
+{
+ /* open panel */
+ if (pa->flag & PNL_CLOSEDX) {
+ if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) {
+ return PANEL_MOUSE_INSIDE_HEADER;
+ }
+ }
+ /* outside left/right side */
+ else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) {
+ /* pass */
+ }
+ else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
+ return PANEL_MOUSE_INSIDE_HEADER;
+ }
+ /* open panel */
+ else if (!(pa->flag & PNL_CLOSEDY)) {
+ if (pa->control & UI_PNL_SCALE) {
+ if (block->rect.xmax - PNL_HEADER <= mx) {
+ if (block->rect.ymin + PNL_HEADER >= my) {
+ return PANEL_MOUSE_INSIDE_SCALE;
+ }
+ }
+ }
+ if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) {
+ if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
+ return PANEL_MOUSE_INSIDE_CONTENT;
+ }
+ }
+ }
+ return PANEL_MOUSE_OUTSIDE;
+}
+
+typedef struct uiPanelDragCollapseHandle {
+ bool was_first_open;
+ int xy_init[2];
+} uiPanelDragCollapseHandle;
+
+static void ui_panel_drag_collapse_handler_remove(bContext *UNUSED(C), void *userdata)
+{
+ uiPanelDragCollapseHandle *dragcol_data = userdata;
+ MEM_freeN(dragcol_data);
+}
+
+static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragcol_data, const int xy_dst[2])
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ uiBlock *block;
+ Panel *pa;
+
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ float xy_a_block[2] = {UNPACK2(dragcol_data->xy_init)};
+ float xy_b_block[2] = {UNPACK2(xy_dst)};
+ rctf rect = block->rect;
+ int oldflag;
+ const bool is_horizontal = (panel_aligned(sa, ar) == BUT_HORIZONTAL);
+
+ if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) {
+ continue;
+ }
+ oldflag = pa->flag;
+
+ /* lock one axis */
+ if (is_horizontal) {
+ xy_b_block[1] = dragcol_data->xy_init[1];
+ }
+ else {
+ xy_b_block[0] = dragcol_data->xy_init[0];
+ }
+
+ /* use cursor coords in block space */
+ ui_window_to_block_fl(ar, block, &xy_a_block[0], &xy_a_block[1]);
+ ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]);
+
+ /* set up rect to match header size */
+ rect.ymin = rect.ymax;
+ rect.ymax = rect.ymin + PNL_HEADER;
+ if (pa->flag & PNL_CLOSEDX) {
+ rect.xmin = rect.xmin;
+ rect.xmax = rect.xmin + PNL_HEADER;
+ }
+
+ /* touch all panels between last mouse coord and the current one */
+ if (BLI_rctf_isect_segment(&rect, xy_a_block, xy_b_block)) {
+ /* force panel to close */
+ if (dragcol_data->was_first_open == true) {
+ pa->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY);
+ }
+ /* force panel to open */
+ else {
+ pa->flag &= ~PNL_CLOSED;
+ }
+
+ /* if pa->flag has changed this means a panel was opened/closed here */
+ if (pa->flag != oldflag) {
+ panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
+ }
+ }
+ }
+}
+
+/**
+ * Panel drag-collapse (modal handler)
+ * Clicking and dragging over panels toggles their collapse state based on the panel that was first
+ * dragged over. If it was open all affected panels incl the initial one are closed and vise versa.
+ */
+static int ui_panel_drag_collapse_handler(bContext *C, const wmEvent *event, void *userdata)
+{
+ wmWindow *win = CTX_wm_window(C);
+ uiPanelDragCollapseHandle *dragcol_data = userdata;
+ short retval = WM_UI_HANDLER_CONTINUE;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ ui_panel_drag_collapse(C, dragcol_data, &event->x);
+
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ /* done! */
+ WM_event_remove_ui_handler(
+ &win->modalhandlers,
+ ui_panel_drag_collapse_handler,
+ ui_panel_drag_collapse_handler_remove,
+ dragcol_data, true);
+ ui_panel_drag_collapse_handler_remove(C, dragcol_data);
+ }
+ /* don't let any left-mouse event fall through! */
+ retval = WM_UI_HANDLER_BREAK;
+ break;
+ }
+
+ return retval;
+}
+
+static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was_open)
+{
+ wmWindow *win = CTX_wm_window(C);
+ wmEvent *event = win->eventstate;
+ uiPanelDragCollapseHandle *dragcol_data = MEM_mallocN(sizeof(*dragcol_data), __func__);
+
+ dragcol_data->was_first_open = was_open;
+ copy_v2_v2_int(dragcol_data->xy_init, &event->x);
+
+ WM_event_add_ui_handler(
+ C, &win->modalhandlers,
+ ui_panel_drag_collapse_handler,
+ ui_panel_drag_collapse_handler_remove,
+ dragcol_data, false);
+}
/* this function is supposed to call general window drawing too */
/* also it supposes a block has panel, and isn't a menu */
@@ -1199,15 +1359,27 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
/* snap back up so full panel aligns with screen edge */
if (block->panel->snap & PNL_SNAP_BOTTOM)
block->panel->ofsy = 0;
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, false);
+ }
}
else if (align == BUT_HORIZONTAL) {
block->panel->flag |= PNL_CLOSEDX;
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, true);
+ }
}
else {
- /* snap down to bottom screen edge*/
+ /* snap down to bottom screen edge */
block->panel->flag |= PNL_CLOSEDY;
if (block->panel->snap & PNL_SNAP_BOTTOM)
block->panel->ofsy = -block->panel->sizey;
+
+ if (event == LEFTMOUSE) {
+ ui_panel_drag_collapse_handler_add(C, true);
+ }
}
for (pa = ar->panels.first; pa; pa = pa->next) {
@@ -1722,8 +1894,8 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
}
for (block = ar->uiblocks.last; block; block = block->prev) {
- bool inside = false, inside_header = false, inside_scale = false;
-
+ uiPanelMouseState mouse_state;
+
mx = event->x;
my = event->y;
ui_window_to_block(ar, block, &mx, &my);
@@ -1735,32 +1907,11 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
continue;
if (pa->type && pa->type->flag & PNL_NO_HEADER) /* XXX - accessed freed panels when scripts reload, need to fix. */
continue;
-
- /* clicked at panel header? */
- if (pa->flag & PNL_CLOSEDX) {
- if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx)
- inside_header = true;
- }
- else if (block->rect.xmin > mx || block->rect.xmax < mx) {
- /* outside left/right side */
- }
- else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
- inside_header = true;
- }
- else if (!(pa->flag & PNL_CLOSEDY)) {
- /* open panel */
- if (pa->control & UI_PNL_SCALE) {
- if (block->rect.xmax - PNL_HEADER <= mx)
- if (block->rect.ymin + PNL_HEADER >= my)
- inside_scale = true;
- }
- if (block->rect.xmin <= mx && block->rect.xmax >= mx)
- if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my)
- inside = true;
- }
-
+
+ mouse_state = ui_panel_mouse_state_get(block, pa, mx, my);
+
/* XXX hardcoded key warning */
- if ((inside || inside_header) && event->val == KM_PRESS) {
+ if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) && event->val == KM_PRESS) {
if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) {
if (pa->flag & PNL_CLOSEDY) {
@@ -1779,13 +1930,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
if (ui_but_is_active(ar))
continue;
- if (inside || inside_header) {
+ if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
if (event->val == KM_PRESS) {
/* open close on header */
if (ELEM(event->type, RETKEY, PADENTER)) {
- if (inside_header) {
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift);
retval = WM_UI_HANDLER_BREAK;
break;
@@ -1795,12 +1946,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
/* all inside clicks should return in break - overlapping/float panels */
retval = WM_UI_HANDLER_BREAK;
- if (inside_header) {
- ui_handle_panel_header(C, block, mx, my, 0, event->ctrl, event->shift);
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
+ ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift);
retval = WM_UI_HANDLER_BREAK;
break;
}
- else if (inside_scale && !(pa->flag & PNL_CLOSED)) {
+ else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) {
panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE);
retval = WM_UI_HANDLER_BREAK;
break;
@@ -1808,7 +1959,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
}
else if (event->type == RIGHTMOUSE) {
- if (inside_header) {
+ if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) {
ui_panel_menu(C, ar, block->panel);
retval = WM_UI_HANDLER_BREAK;
break;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index c3a9d17d255..8d2ee04a2e9 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1634,17 +1634,14 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
static RNAUpdateCb cb;
uiBlock *block;
uiBut *but;
- int icon;
+ int icon, value;
EnumPropertyItem *item;
int a;
bool free;
/* arg_litem is malloced, can be freed by parent button */
cb = *((RNAUpdateCb *)arg_litem);
-
- /* unused */
- // icon = RNA_property_enum_get(&cb.ptr, cb.prop);
-
+
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_LOOP);
@@ -1659,7 +1656,9 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem)
y = (a / 8) * UI_UNIT_X * 5;
icon = item[a].icon;
- but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL);
+ value = item[a].value;
+ but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5,
+ &cb.ptr, cb.prop, -1, 0, value, -1, -1, NULL);
UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
}
@@ -1677,36 +1676,35 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
RNAUpdateCb *cb;
+ EnumPropertyItem *items;
uiBlock *block;
uiBut *but;
-// rctf rect; /* UNUSED */
- int icon;
-
- if (!prop || RNA_property_type(prop) != PROP_ENUM)
+ int value, icon = ICON_NONE, tot_items;
+ bool free_items;
+
+ if (!prop || RNA_property_type(prop) != PROP_ENUM) {
+ RNA_warning("property of type Enum not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
return;
-
- icon = RNA_property_enum_get(ptr, prop);
-
+ }
+
+ block = uiLayoutAbsoluteBlock(layout);
+
+ RNA_property_enum_items(block->evil_C, ptr, prop, &items, &tot_items, &free_items);
+ value = RNA_property_enum_get(ptr, prop);
+ RNA_enum_icon_from_value(items, value, &icon);
+
cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
cb->ptr = *ptr;
cb->prop = prop;
-
-// rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
-// rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X;
-
- block = uiLayoutAbsoluteBlock(layout);
- but = uiDefBlockButN(block, ui_icon_view_menu_cb, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
-
-// but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL);
-
but->icon = icon;
UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
-
- UI_but_funcN_set(but, rna_update_cb, MEM_dupallocN(cb), NULL);
-
- MEM_freeN(cb);
+
+ if (free_items) {
+ MEM_freeN(items);
+ }
}
/********************* Histogram Template ************************/
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 28bd637ae59..14d97dd883e 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -52,6 +52,9 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "interface_intern.h"
@@ -309,6 +312,34 @@ int UI_calc_float_precision(int prec, double value)
return prec;
}
+bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
+{
+ if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) {
+ BLI_snprintf(r_str, maxlength, "%s.%s", RNA_struct_identifier(but->rnapoin.type),
+ RNA_property_identifier(but->rnaprop));
+ return true;
+ }
+ else if (but->optype) {
+ WM_operator_py_idname(r_str, but->optype->idname);
+ return true;
+ }
+
+ *r_str = '\0';
+ return false;
+}
+
+bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength)
+{
+ uiBut *but = UI_context_active_but_get(C);
+
+ if (but) {
+ return UI_but_online_manual_id(but, r_str, maxlength);
+ }
+
+ *r_str = '\0';
+ return false;
+}
+
/* -------------------------------------------------------------------- */
/* Modal Button Store API */
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index b3c3d7f53a9..08bd2d3360c 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1501,6 +1501,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
+ uiButExtraIconType extra_icon_type;
ui_but_text_password_hide(password_str, but, false);
@@ -1540,11 +1541,23 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
}
/* unlink icon for this button type */
- if ((but->type == UI_BTYPE_SEARCH_MENU) && ui_but_is_search_unlink_visible(but)) {
+ if ((but->type == UI_BTYPE_SEARCH_MENU) &&
+ ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
+ {
rcti temp = *rect;
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
- widget_draw_icon(but, ICON_X, alpha, &temp, false);
+
+ if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
+ widget_draw_icon(but, ICON_X, alpha, &temp, false);
+ }
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false);
+ }
+ else {
+ BLI_assert(0);
+ }
+
rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect);
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 15e742c930a..8e003e50df3 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -569,6 +569,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->paint_curve_pivot;
break;
+ case TH_METADATA_BG:
+ cp = ts->metadatabg;
+ break;
+ case TH_METADATA_TEXT:
+ cp = ts->metadatatext;
+ break;
+
case TH_UV_OTHERS:
cp = ts->uv_others;
break;
@@ -2602,6 +2609,15 @@ void init_userdef_do_versions(void)
cp[3] = 255;
}
}
+
+ if (U.versionfile < 274 || (U.versionfile == 274 && U.subversionfile < 5)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ copy_v4_v4_char(btheme->tima.metadatatext, btheme->tima.text_hi);
+ copy_v4_v4_char(btheme->tseq.metadatatext, btheme->tseq.text_hi);
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 5730c967880..816c9a93d8c 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -328,7 +328,7 @@ static void VIEW2D_OT_pan(wmOperatorType *ot)
ot->cancel = view_pan_cancel;
/* operator is modal */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna - must keep these in sync with the other operators */
RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
@@ -661,7 +661,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool
const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
/* only move view to mouse if zoom fac is inside minzoom/maxzoom */
- if (IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) {
+ if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
+ IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom))
+ {
float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dx) - (mval_faci * dx);
@@ -692,7 +694,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool
const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur);
/* only move view to mouse if zoom fac is inside minzoom/maxzoom */
- if (IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) {
+ if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) ||
+ IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom))
+ {
float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dy) - (mval_faci * dy);
@@ -1175,7 +1179,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
ot->poll = view_zoom_poll;
/* operator is repeatable */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna - must keep these in sync with the other operators */
prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 7e767d8f6c8..2efa9e211c9 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -253,7 +253,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
return;
if (sc)
- undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
+ undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
/* TODO, add this to sequence editor */
handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
@@ -422,7 +422,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
float (*points)[2] = orig_points;
if (sc) {
- int undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
+ const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
if (undistort) {
int i;
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 113f0f71b53..35fc4483702 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -446,7 +446,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
}
}
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
rt = ibuf->rect;
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 6ce5e8a304b..c67ee41703a 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -62,10 +62,7 @@ static Object *make_prim_init(bContext *C, const char *idname,
*was_editmode = false;
if (obedit == NULL || obedit->type != OB_MESH) {
- obedit = ED_object_add_type(C, OB_MESH, loc, rot, false, layer);
-
- rename_id((ID *)obedit, idname);
- rename_id((ID *)obedit->data, idname);
+ obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, layer);
/* create editmode */
ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 0e48cbcd589..1e44d7e654d 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -477,7 +477,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
ot->poll = ED_operator_editmesh;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
prop = RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Amount", "", 0.0f, 1.0f);
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 5c7efcc40da..e8f9a76a873 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -574,8 +574,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
/* correct the normal to be aligned on the view plane */
- copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
- mul_mat3_m4_v3(vc.obedit->imat, view_vec);
+ mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]);
cross_v3_v3v3(cross, nor, view_vec);
cross_v3_v3v3(nor, view_vec, cross);
normalize_v3(nor);
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index f1c3ca30610..80d3777d057 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -499,7 +499,7 @@ void MESH_OT_inset(wmOperatorType *ot)
ot->poll = ED_operator_editmesh;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
/* properties */
RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index f3745ed72fb..cfd0d3fdcf5 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1319,18 +1319,63 @@ static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe)
return ele_test;
}
+/* Do edges e1 and e2 go between exactly the same coordinates? */
+static bool coinciding_edges(BMEdge *e1, BMEdge *e2)
+{
+ const float *co11, *co12, *co21, *co22;
+
+ co11 = e1->v1->co;
+ co12 = e1->v2->co;
+ co21 = e2->v1->co;
+ co22 = e2->v2->co;
+ if ((equals_v3v3(co11, co21) && equals_v3v3(co12, co22)) ||
+ (equals_v3v3(co11, co22) && equals_v3v3(co12, co21)))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/* Callback used in point_is_visible to exclude hits on the faces that are the same
+ * as or contain the hitting element (which is in user_data).
+ * Also (see T44492) want to exclude hits on faces that butt up to the hitting element
+ * (e.g., when you double an edge by an edge split).
+ */
static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data)
{
+ bool ans;
+ BMEdge *e, *e2;
+ BMIter iter;
+
switch (((BMElem *)user_data)->head.htype) {
case BM_FACE:
- return (BMFace *)user_data != f;
+ ans = (BMFace *)user_data != f;
+ break;
case BM_EDGE:
- return !BM_edge_in_face((BMEdge *)user_data, f);
+ e = (BMEdge *)user_data;
+ ans = !BM_edge_in_face(e, f);
+ if (ans) {
+ /* Is it a boundary edge, coincident with a split edge? */
+ if (BM_edge_is_boundary(e)) {
+ BM_ITER_ELEM(e2, &iter, f, BM_EDGES_OF_FACE) {
+ if (coinciding_edges(e, e2)) {
+ ans = false;
+ break;
+ }
+ }
+ }
+ }
+ break;
case BM_VERT:
- return !BM_vert_in_face((BMVert *)user_data, f);
+ ans = !BM_vert_in_face((BMVert *)user_data, f);
+ break;
default:
- return true;
+ ans = true;
+ break;
}
+ return ans;
}
@@ -2831,8 +2876,7 @@ static void knife_recalc_projmat(KnifeTool_OpData *kcd)
ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat);
invert_m4_m4(kcd->projmat_inv, kcd->projmat);
- copy_v3_v3(kcd->proj_zaxis, kcd->vc.rv3d->viewinv[2]);
- mul_mat3_m4_v3(kcd->ob->imat, kcd->proj_zaxis);
+ mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]);
normalize_v3(kcd->proj_zaxis);
kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.v3d, kcd->vc.rv3d,
@@ -3006,6 +3050,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
knifetool_init(C, kcd, only_select, cut_through, true);
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
/* add a modal handler for this operator - handles loop selection */
WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR);
WM_event_add_modal_handler(C, op);
@@ -3098,6 +3144,9 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
+ em_setup_viewcontext(C, &kcd->vc);
+ kcd->ar = kcd->vc.ar;
+
view3d_operator_needs_opengl(C);
ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */
@@ -3257,6 +3306,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
+ if (kcd->mode == MODE_DRAGGING) {
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
+ else {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+
if (do_refresh) {
/* we don't really need to update mval,
* but this happens to be the best way to refresh at the moment */
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 3d93210382c..c7f9522ab3f 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -553,6 +553,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
/* add a modal handler for this operator - handles loop selection */
if (is_interactive) {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
WM_event_add_modal_handler(C, op);
}
@@ -639,6 +640,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool show_cuts = false;
const bool has_numinput = hasNumInput(&lcd->num);
+ em_setup_viewcontext(C, &lcd->vc);
+ lcd->ar = lcd->vc.ar;
+
view3d_operator_needs_opengl(C);
/* using the keyboard to input the number of cuts */
@@ -835,7 +839,7 @@ void MESH_OT_loopcut(wmOperatorType *ot)
prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items);
- RNA_def_property_enum_default(prop, PROP_ROOT);
+ RNA_def_property_enum_default(prop, PROP_INVSQUARE);
RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather");
RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index 4eaac6cc1d3..72dfb89e5f3 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -94,7 +94,7 @@ static bool mouse_mesh_shortest_path_vert(ViewContext *vc)
float dist = ED_view3d_select_dist_px();
const bool use_length = true;
- v_dst = EDBM_vert_find_nearest(vc, &dist, false, false);
+ v_dst = EDBM_vert_find_nearest(vc, &dist);
if (v_dst) {
struct UserData user_data = {bm, vc->obedit->data, vc->scene};
LinkNode *path = NULL;
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 45e16ceff7b..abd88ae65aa 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -559,9 +559,10 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
- /* this should be impossible, but sanity checks are a good thing */
- if (!v)
+ /* (v == NULL) should be impossible */
+ if ((v == NULL) || (v->e == NULL)) {
return OPERATOR_CANCELLED;
+ }
is_wire = BM_vert_is_wire(v);
@@ -570,12 +571,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
if (v->e) {
/* find closest edge to mouse cursor */
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- const bool is_boundary = BM_edge_is_boundary(e);
/* consider wire as boundary for this purpose,
* otherwise we can't a face away from a wire edge */
- totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e));
+ totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e));
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- if (is_boundary == false && BM_edge_is_manifold(e)) {
+ if (BM_edge_is_manifold(e)) {
d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
if ((e2 == NULL) || (d < dist_sq)) {
dist_sq = d;
@@ -622,6 +622,32 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
+ if (e2) {
+ /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */
+
+ /* note: we're lazy here and first split then check there are any faces remaining,
+ * this isn't good practice, however its less hassle then checking for multiple-disconnected regions */
+ BMLoop *l_sep = e2->l->v == v ? e2->l : e2->l->next;
+ BMVert *v_new;
+ BLI_assert(l_sep->v == v);
+ v_new = bmesh_urmv_loop_region(bm, l_sep);
+ if (BM_vert_find_first_loop(v)) {
+ BM_vert_select_set(bm, v, false);
+ BM_select_history_remove(bm, v);
+
+ BM_vert_select_set(bm, v_new, true);
+ if (ese.ele) {
+ BM_select_history_store(bm, v_new);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* rewind */
+ BM_vert_splice(bm, v, v_new);
+ }
+ }
+
/* should we go ahead with edge rip or do we need to do special case, split off vertex?:
* split off vertex if...
* - we cant find an edge - this means we are ripping a faces vert that is connected to other
@@ -715,7 +741,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
for (i = 2; i < vout_len; i++) {
- BM_vert_splice(bm, vout[i], vout[1]);
+ BM_vert_splice(bm, vout[1], vout[i]);
}
}
@@ -734,20 +760,42 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
/* unlike edge split, for single vertex split we only use the operator in one of the cases
* but both allocate fill */
- /* rip two adjacent edges */
- if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) {
- /* Don't run the edge split operator in this case */
+ {
BMVert *v_rip;
+ BMLoop *larr[2];
+ int larr_len = 0;
- l = BM_edge_vert_share_loop(e2->l, v);
+ /* rip two adjacent edges */
+ if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) {
+ /* Don't run the edge split operator in this case */
- /* only tag for face-fill (we don't call the operator) */
- if (BM_edge_is_boundary(e2)) {
- BM_elem_flag_enable(e2, BM_ELEM_TAG);
+ l = BM_edge_vert_share_loop(e2->l, v);
+ larr[larr_len] = l;
+ larr_len++;
+
+ /* only tag for face-fill (we don't call the operator) */
+ if (BM_edge_is_boundary(e2)) {
+ BM_elem_flag_enable(e2, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ }
}
else {
- BM_elem_flag_enable(l->e, BM_ELEM_TAG);
- BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ if (BM_edge_is_manifold(e2)) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = e2->l;
+ do {
+ larr[larr_len] = BM_edge_vert_share_loop(l_iter, v);
+ BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG);
+ larr_len++;
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ else {
+ /* looks like there are no split edges, we could just return/report-error? - Campbell */
+ }
}
/* keep directly before edgesplit */
@@ -755,13 +803,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
}
-#if 0
- v_rip = BM_face_vert_separate(bm, l->f, v);
-#else
- v_rip = BM_face_loop_separate(bm, l);
-#endif
-
- BLI_assert(v_rip);
+ if (larr_len) {
+ v_rip = BM_face_loop_separate_multi(bm, larr, larr_len);
+ }
+ else {
+ v_rip = NULL;
+ }
if (v_rip) {
BM_vert_select_set(bm, v_rip, true);
@@ -771,27 +818,6 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
return OPERATOR_CANCELLED;
}
}
- else {
- if (BM_edge_is_manifold(e2)) {
- l = e2->l;
- e = BM_loop_other_edge_loop(l, v)->e;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
-
- l = e2->l->radial_next;
- e = BM_loop_other_edge_loop(l, v)->e;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- else {
- /* looks like there are no split edges, we could just return/report-error? - Campbell */
- }
-
- /* keep directly before edgesplit */
- if (do_fill) {
- fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
- }
-
- BM_mesh_edgesplit(em->bm, true, true, true);
- }
{
/* --- select which vert --- */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 0c3f69e4996..4ce493def5b 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -36,6 +36,7 @@
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_rand.h"
#include "BLI_array.h"
@@ -196,11 +197,11 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma
unsigned int *dr;
int a;
- if (vc->obedit == NULL || vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) {
return false;
}
- buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
if (buf == NULL) return false;
if (bm_vertoffs == 0) return false;
@@ -271,11 +272,11 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
return false;
}
}
- else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ else if (!V3D_IS_ZBUF(vc->v3d)) {
return false;
}
- buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
if (buf == NULL) return false;
if (bm_vertoffs == 0) return false;
@@ -320,13 +321,13 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
return false;
}
}
- else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ else if (!V3D_IS_ZBUF(vc->v3d)) {
return false;
}
xmin = xs - rads; xmax = xs + rads;
ymin = ys - rads; ymax = ys + rads;
- buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+ buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
if (bm_vertoffs == 0) return false;
if (buf == NULL) return false;
@@ -350,194 +351,369 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
}
+
+/* -------------------------------------------------------------------- */
+
+/** \name Find Nearest Vert/Edge/Face
+ *
+ * \note Screen-space manhatten distances are used here,
+ * since its faster and good enough for the purpose of selection.
+ *
+ * \note \a dist_bias is used so we can bias against selected items.
+ * when choosing between elements of a single type, but return the real distance
+ * to avoid the bias interfering with distance comparisons when mixing types.
+ * \{ */
+
+#define FIND_NEAR_SELECT_BIAS 5
+#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3
+
+struct NearestVertUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMVert *vert;
+};
+
+struct NearestVertUserData {
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestVertUserData_Hit hit;
+ struct NearestVertUserData_Hit hit_cycle;
+};
+
static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
{
- struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } *data = userData;
+ struct NearestVertUserData *data = userData;
+ float dist_test, dist_test_bias;
- if (data->pass == 0) {
- if (index <= data->lastIndex)
- return;
- }
- else {
- if (index > data->lastIndex)
- return;
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
- if (data->dist > 3) {
- float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->select) {
- if (data->strict == 1) {
- return;
- }
- else {
- dist_test += 5;
- }
- }
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.vert = eve;
+ }
- if (dist_test < data->dist) {
- data->dist = dist_test;
- data->closest = eve;
- data->closestIndex = index;
+ if (data->use_cycle) {
+ if ((data->hit_cycle.vert == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.vert = eve;
}
}
}
-
-static bool findnearestvert__backbufIndextest(void *handle, unsigned int index)
-{
- BMEditMesh *em = (BMEditMesh *)handle;
- BMVert *eve = BM_vert_at_index_find(em->bm, index - 1);
- return !(eve && BM_elem_flag_test(eve, BM_ELEM_SELECT));
-}
/**
- * findnearestvert
- *
- * dist (in/out): minimal distance to the nearest and at the end, actual distance
- * sel: selection bias
- * if SELECT, selected vertice are given a 5 pixel bias to make them further than unselect verts
- * if 0, unselected vertice are given the bias
- * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
+ * Nearest vertex under the cursor.
+ *
+ * \param r_dist (in/out), minimal distance to the nearest and at the end, actual distance
+ * \param use_select_bias
+ * - When true, selected vertice are given a 5 pixel bias to make them further than unselect verts.
+ * - When false, unselected vertice are given the bias.
+ * \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
*/
-BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const bool sel, const bool strict)
+BMVert *EDBM_vert_find_nearest_ex(
+ ViewContext *vc, float *r_dist,
+ const bool use_select_bias, bool use_cycle)
{
- if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- float distance;
+ BMesh *bm = vc->em->bm;
+
+ if (V3D_IS_ZBUF(vc->v3d)) {
+ const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ float dist_test;
unsigned int index;
BMVert *eve;
- if (strict) {
- index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance,
- strict, vc->em, findnearestvert__backbufIndextest);
- }
- else {
- index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance,
- 0, NULL, NULL);
- }
-
- eve = index ? BM_vert_at_index_find(vc->em->bm, index - 1) : NULL;
+ index = ED_view3d_backbuf_sample_rect(
+ vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
+ eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
- if (eve && distance < *r_dist) {
- *r_dist = distance;
- return eve;
- }
- else {
- return NULL;
+ if (eve) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return eve;
+ }
}
-
+ return NULL;
}
else {
- struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } data;
- static int lastSelectedIndex = 0;
- static BMVert *lastSelected = NULL;
-
- if (lastSelected && BM_vert_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
+ struct NearestVertUserData data = {{0}};
+ const struct NearestVertUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+
+ static int prev_select_index = 0;
+ static const BMVert *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))))
+ {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
}
- data.lastIndex = lastSelectedIndex;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.select = sel ? BM_ELEM_SELECT : 0;
- data.dist = *r_dist;
- data.strict = strict;
- data.closest = NULL;
- data.closestIndex = 0;
-
- data.pass = 0;
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = \
+ data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
- if (data.dist > 3) {
- data.pass = 1;
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- }
+ prev_select_elem = hit->vert;
+ prev_select_index = hit->index;
- *r_dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
+ return hit->vert;
+ }
+}
+
+BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
+{
+ return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
+}
+
+/* find the distance to the edge we already have */
+struct NearestEdgeUserData_ZBuf {
+ float mval_fl[2];
+ float dist;
+ const BMEdge *edge_test;
+};
+
+static void find_nearest_edge_center__doZBuf(
+ void *userData, BMEdge *eed,
+ const float screen_co_a[2], const float screen_co_b[2],
+ int UNUSED(index))
+{
+ struct NearestEdgeUserData_ZBuf *data = userData;
+
+ if (eed == data->edge_test) {
+ float dist_test;
+ float screen_co_mid[2];
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
- return data.closest;
+ if (dist_test < data->dist) {
+ data->dist = dist_test;
+ }
}
}
+struct NearestEdgeUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMEdge *edge;
+
+ /* edges only, un-biased manhatten distance to which ever edge we pick
+ * (not used for choosing) */
+ float dist_center;
+};
+
+struct NearestEdgeUserData {
+ ViewContext vc;
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestEdgeUserData_Hit hit;
+ struct NearestEdgeUserData_Hit hit_cycle;
+};
+
/* note; uses v3d, so needs active 3d window */
-static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
+static void find_nearest_edge__doClosest(
+ void *userData, BMEdge *eed,
+ const float screen_co_a[2], const float screen_co_b[2],
+ int index)
{
- struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } *data = userData;
- int distance;
+ struct NearestEdgeUserData *data = userData;
+ float dist_test, dist_test_bias;
- distance = dist_to_line_segment_v2(data->mval_fl, screen_co_a, screen_co_b);
-
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- distance += 5;
+ float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
+ float screen_co[2];
+
+ if (fac <= 0.0f) {
+ fac = 0.0f;
+ copy_v2_v2(screen_co, screen_co_a);
+ }
+ else if (fac >= 1.0f) {
+ fac = 1.0f;
+ copy_v2_v2(screen_co, screen_co_b);
+ }
+ else {
+ interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac);
}
- if (distance < data->dist) {
- if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
- float lambda = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
- float vec[3];
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
- vec[0] = eed->v1->co[0] + lambda * (eed->v2->co[0] - eed->v1->co[0]);
- vec[1] = eed->v1->co[1] + lambda * (eed->v2->co[1] - eed->v1->co[1]);
- vec[2] = eed->v1->co[2] + lambda * (eed->v2->co[2] - eed->v1->co[2]);
+ if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ dist_test += FIND_NEAR_SELECT_BIAS;
+ }
- if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) {
- data->dist = distance;
- data->closest = eed;
- }
+ if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
+ float vec[3];
+
+ interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
+ if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
+ return;
}
- else {
- data->dist = distance;
- data->closest = eed;
+ }
+
+ if (dist_test_bias < data->hit.dist_bias) {
+ float screen_co_mid[2];
+
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
+ }
+
+ if (data->use_cycle) {
+ if ((data->hit_cycle.edge == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ float screen_co_mid[2];
+
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.edge = eed;
+
+ mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b);
+ data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid);
}
}
}
-BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
+
+BMEdge *EDBM_edge_find_nearest_ex(
+ ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ BMEdge **r_eed_zbuf)
{
+ BMesh *bm = vc->em->bm;
- if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
- float distance;
+ if (V3D_IS_ZBUF(vc->v3d)) {
+ const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
+ float dist_test = 0.0f;
unsigned int index;
BMEdge *eed;
- view3d_validate_backbuf(vc);
-
- index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL);
- eed = index ? BM_edge_at_index_find(vc->em->bm, index - 1) : NULL;
-
- if (eed && distance < *r_dist) {
- *r_dist = distance;
- return eed;
+ ED_view3d_backbuf_validate(vc);
+
+ index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
+ eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
+
+ if (r_eed_zbuf) {
+ *r_eed_zbuf = eed;
}
- else {
- return NULL;
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && eed) {
+ struct NearestEdgeUserData_ZBuf data;
+
+ data.mval_fl[0] = vc->mval[0];
+ data.mval_fl[1] = vc->mval[1];
+ data.dist = FLT_MAX;
+ data.edge_test = eed;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+
+ mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ *r_dist_center = data.dist;
}
+ /* end exception */
+
+ if (eed) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
+ return eed;
+ }
+ }
+ return NULL;
}
else {
- struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } data;
+ struct NearestEdgeUserData data = {{0}};
+ const struct NearestEdgeUserData_Hit *hit;
+ /* interpolate along the edge before doing a clipping plane test */
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
+
+ static int prev_select_index = 0;
+ static const BMEdge *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index))))
+ {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
+ }
data.vc = *vc;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.dist = *r_dist;
- data.closest = NULL;
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = \
+ data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
+
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist_center;
+ }
- mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN);
+ prev_select_elem = hit->edge;
+ prev_select_index = hit->index;
- *r_dist = data.dist;
- return data.closest;
+ return hit->edge;
}
}
-static void findnearestface__getDistance(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+BMEdge *EDBM_edge_find_nearest(
+ ViewContext *vc, float *r_dist)
{
- struct { float mval_fl[2]; float dist; BMFace *toFace; } *data = userData;
+ return EDBM_edge_find_nearest_ex(vc, r_dist, false, false, false, NULL);
+}
+
+/* find the distance to the face we already have */
+struct NearestFaceUserData_ZBuf {
+ float mval_fl[2];
+ float dist;
+ const BMFace *face_test;
+};
- if (efa == data->toFace) {
+static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+{
+ struct NearestFaceUserData_ZBuf *data = userData;
+
+ if (efa == data->face_test) {
const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
if (dist_test < data->dist) {
@@ -545,96 +721,152 @@ static void findnearestface__getDistance(void *userData, BMFace *efa, const floa
}
}
}
+
+
+struct NearestFaceUserData_Hit {
+ float dist;
+ float dist_bias;
+ int index;
+ BMFace *face;
+};
+
+struct NearestFaceUserData {
+ float mval_fl[2];
+ bool use_select_bias;
+ bool use_cycle;
+ int cycle_index_prev;
+
+ struct NearestFaceUserData_Hit hit;
+ struct NearestFaceUserData_Hit hit_cycle;
+};
+
static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index)
{
- struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } *data = userData;
+ struct NearestFaceUserData *data = userData;
+ float dist_test, dist_test_bias;
- if (data->pass == 0) {
- if (index <= data->lastIndex)
- return;
- }
- else {
- if (index > data->lastIndex)
- return;
+ dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
+
+ if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
- if (data->dist > 3) {
- const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+ if (dist_test_bias < data->hit.dist_bias) {
+ data->hit.dist_bias = dist_test_bias;
+ data->hit.dist = dist_test;
+ data->hit.index = index;
+ data->hit.face = efa;
+ }
- if (dist_test < data->dist) {
- data->dist = dist_test;
- data->closest = efa;
- data->closestIndex = index;
+ if (data->use_cycle) {
+ if ((data->hit_cycle.face == NULL) &&
+ (index > data->cycle_index_prev) &&
+ (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+ {
+ data->hit_cycle.dist_bias = dist_test_bias;
+ data->hit_cycle.dist = dist_test;
+ data->hit_cycle.index = index;
+ data->hit_cycle.face = efa;
}
}
}
-BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
+
+BMFace *EDBM_face_find_nearest_ex(
+ ViewContext *vc, float *r_dist,
+ float *r_dist_center,
+ const bool use_select_bias, const bool use_cycle,
+ BMFace **r_efa_zbuf)
{
+ BMesh *bm = vc->em->bm;
- if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
+ if (V3D_IS_ZBUF(vc->v3d)) {
+ float dist_test = 0.0f;
unsigned int index;
BMFace *efa;
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
- index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
- efa = index ? BM_face_at_index_find(vc->em->bm, index - 1) : NULL;
+ index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]);
+ efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
- if (efa) {
- struct { float mval_fl[2]; float dist; BMFace *toFace; } data;
+ if (r_efa_zbuf) {
+ *r_efa_zbuf = efa;
+ }
+
+ /* exception for faces (verts don't need this) */
+ if (r_dist_center && efa) {
+ struct NearestFaceUserData_ZBuf data;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
data.dist = FLT_MAX;
- data.toFace = efa;
+ data.face_test = efa;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__getDistance, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- if ((vc->em->selectmode == SCE_SELECT_FACE) || (data.dist < *r_dist)) { /* only faces, no dist check */
- *r_dist = data.dist;
+ *r_dist_center = data.dist;
+ }
+ /* end exception */
+
+ if (efa) {
+ if (dist_test < *r_dist) {
+ *r_dist = dist_test;
return efa;
}
}
-
return NULL;
}
else {
- struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } data;
- static int lastSelectedIndex = 0;
- static BMFace *lastSelected = NULL;
+ struct NearestFaceUserData data = {{0}};
+ const struct NearestFaceUserData_Hit *hit;
+ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
- if (lastSelected && BM_face_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) {
- lastSelectedIndex = 0;
- lastSelected = NULL;
+ static int prev_select_index = 0;
+ static const BMFace *prev_select_elem = NULL;
+
+ if ((use_cycle == false) ||
+ (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index))))
+ {
+ prev_select_index = 0;
+ prev_select_elem = NULL;
}
- data.lastIndex = lastSelectedIndex;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.dist = *r_dist;
- data.closest = NULL;
- data.closestIndex = 0;
+ data.use_select_bias = use_select_bias;
+ data.use_cycle = use_cycle;
+ data.hit.dist = data.hit_cycle.dist = \
+ data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+ data.cycle_index_prev = prev_select_index;
- data.pass = 0;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
- if (data.dist > 3.0f) {
- data.pass = 1;
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
+ *r_dist = hit->dist;
+ if (r_dist_center) {
+ *r_dist_center = hit->dist;
}
- *r_dist = data.dist;
- lastSelected = data.closest;
- lastSelectedIndex = data.closestIndex;
+ prev_select_elem = hit->face;
+ prev_select_index = hit->index;
- return data.closest;
+ return hit->face;
}
}
+BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
+{
+ return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+}
+
+#undef FIND_NEAR_SELECT_BIAS
+#undef FIND_NEAR_CYCLE_THRESHOLD_MIN
+
+
/* best distance based on screen coords.
* use em->selectmode to define how to use
* selected vertices and edges get disadvantage
@@ -643,35 +875,78 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
{
BMEditMesh *em = vc->em;
- float dist = ED_view3d_select_dist_px();
-
- *r_eve = NULL;
- *r_eed = NULL;
- *r_efa = NULL;
+ static short mval_prev[2] = {-1, -1};
+ /* only cycle while the mouse remains still */
+ const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1]));
+ const float dist_init = ED_view3d_select_dist_px();
+ /* since edges select lines, we give dots advantage of ~20 pix */
+ const float dist_margin = (dist_init / 2);
+ float dist = dist_init;
+ BMFace *efa_zbuf = NULL;
+ BMEdge *eed_zbuf = NULL;
+ BMVert *eve = NULL;
+ BMEdge *eed = NULL;
+ BMFace *efa = NULL;
+
+
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- view3d_validate_backbuf(vc);
-
- if (em->selectmode & SCE_SELECT_VERTEX)
- *r_eve = EDBM_vert_find_nearest(vc, &dist, BM_ELEM_SELECT, 0);
- if (em->selectmode & SCE_SELECT_FACE)
- *r_efa = EDBM_face_find_nearest(vc, &dist);
+ ED_view3d_backbuf_validate(vc);
+
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
+ efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
+ if (efa && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ }
+
+ if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
+ float dist_center = 0.0f;
+ float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
+ eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
+ if (eed && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ }
- dist -= 20; /* since edges select lines, we give dots advantage of 20 pix */
- if (em->selectmode & SCE_SELECT_EDGE)
- *r_eed = EDBM_edge_find_nearest(vc, &dist);
+ if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
+ eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
+ }
/* return only one of 3 pointers, for frontbuffer redraws */
- if (*r_eed) {
- *r_efa = NULL; *r_eve = NULL;
+ if (eve) {
+ efa = NULL; eed = NULL;
}
- else if (*r_efa) {
- *r_eve = NULL;
+ else if (eed) {
+ efa = NULL;
}
-
- return (*r_eve || *r_eed || *r_efa);
+
+ /* there may be a face under the cursor, who's center if too far away
+ * use this if all else fails, it makes sense to select this */
+ if ((eve || eed || efa) == 0) {
+ if (eed_zbuf) {
+ eed = eed_zbuf;
+ }
+ else if (efa_zbuf) {
+ efa = efa_zbuf;
+ }
+ }
+
+ mval_prev[0] = vc->mval[0];
+ mval_prev[1] = vc->mval[1];
+
+ *r_eve = eve;
+ *r_eed = eed;
+ *r_efa = efa;
+
+ return (eve || eed || efa);
}
+/** \} */
+
+
/* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
static EnumPropertyItem prop_similar_compare_types[] = {
{SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
@@ -1286,7 +1561,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
em = vc.em;
/* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
- view3d_validate_backbuf(&vc);
+ ED_view3d_backbuf_validate(&vc);
eed = EDBM_edge_find_nearest(&vc, &dist);
if (eed == NULL) {
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 93ebbbcf620..54acf4abf7c 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -96,7 +96,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
}
BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT,
- smooth, SUBD_FALLOFF_ROOT, false,
+ smooth, SUBD_FALLOFF_INVSQUARE, false,
fractal, along_normal,
cuts,
SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"),
@@ -492,7 +492,7 @@ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT))
+ if (!EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, true))
return OPERATOR_CANCELLED;
EDBM_update_generic(em, true, true);
@@ -2049,9 +2049,7 @@ static int edbm_merge_exec(bContext *C, wmOperator *op)
ok = merge_firstlast(em, true, uvs, op);
break;
case 5:
- ok = true;
- if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT))
- ok = false;
+ ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs);
break;
default:
BLI_assert(0);
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index 86991d7dfeb..f497cd7a1aa 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -748,7 +748,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C,
}
/* Clear Mask */
-static int mesh_customdata_clear_mask_poll(bContext *C)
+static int mesh_customdata_mask_clear_poll(bContext *C)
{
Object *ob = ED_object_context(C);
if (ob && ob->type == OB_MESH) {
@@ -772,7 +772,7 @@ static int mesh_customdata_clear_mask_poll(bContext *C)
}
return false;
}
-static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op))
+static int mesh_customdata_mask_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
int ret_a = mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK);
int ret_b = mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_GRID_PAINT_MASK);
@@ -787,24 +787,24 @@ static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op))
}
}
-void MESH_OT_customdata_clear_mask(wmOperatorType *ot)
+void MESH_OT_customdata_mask_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Sculpt-Mask Data";
- ot->idname = "MESH_OT_customdata_clear_mask";
+ ot->idname = "MESH_OT_customdata_mask_clear";
ot->description = "Clear vertex sculpt masking data from the mesh";
/* api callbacks */
- ot->exec = mesh_customdata_clear_mask_exec;
- ot->poll = mesh_customdata_clear_mask_poll;
+ ot->exec = mesh_customdata_mask_clear_exec;
+ ot->poll = mesh_customdata_mask_clear_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* Clear Skin */
-static int mesh_customdata_clear_skin_poll(bContext *C)
+static bool mesh_customdata_skin_has(bContext *C)
{
Object *ob = ED_object_context(C);
@@ -819,21 +819,60 @@ static int mesh_customdata_clear_skin_poll(bContext *C)
}
return false;
}
-static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op))
+
+static int mesh_customdata_skin_add_poll(bContext *C)
+{
+ return !mesh_customdata_skin_has(C);
+}
+
+static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ Mesh *me = ob->data;
+
+ BKE_mesh_ensure_skin_customdata(me);
+
+ DAG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_customdata_skin_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Skin Data";
+ ot->idname = "MESH_OT_customdata_skin_add";
+ ot->description = "Add a vertex skin layer";
+
+ /* api callbacks */
+ ot->exec = mesh_customdata_skin_add_exec;
+ ot->poll = mesh_customdata_skin_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int mesh_customdata_skin_clear_poll(bContext *C)
+{
+ return mesh_customdata_skin_has(C);
+}
+
+static int mesh_customdata_skin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN);
}
-void MESH_OT_customdata_clear_skin(wmOperatorType *ot)
+void MESH_OT_customdata_skin_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Skin Data";
- ot->idname = "MESH_OT_customdata_clear_skin";
+ ot->idname = "MESH_OT_customdata_skin_clear";
ot->description = "Clear vertex skin layer";
/* api callbacks */
- ot->exec = mesh_customdata_clear_skin_exec;
- ot->poll = mesh_customdata_clear_skin_poll;
+ ot->exec = mesh_customdata_skin_clear_exec;
+ ot->poll = mesh_customdata_skin_clear_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index c7355120a57..9226146bc51 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -232,8 +232,9 @@ void MESH_OT_uv_texture_remove(struct wmOperatorType *ot);
void MESH_OT_vertex_color_add(struct wmOperatorType *ot);
void MESH_OT_vertex_color_remove(struct wmOperatorType *ot);
/* no create_mask yet */
-void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot);
-void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot);
+void MESH_OT_customdata_mask_clear(struct wmOperatorType *ot);
+void MESH_OT_customdata_skin_add(struct wmOperatorType *ot);
+void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot);
void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot);
void MESH_OT_drop_named_image(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 440ab14dacd..0d9f6f2a0be 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -325,7 +325,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
if (createob) {
/* create new object */
- obedit = ED_object_add_type(C, OB_MESH, co, rot, false, lay);
+ obedit = ED_object_add_type(C, OB_MESH, "Navmesh", co, rot, false, lay);
}
else {
obedit = base->object;
@@ -429,7 +429,6 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
obedit->gameflag &= ~OB_COLLISION;
obedit->gameflag |= OB_NAVMESH;
obedit->body_type = OB_BODY_TYPE_NAVMESH;
- rename_id((ID *)obedit, "Navmesh");
}
BKE_mesh_ensure_navmesh(obedit->data);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 126d1cb0ad9..197df48d688 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -151,8 +151,9 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_uv_texture_remove);
WM_operatortype_append(MESH_OT_vertex_color_add);
WM_operatortype_append(MESH_OT_vertex_color_remove);
- WM_operatortype_append(MESH_OT_customdata_clear_mask);
- WM_operatortype_append(MESH_OT_customdata_clear_skin);
+ WM_operatortype_append(MESH_OT_customdata_mask_clear);
+ WM_operatortype_append(MESH_OT_customdata_skin_add);
+ WM_operatortype_append(MESH_OT_customdata_skin_clear);
WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add);
WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear);
WM_operatortype_append(MESH_OT_drop_named_image);
@@ -409,7 +410,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
/* use KM_CLICK because same key is used for tweaks */
kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "rotate_source", true);
- kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "rotate_source", false);
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", XKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 00d79b22e99..2491685161c 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -1082,11 +1082,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int
* on an edge in the backbuf, we can still select a face */
float dummy_dist;
- *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL);
+ *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist);
}
else {
/* sample only on the exact position */
- *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+ *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]);
}
if ((*index) == 0 || (*index) > (unsigned int)me->totpoly)
@@ -1248,11 +1248,11 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
* on an face in the backbuf, we can still select a vert */
float dummy_dist;
- *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL);
+ *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist);
}
else {
/* sample only on the exact position */
- *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+ *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]);
}
if ((*index) == 0 || (*index) > (unsigned int)me->totvert)
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 37faa7ba664..27d77f0635e 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -394,8 +394,11 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
/* For object add primitive operators.
* Do not call undo push in this function (users of this function have to). */
-Object *ED_object_add_type(bContext *C, int type, const float loc[3], const float rot[3],
- bool enter_editmode, unsigned int layer)
+Object *ED_object_add_type(
+ bContext *C,
+ int type, const char *name,
+ const float loc[3], const float rot[3],
+ bool enter_editmode, unsigned int layer)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -406,7 +409,7 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
/* deselects all, sets scene->basact */
- ob = BKE_object_add(bmain, scene, type);
+ ob = BKE_object_add(bmain, scene, type, name);
BASACT->lay = ob->lay = layer;
/* editor level activate, notifiers */
ED_base_object_activate(C, BASACT);
@@ -447,7 +450,7 @@ static int object_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
radius = RNA_float_get(op->ptr, "radius");
- ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer);
+ ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, layer);
if (ob->type == OB_LATTICE) {
/* lattice is a special case!
@@ -504,9 +507,9 @@ static int effector_add_exec(bContext *C, wmOperator *op)
if (type == PFIELD_GUIDE) {
Curve *cu;
- ob = ED_object_add_type(C, OB_CURVE, loc, rot, false, layer);
+ const char *name = CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide");
+ ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, layer);
- rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide"));
cu = ob->data;
cu->flag |= CU_PATH | CU_3D;
ED_object_editmode_enter(C, 0);
@@ -516,9 +519,9 @@ static int effector_add_exec(bContext *C, wmOperator *op)
ED_object_editmode_exit(C, EM_FREEDATA);
}
else {
- ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
+ const char *name = CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field");
+ ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, layer);
BKE_object_obdata_size_init(ob, dia);
- rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field"));
if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
ob->empty_drawtype = OB_SINGLE_ARROW;
}
@@ -569,7 +572,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_CAMERA, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, layer);
if (v3d) {
if (v3d->camera == NULL)
@@ -626,7 +629,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (obedit == NULL || obedit->type != OB_MBALL) {
- obedit = ED_object_add_type(C, OB_MBALL, loc, rot, true, layer);
+ obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, layer);
newob = true;
}
else {
@@ -685,7 +688,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
if (obedit && obedit->type == OB_FONT)
return OPERATOR_CANCELLED;
- obedit = ED_object_add_type(C, OB_FONT, loc, rot, enter_editmode, layer);
+ obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, layer);
BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
@@ -729,7 +732,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
- obedit = ED_object_add_type(C, OB_ARMATURE, loc, rot, true, layer);
+ obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, layer);
ED_object_editmode_enter(C, 0);
newob = true;
}
@@ -786,7 +789,7 @@ static int object_empty_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, layer);
BKE_object_empty_draw_type_set(ob, type);
BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
@@ -846,7 +849,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_EMPTY, NULL, rot, false, layer);
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, layer);
/* add under the mouse */
ED_object_location_from_view(C, ob->loc);
@@ -916,13 +919,11 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_LAMP, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_LAMP, get_lamp_defname(type), loc, rot, false, layer);
BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
la = (Lamp *)ob->data;
la->type = type;
- rename_id(&ob->id, get_lamp_defname(type));
- rename_id(&la->id, get_lamp_defname(type));
if (BKE_scene_use_new_shading_nodes(scene)) {
ED_node_shader_default(C, &la->id);
@@ -988,8 +989,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
if (group) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer);
- rename_id(&ob->id, group->id.name + 2);
+ Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer);
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
id_lib_extern(&group->id);
@@ -1044,7 +1044,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- ob = ED_object_add_type(C, OB_SPEAKER, loc, rot, false, layer);
+ ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, layer);
/* to make it easier to start using this immediately in NLA, a default sound clip is created
* ready to be moved around to retime the sound and/or make new sound clips
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 578335a385b..b382fbafcfd 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -775,11 +775,7 @@ static int bake(
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
- /* rotation */
- normalize_m4_m4(highpoly[i].rotmat, highpoly[i].imat);
- zero_v3(highpoly[i].rotmat[3]);
- if (is_negative_m4(highpoly[i].rotmat))
- negate_mat3_m4(highpoly[i].rotmat);
+ highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);
i++;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index d459dd417c7..f214741467f 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1662,7 +1662,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
Object *obt;
/* add new target object */
- obt = BKE_object_add(bmain, scene, OB_EMPTY);
+ obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
/* set layers OK */
newbase = BASACT;
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index b39e8470a95..a7802b6a411 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -325,7 +325,7 @@ static bool data_transfer_exec_is_object_valid(
static int data_transfer_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Object *ob_src = CTX_data_active_object(C);
+ Object *ob_src = ED_object_active_context(C);
ListBase ctx_objects;
CollectionPointerLink *ctx_ob_dst;
@@ -419,7 +419,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
/* Note this context poll is only really partial, it cannot check for all possible invalid cases. */
static int data_transfer_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_active_context(C);
ID *data = (ob) ? ob->data : NULL;
return (ob && ob->type == OB_MESH && data);
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 76e84e67972..1769b3a8527 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1771,6 +1771,77 @@ void OBJECT_OT_game_property_remove(wmOperatorType *ot)
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX);
}
+#define GAME_PROPERTY_MOVE_UP 1
+#define GAME_PROPERTY_MOVE_DOWN -1
+
+static int game_property_move(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bProperty *prop;
+ bProperty *otherprop = NULL;
+ const int index = RNA_int_get(op->ptr, "index");
+ const int dir = RNA_int_get(op->ptr, "direction");
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ prop = BLI_findlink(&ob->prop, index);
+ /* invalid index */
+ if (prop == NULL)
+ return OPERATOR_CANCELLED;
+
+ if (dir == GAME_PROPERTY_MOVE_UP) {
+ otherprop = prop->prev;
+ }
+ else if (dir == GAME_PROPERTY_MOVE_DOWN) {
+ otherprop = prop->next;
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (prop && otherprop) {
+ BLI_listbase_swaplinks(&ob->prop, prop, otherprop);
+
+ WM_event_add_notifier(C, NC_LOGIC, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void OBJECT_OT_game_property_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_property_move[] = {
+ {GAME_PROPERTY_MOVE_UP, "UP", 0, "Up", ""},
+ {GAME_PROPERTY_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Move Game Property";
+ ot->description = "Move game property";
+ ot->idname = "OBJECT_OT_game_property_move";
+
+ /* api callbacks */
+ ot->exec = game_property_move;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to move", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_enum(ot->srna, "direction", direction_property_move, 0, "Direction",
+ "Direction for moving the property");
+}
+
+#undef GAME_PROPERTY_MOVE_UP
+#undef GAME_PROPERTY_MOVE_DOWN
+
#define COPY_PROPERTIES_REPLACE 1
#define COPY_PROPERTIES_MERGE 2
#define COPY_PROPERTIES_COPY 3
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 1d764ced524..8797b75a801 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -448,11 +448,12 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit)
Base *base, *basedit;
Object *ob;
- ob = BKE_object_add(bmain, scene, OB_EMPTY);
+ ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
basedit = BKE_scene_base_find(scene, obedit);
- base = BKE_scene_base_find(scene, ob);
+ base = scene->basact;
base->lay = ob->lay = obedit->lay;
+ BLI_assert(scene->basact->object == ob);
/* icky, BKE_object_add sets new base as active.
* so set it back to the original edit object */
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index d535457fc5b..2801d2711e7 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -94,6 +94,7 @@ void OBJECT_OT_game_property_new(struct wmOperatorType *ot);
void OBJECT_OT_game_property_remove(struct wmOperatorType *ot);
void OBJECT_OT_game_property_copy(struct wmOperatorType *ot);
void OBJECT_OT_game_property_clear(struct wmOperatorType *ot);
+void OBJECT_OT_game_property_move(struct wmOperatorType *ot);
void OBJECT_OT_logic_bricks_copy(struct wmOperatorType *ot);
void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index ac5ec1976ab..1cee54c33fa 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -459,7 +459,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
if (totvert == 0) return 0;
/* add new mesh */
- obn = BKE_object_add(bmain, scene, OB_MESH);
+ obn = BKE_object_add(bmain, scene, OB_MESH, NULL);
me = obn->data;
me->totvert = totvert;
@@ -1704,7 +1704,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *
NULL,
me->totvert);
- arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE);
+ arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL);
BKE_object_transform_copy(arm_ob, skin_ob);
arm = arm_ob->data;
arm->layer = 1;
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 422f0c12e51..00c6a41423a 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -206,6 +206,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_game_property_remove);
WM_operatortype_append(OBJECT_OT_game_property_copy);
WM_operatortype_append(OBJECT_OT_game_property_clear);
+ WM_operatortype_append(OBJECT_OT_game_property_move);
WM_operatortype_append(OBJECT_OT_logic_bricks_copy);
WM_operatortype_append(OBJECT_OT_game_physics_copy);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 2d981594524..19648c291f7 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -342,12 +342,10 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
Base *newbase, *oldbase = BASACT;
char name[MAX_ID_NAME + 4];
- /* Add new object for the proxy */
- newob = BKE_object_add(bmain, scene, OB_EMPTY);
-
BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
- rename_id(&newob->id, name);
+ /* Add new object for the proxy */
+ newob = BKE_object_add(bmain, scene, OB_EMPTY, name);
/* set layers OK */
newbase = BASACT; /* BKE_object_add sets active... */
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 92fe5ded4dd..340b662c0ef 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -939,8 +939,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* convert the offset to parent space */
BKE_object_to_mat4(ob, obmat);
- copy_v3_v3(centn, cent);
- mul_mat3_m4_v3(obmat, centn); /* omit translation part */
+ mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
add_v3_v3(ob->loc, centn);
@@ -970,8 +969,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
ob_other->flag |= OB_DONE;
DAG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA);
- copy_v3_v3(centn, cent);
- mul_mat3_m4_v3(ob_other->obmat, centn); /* omit translation part */
+ mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
add_v3_v3(ob_other->loc, centn);
BKE_object_where_is_calc(scene, ob_other);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index f885cbbb24f..960b29ae38e 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -2062,7 +2062,7 @@ void ED_vgroup_mirror(Object *ob,
/* object mode / weight paint */
MVert *mv, *mv_mirr;
int vidx, vidx_mirr;
- const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
if (me->dvert == NULL) {
goto cleanup;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index e714dfc464c..5349377f6ff 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -400,12 +400,12 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
/* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */
view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats);
- if ((data->vc.v3d->drawtype>OB_WIRE) && (data->vc.v3d->flag & V3D_ZBUF_SELECT)) {
+ if (V3D_IS_ZBUF(data->vc.v3d)) {
if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- view3d_validate_backbuf(&data->vc);
+ ED_view3d_backbuf_validate(&data->vc);
/* we may need to force an update here by setting the rv3d as dirty
* for now it seems ok, but take care!:
* rv3d->depths->dirty = 1; */
@@ -443,8 +443,8 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
float depth;
/* nothing to do */
- if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0)
- return 1;
+ if (!V3D_IS_ZBUF(v3d))
+ return true;
/* used to calculate here but all callers have the screen_co already, so pass as arg */
#if 0
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 9b4f128ef86..c8b944f7d2a 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -348,6 +348,7 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
if (changed) {
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* done */
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 5c6744b0248..54429f9f066 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -44,6 +44,7 @@ void OBJECT_OT_material_slot_assign(struct wmOperatorType *ot);
void OBJECT_OT_material_slot_select(struct wmOperatorType *ot);
void OBJECT_OT_material_slot_deselect(struct wmOperatorType *ot);
void OBJECT_OT_material_slot_copy(struct wmOperatorType *ot);
+void OBJECT_OT_material_slot_move(struct wmOperatorType *ot);
void MATERIAL_OT_new(struct wmOperatorType *ot);
void TEXTURE_OT_new(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 2f279122ae4..2ba1e615a9e 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -189,11 +189,15 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
*/
/* TODO(sergey): Need to check has_combined here? */
if (iuser->passtype == SCE_PASS_COMBINED) {
+ RenderView *rv;
size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
+ rv = RE_RenderViewGetById(rr, view_id);
+
/* find current float rect for display, first case is after composite... still weak */
- rectf = RE_RenderViewGetRectf(rr, view_id);
- if (rectf == NULL) {
- if (RE_RenderViewGetRect32(rr, view_id)) {
+ if (rv->rectf)
+ rectf = rv->rectf;
+ else {
+ if (rv->rect32) {
/* special case, currently only happens with sequencer rendering,
* which updates the whole frame, so we can only mark display buffer
* as invalid here (sergey)
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index ded2489e1e5..7fbdf9dc66b 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -248,6 +248,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
Object *camera = NULL;
ImBuf *ibuf;
float winmat[4][4];
+ float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf;
int sizex = oglrender->sizex;
int sizey = oglrender->sizey;
const short view_context = (v3d != NULL);
@@ -271,7 +272,6 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
if (ibuf) {
- float *rectf;
ImBuf *linear_ibuf;
BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
@@ -292,7 +292,6 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf);
}
- rectf = RE_RenderViewGetRectf(rr, oglrender->view_id);
memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);
IMB_freeImBuf(linear_ibuf);
@@ -317,10 +316,12 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect);
+ BLI_assert(rectf != NULL);
+
for (i = 0; i < sizex * sizey * 4; i += 4) {
float col_src[4];
rgba_uchar_to_float(col_src, &gp_rect[i]);
- blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src);
+ blend_color_mix_float(&rectf[i], &rectf[i], col_src);
}
GPU_offscreen_unbind(oglrender->ofs, true);
@@ -338,7 +339,9 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
/* render 3d view */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- /*int is_ortho = scene->r.mode & R_ORTHO;*/
+#if 0
+ const bool is_ortho = (scene->r.mode & R_ORTHO) != 0;
+#endif
camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat);
if (camera->type == OB_CAMERA) {
@@ -443,8 +446,8 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
if (rect) {
int profile_to;
- float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id);
-
+ float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf;
+
if (BKE_scene_check_color_management_enabled(scene))
profile_to = IB_PROFILE_LINEAR_RGB;
else
@@ -475,12 +478,14 @@ static void screen_opengl_render_write(OGLRender *oglrender)
rr = RE_AcquireResultRead(oglrender->re);
+ BKE_render_result_stamp_info(scene, camera, rr);
+
BKE_image_path_from_imformat(
name, scene->r.pic, oglrender->bmain->name, scene->r.cfra,
&scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL);
/* write images as individual images or stereo */
- ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, camera, false, name);
+ ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name);
RE_ReleaseResultImage(oglrender->re);
@@ -802,7 +807,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
}
}
else {
- ok = RE_WriteRenderViewsImage(op->reports, rr, scene, scene->camera, true, name);
+ ok = RE_WriteRenderViewsImage(op->reports, rr, scene, true, name);
if (ok) {
printf("Saved: %s", name);
BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index 6aaad98f946..f98083f7e74 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -47,6 +47,7 @@ void ED_operatortypes_render(void)
WM_operatortype_append(OBJECT_OT_material_slot_select);
WM_operatortype_append(OBJECT_OT_material_slot_deselect);
WM_operatortype_append(OBJECT_OT_material_slot_copy);
+ WM_operatortype_append(OBJECT_OT_material_slot_move);
WM_operatortype_append(MATERIAL_OT_new);
WM_operatortype_append(TEXTURE_OT_new);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index e6fbfda3067..65d4c2301a9 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -525,6 +525,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
{
Render *re;
+ RenderView *rv;
RenderResult rres;
char name[32];
int offx = 0;
@@ -549,10 +550,15 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
/* test if something rendered ok */
re = RE_GetRender(name);
+ if (re == NULL)
+ return false;
+
+ RE_AcquireResultImageViews(re, &rres);
+
/* material preview only needs monoscopy (view 0) */
- RE_AcquireResultImage(re, &rres, 0);
+ rv = RE_RenderViewGetById(&rres, 0);
- if (rres.rectf) {
+ if (rv->rectf) {
if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) {
@@ -577,7 +583,7 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
}
}
- RE_ReleaseResultImage(re);
+ RE_ReleaseResultImageViews(re, &rres);
return ok;
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 3de21536148..3b8b874a462 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -41,8 +41,9 @@
#include "DNA_space_types.h"
#include "DNA_world_types.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_math_vector.h"
#include "BLF_translation.h"
@@ -202,7 +203,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
if (nurbs) {
for (nu = nurbs->first; nu; nu = nu->next)
if (isNurbsel(nu))
- nu->mat_nr = nu->charidx = ob->actcol - 1;
+ nu->mat_nr = ob->actcol - 1;
}
}
else if (ob->type == OB_FONT) {
@@ -381,6 +382,74 @@ void OBJECT_OT_material_slot_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
+static int material_slot_move_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_context(C);
+
+ unsigned int *slot_remap;
+ int index_pair[2];
+
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (!ob || ob->totcol < 2) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* up */
+ if (dir == 1 && ob->actcol > 1) {
+ index_pair[0] = ob->actcol - 2;
+ index_pair[1] = ob->actcol - 1;
+ ob->actcol--;
+ }
+ /* down */
+ else if (dir == -1 && ob->actcol < ob->totcol) {
+ index_pair[0] = ob->actcol - 1;
+ index_pair[1] = ob->actcol - 0;
+ ob->actcol++;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__);
+
+ range_vn_u(slot_remap, ob->totcol, 0);
+
+ slot_remap[index_pair[0]] = index_pair[1];
+ slot_remap[index_pair[1]] = index_pair[0];
+
+ BKE_material_remap_object(ob, slot_remap);
+
+ MEM_freeN(slot_remap);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_material_slot_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem material_slot_move[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Material";
+ ot->idname = "OBJECT_OT_material_slot_move";
+ ot->description = "Move the active material up/down in the list";
+
+ /* api callbacks */
+ ot->exec = material_slot_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
/********************** new material operator *********************/
static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index d786c0cfc36..a0ab8de0101 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -61,6 +61,9 @@
#include "BIF_glutil.h"
#include "BLF_api.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
@@ -149,6 +152,34 @@ void ED_area_do_refresh(bContext *C, ScrArea *sa)
}
/**
+ * Action zones are only updated if the mouse is inside of them, but in some cases (currently only fullscreen icon)
+ * it might be needed to update their properties and redraw if the mouse isn't inside.
+ */
+void ED_area_azones_update(ScrArea *sa, const int mouse_xy[2])
+{
+ AZone *az;
+ bool changed = false;
+
+ for (az = sa->actionzones.first; az; az = az->next) {
+ if (az->type == AZONE_FULLSCREEN) {
+ /* only if mouse is not hovering the azone */
+ if (BLI_rcti_isect_pt_v(&az->rect, mouse_xy) == false) {
+ az->alpha = 0.0f;
+ changed = true;
+
+ /* can break since currently only this is handled here */
+ break;
+ }
+ }
+ }
+
+ if (changed) {
+ sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE;
+ ED_area_tag_redraw(sa);
+ }
+}
+
+/**
* \brief Corner widget use for quitting fullscreen.
*/
static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, float alpha)
@@ -366,6 +397,11 @@ static void region_draw_azone_tria(AZone *az)
glDisable(GL_BLEND);
}
+static void area_azone_tag_update(ScrArea *sa)
+{
+ sa->flag |= AREA_FLAG_ACTIONZONES_UPDATE;
+}
+
static void region_draw_azones(ScrArea *sa, ARegion *ar)
{
AZone *az;
@@ -406,6 +442,10 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
}
else if (az->type == AZONE_FULLSCREEN) {
area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha);
+
+ if (az->alpha != 0.0f) {
+ area_azone_tag_update(sa);
+ }
}
}
}
@@ -2027,6 +2067,196 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_co
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
+#define MAX_METADATA_STR 1024
+
+const char *meta_data_list[] =
+{
+ "File",
+ "Strip",
+ "Note",
+ "Date",
+ "RenderTime",
+ "Marker",
+ "Time",
+ "Frame",
+ "Camera",
+ "Scene"
+};
+
+BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
+{
+ return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]);
+}
+
+static void metadata_draw_imbuf(ImBuf *ibuf, rctf rect, int fontid, const bool is_top)
+{
+ char temp_str[MAX_METADATA_STR];
+ int line_width;
+ int ofs_y = 0;
+ short i;
+ int len;
+ const float height = BLF_height_max(fontid);
+ const float vertical_offset = height + (0.1f * U.widget_unit);
+
+ if (is_top) {
+ for (i = 0; i < 4; i++) {
+ /* first line */
+ if (i == 0) {
+ bool do_newline = false;
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]);
+ if (metadata_is_valid(ibuf, temp_str, 0, len)) {
+ BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit),
+ rect.ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]);
+ if (metadata_is_valid(ibuf, temp_str, 1, len)) {
+ line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit),
+ rect.ymax - vertical_offset, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ do_newline = true;
+ }
+
+ if (do_newline)
+ ofs_y += vertical_offset;
+ }
+ else if (i == 1) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit),
+ rect.ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ }
+ else {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit),
+ rect.ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+ ofs_y += vertical_offset;
+ }
+ }
+ }
+ }
+ else {
+ int ofs_x = 0;
+ for (i = 5; i < 10; i++) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]);
+ if (metadata_is_valid(ibuf, temp_str, i, len)) {
+ BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x,
+ rect.ymin + (0.3f * U.widget_unit), 0.0f);
+ BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
+
+ ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X;
+ }
+ }
+ }
+}
+
+static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
+{
+ char str[MAX_METADATA_STR];
+ short i, count = 0;
+ const float height = BLF_height_max(fontid) + 0.1f * U.widget_unit;
+
+ if (is_top) {
+ if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
+ count++;
+ }
+ for (i = 2; i < 5; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ count++;
+ }
+ }
+ }
+ else {
+ for (i = 5; i < 10; i++) {
+ if (metadata_is_valid(ibuf, str, i, 0)) {
+ count = 1;
+ }
+ }
+ }
+
+ if (count) {
+ return (height * count + (0.1f * U.widget_unit));
+ }
+
+ return 0;
+}
+
+#undef MAX_METADATA_STR
+
+void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float zoomx, float zoomy)
+{
+ float box_y;
+ rctf rect;
+ uiStyle *style = UI_style_get_dpi();
+
+ if (!ibuf->metadata)
+ return;
+
+ /* find window pixel coordinates of origin */
+ glPushMatrix();
+
+ /* offset and zoom using ogl */
+ glTranslatef(x, y, 0.0f);
+ glScalef(zoomx, zoomy, 1.0f);
+
+ BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f, U.dpi);
+
+ /* *** upper box*** */
+
+ /* get needed box height */
+ box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
+
+ if (box_y) {
+ UI_ThemeColor(TH_METADATA_BG);
+
+ /* set up rect */
+ BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymax, frame.ymax + box_y);
+ /* draw top box */
+ glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
+
+ UI_ThemeColor(TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, rect, blf_mono_font, true);
+
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
+
+
+ /* *** lower box*** */
+
+ box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
+
+ if (box_y) {
+ UI_ThemeColor(TH_METADATA_BG);
+
+ /* set up box rect */
+ BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymin - box_y, frame.ymin);
+ /* draw top box */
+ glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(blf_mono_font, BLF_CLIPPING);
+
+ UI_ThemeColor(TH_METADATA_TEXT);
+ metadata_draw_imbuf(ibuf, rect, blf_mono_font, false);
+
+ BLF_disable(blf_mono_font, BLF_CLIPPING);
+ }
+
+ glPopMatrix();
+}
+
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
{
float gridsize, gridstep = 1.0f / 32.0f;
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 6001534e88d..8a8b61e09fe 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -579,25 +579,25 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
continue;
if (type == GL_FLOAT) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
/* add an extra border of pixels so linear looks ok at edges of full image. */
if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
}
else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
}
glEnable(GL_TEXTURE_2D);
@@ -991,7 +991,7 @@ void bgl_get_mats(bglMats *mats)
/**
* \note \a viewdist is only for ortho at the moment.
*/
-void bglPolygonOffset(float viewdist, float dist)
+void bglPolygonOffset(float viewdist, float dist)
{
static float winmat[16], offset = 0.0;
@@ -1007,8 +1007,25 @@ void bglPolygonOffset(float viewdist, float dist)
/* dist is from camera to center point */
- if (winmat[15] > 0.5f) offs = 0.00001f * dist * viewdist; // ortho tweaking
- else offs = 0.0005f * dist; // should be clipping value or so...
+ if (winmat[15] > 0.5f) {
+#if 1
+ offs = 0.00001f * dist * viewdist; // ortho tweaking
+#else
+ static float depth_fac = 0.0f;
+ if (depth_fac == 0.0f) {
+ int depthbits;
+ glGetIntegerv(GL_DEPTH_BITS, &depthbits);
+ depth_fac = 1.0f / (float)((1 << depthbits) - 1);
+ }
+ offs = (-1.0 / winmat[10]) * dist * depth_fac;
+
+ UNUSED_VARS(viewdist);
+#endif
+ }
+ else {
+ /* should be clipping value or so... */
+ offs = 0.0005f * dist;
+ }
winmat[14] -= offs;
offset += offs;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 67c18ac287e..9745d01fc89 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -4252,6 +4252,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_CTRL, 0);
WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", EVT_ACTIONZONE_FULLSCREEN, 0, 0, 0);
+ RNA_boolean_set(kmi->ptr, "use_hide_panels", true);
/* area move after action zones */
WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
@@ -4279,8 +4281,6 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0);
kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0);
RNA_boolean_set(kmi->ptr, "use_hide_panels", true);
- kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", EVT_ACTIONZONE_FULLSCREEN, 0, 0, 0);
- RNA_boolean_set(kmi->ptr, "use_hide_panels", true);
WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 7992767072a..346be5b336e 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -215,7 +215,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
return NULL;
}
-void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj, bool find_prev)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -226,7 +226,7 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
/* check if tile is already pushed */
/* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
- if (!proj) {
+ if (find_prev) {
data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
if (data)
return data;
@@ -445,7 +445,7 @@ void imapaint_region_tiles(ImBuf *ibuf, int x, int y, int w, int h, int *tx, int
*ty = (y >> IMAPAINT_TILE_BITS);
}
-void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
+void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h, bool find_old)
{
ImBuf *tmpibuf = NULL;
int tilex, tiley, tilew, tileh, tx, ty;
@@ -474,7 +474,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
for (ty = tiley; ty <= tileh; ty++)
for (tx = tilex; tx <= tilew; tx++)
- image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false);
+ image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old);
ibuf->userflags |= IB_BITMAPDIRTY;
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index eff604658d9..1ad700b2964 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -1049,7 +1049,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign
for (a = 0; a < tot; a++) {
ED_imapaint_dirty_region(s->image, s->canvas,
region[a].destx, region[a].desty,
- region[a].width, region[a].height);
+ region[a].width, region[a].height, true);
if (s->do_masking) {
/* masking, find original pixels tiles from undo buffer to composite over */
@@ -1306,12 +1306,12 @@ static void paint_2d_fill_add_pixel_byte(
const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
const float color[4], float threshold_sq)
{
- int coordinate;
+ size_t coordinate;
if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
return;
- coordinate = y_px * ibuf->x + x_px;
+ coordinate = ((size_t)y_px) * ibuf->x + x_px;
if (!BLI_BITMAP_TEST(touched, coordinate)) {
float color_f[4];
@@ -1329,12 +1329,12 @@ static void paint_2d_fill_add_pixel_float(
const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched,
const float color[4], float threshold_sq)
{
- int coordinate;
+ size_t coordinate;
if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
return;
- coordinate = y_px * ibuf->x + x_px;
+ coordinate = ((size_t)y_px) * ibuf->x + x_px;
if (!BLI_BITMAP_TEST(touched, coordinate)) {
if (compare_len_squared_v3v3(ibuf->rect_float + 4 * coordinate, color, threshold_sq)) {
@@ -1386,21 +1386,21 @@ void paint_2d_bucket_fill(
if (!mouse_init || !br) {
/* first case, no image UV, fill the whole image */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
if (do_float) {
for (x_px = 0; x_px < ibuf->x; x_px++) {
for (y_px = 0; y_px < ibuf->y; y_px++) {
- blend_color_mix_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
- ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), color_f);
+ blend_color_mix_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
+ ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), color_f);
}
}
}
else {
for (x_px = 0; x_px < ibuf->x; x_px++) {
for (y_px = 0; y_px < ibuf->y; y_px++) {
- blend_color_mix_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
- (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), (unsigned char *)&color_b);
+ blend_color_mix_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), (unsigned char *)&color_b);
}
}
}
@@ -1410,7 +1410,7 @@ void paint_2d_bucket_fill(
* value is within the brush fill threshold from the fill color */
BLI_Stack *stack;
BLI_bitmap *touched;
- int coordinate;
+ size_t coordinate;
int width = ibuf->x;
float image_init[2];
int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
@@ -1428,12 +1428,12 @@ void paint_2d_bucket_fill(
}
/* change image invalidation method later */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
- stack = BLI_stack_new(sizeof(int), __func__);
- touched = BLI_BITMAP_NEW(ibuf->x * ibuf->y, "bucket_fill_bitmap");
+ stack = BLI_stack_new(sizeof(size_t), __func__);
+ touched = BLI_BITMAP_NEW(((size_t)ibuf->x) * ibuf->y, "bucket_fill_bitmap");
- coordinate = (y_px * ibuf->x + x_px);
+ coordinate = (((size_t)y_px) * ibuf->x + x_px);
if (do_float) {
copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate);
@@ -1566,7 +1566,7 @@ void paint_2d_gradient_fill(
do_float = (ibuf->rect_float != NULL);
/* this will be substituted by something else when selection is available */
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
if (do_float) {
for (x_px = 0; x_px < ibuf->x; x_px++) {
@@ -1590,8 +1590,8 @@ void paint_2d_gradient_fill(
/* convert to premultiplied */
mul_v3_fl(color_f, color_f[3]);
color_f[3] *= br->alpha;
- IMB_blend_color_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
- ibuf->rect_float + 4 * (y_px * ibuf->x + x_px),
+ IMB_blend_color_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
+ ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px),
color_f, br->blend);
}
}
@@ -1619,8 +1619,8 @@ void paint_2d_gradient_fill(
linearrgb_to_srgb_v3_v3(color_f, color_f);
rgba_float_to_uchar((unsigned char *)&color_b, color_f);
((unsigned char *)&color_b)[3] *= br->alpha;
- IMB_blend_color_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
- (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px),
+ IMB_blend_color_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
+ (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px),
(unsigned char *)&color_b, br->blend);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index b01d315650f..70127d0d425 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -43,6 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_math_color_blend.h"
#include "BLI_memarena.h"
#include "BLI_threads.h"
@@ -134,6 +135,8 @@ BLI_INLINE unsigned char f_to_char(const float val)
//#define PROJ_DEBUG_PRINT_CLIP 1
#define PROJ_DEBUG_WINCLIP 1
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
/* projectFaceSeamFlags options */
//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */
//#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */
@@ -151,6 +154,13 @@ BLI_INLINE unsigned char f_to_char(const float val)
#define PROJ_FACE_WINDING_INIT 1
#define PROJ_FACE_WINDING_CW 2
+/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
+ * as this number approaches 1.0f the likelihood increases of float precision errors where
+ * it is occluded by an adjacent face */
+#define PROJ_FACE_SCALE_SEAM 0.99f
+#endif /* PROJ_DEBUG_NOSEAMBLEED */
+
+
#define PROJ_SRC_VIEW 1
#define PROJ_SRC_IMAGE_CAM 2
#define PROJ_SRC_IMAGE_VIEW 3
@@ -159,12 +169,6 @@ BLI_INLINE unsigned char f_to_char(const float val)
#define PROJ_VIEW_DATA_ID "view_data"
#define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */
-
-/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
- * as this number approaches 1.0f the likelihood increases of float precision errors where
- * it is occluded by an adjacent face */
-#define PROJ_FACE_SCALE_SEAM 0.99f
-
#define PROJ_BUCKET_NULL 0
#define PROJ_BUCKET_INIT (1 << 0)
// #define PROJ_BUCKET_CLONE_INIT (1<<1)
@@ -190,9 +194,32 @@ typedef struct ProjPaintImage {
unsigned short **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket.
* Here we store the mask rectangle */
bool **valid; /* store flag to enforce validation of undo rectangle */
- int touch;
+ bool touch;
} ProjPaintImage;
+/**
+ * Handle for stroke (operator customdata)
+ */
+typedef struct ProjStrokeHandle {
+ /* Support for painting from multiple views at once,
+ * currently used to impliment summetry painting,
+ * we can assume at least the first is set while painting. */
+ struct ProjPaintState *ps_views[8];
+ int ps_views_tot;
+ int symmetry_flags;
+
+ int orig_brush_size;
+
+ bool need_redraw;
+
+ /* trick to bypass regular paint and allow clone picking */
+ bool is_clone_cursor_pick;
+
+ /* In ProjPaintState, only here for convenience */
+ Scene *scene;
+ Brush *brush;
+} ProjStrokeHandle;
+
/* Main projection painting struct passed to all projection painting functions */
typedef struct ProjPaintState {
View3D *v3d;
@@ -208,24 +235,14 @@ typedef struct ProjPaintState {
Brush *brush;
short tool, blend, mode;
- int orig_brush_size;
+
float brush_size;
Object *ob;
+ /* for symmetry, we need to store modified object matrix */
+ float obmat[4][4];
+ float obmat_imat[4][4];
/* end similarities with ImagePaintState */
- DerivedMesh *dm;
- int dm_totface;
- int dm_totedge;
- int dm_totvert;
- int dm_release;
-
- MVert *dm_mvert;
- MEdge *dm_medge;
- MFace *dm_mface;
- MTFace **dm_mtface;
- MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */
- MTFace *dm_mtface_stencil;
-
Image *stencil_ima;
Image *canvas_ima;
Image *clone_ima;
@@ -236,24 +253,16 @@ typedef struct ProjPaintState {
LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */
unsigned char *bucketFlags; /* store if the bucks have been initialized */
-#ifndef PROJ_DEBUG_NOSEAMBLEED
- char *faceSeamFlags; /* store info about faces, if they are initialized etc*/
- char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */
- float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */
- LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */
-#endif
+
char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */
int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */
int buckets_y;
- ProjPaintImage *projImages;
-
int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */
int image_tot; /* size of projectImages array */
float (*screenCoords)[4]; /* verts projected into floating point screen space */
- float *cavities; /* cavity amount for vertices */
float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */
float screenMax[2];
float screen_width; /* Calculated from screenMin & screenMax */
@@ -272,12 +281,15 @@ typedef struct ProjPaintState {
bool do_mask_normal; /* mask out pixels based on their normals */
bool do_mask_cavity; /* mask out pixels based on cavity */
bool do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */
- float normal_angle; /* what angle to mask at*/
+ float normal_angle; /* what angle to mask at */
+ float normal_angle__cos; /* cos(normal_angle), faster to compare */
float normal_angle_inner;
+ float normal_angle_inner__cos;
float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */
bool do_face_sel; /* quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */
bool is_ortho;
+ bool is_flip_object; /* the object is negative scaled */
bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */
bool is_texbrush; /* only to avoid running */
bool is_maskbrush; /* mask brush is applied before masking */
@@ -302,13 +314,51 @@ typedef struct ProjPaintState {
int bucketMax[2];
int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
- /* redraw */
- bool need_redraw;
-
struct CurveMapping *cavity_curve;
BlurKernel *blurkernel;
+
+
+ /* -------------------------------------------------------------------- */
+ /* Vars shared between multiple views (keep last) */
+ /**
+ * This data is owned by ``ProjStrokeHandle.ps_views[0]``,
+ * all other views re-use the data.
+ */
+
+#define PROJ_PAINT_STATE_SHARED_MEMCPY(ps_dst, ps_src) \
+ MEMCPY_STRUCT_OFS(ps_dst, ps_src, is_shared_user)
+
+#define PROJ_PAINT_STATE_SHARED_CLEAR(ps) \
+ MEMSET_STRUCT_OFS(ps, 0, is_shared_user)
+
+ bool is_shared_user;
+
+ ProjPaintImage *projImages;
+ float *cavities; /* cavity amount for vertices */
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ char *faceSeamFlags; /* store info about faces, if they are initialized etc*/
+ char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */
+ float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */
+ LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */
+#endif
+
SpinLock *tile_lock;
+
+ DerivedMesh *dm;
+ int dm_totface;
+ int dm_totedge;
+ int dm_totvert;
+ int dm_release;
+
+ MVert *dm_mvert;
+ MEdge *dm_medge;
+ MFace *dm_mface;
+ MTFace *dm_mtface_stencil;
+
+ MTFace **dm_mtface;
+ MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */
} ProjPaintState;
typedef union pixelPointer {
@@ -326,25 +376,27 @@ typedef union pixelStore {
typedef struct ProjPixel {
float projCoSS[2]; /* the floating point screen projection of this pixel */
float worldCoSS[3];
+
+ short x_px, y_px;
+
+ unsigned short image_index; /* if anyone wants to paint onto more than 65535 images they can bite me */
+ unsigned char bb_cell_index;
+
+ /* for various reasons we may want to mask out painting onto this pixel */
+ unsigned short mask;
+
/* Only used when the airbrush is disabled.
* Store the max mask value to avoid painting over an area with a lower opacity
* with an advantage that we can avoid touching the pixel at all, if the
* new mask value is lower then mask_accum */
unsigned short *mask_accum;
- /* for various reasons we may want to mask out painting onto this pixel */
- unsigned short mask;
-
- short x_px, y_px;
/* horrible hack, store tile valid flag pointer here to re-validate tiles used for anchored and drag-dot strokes */
bool *valid;
PixelPointer origColor;
PixelStore newColor;
PixelPointer pixel;
-
- short image_index; /* if anyone wants to paint onto more than 32768 images they can bite me */
- unsigned char bb_cell_index;
} ProjPixel;
typedef struct ProjPixelClone {
@@ -474,7 +526,9 @@ static float VecZDepthPersp(
/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
-static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], float w[3], int *side)
+static int project_paint_PickFace(
+ const ProjPaintState *ps, const float pt[2],
+ float w[3], int *r_side)
{
LinkNode *node;
float w_tmp[3];
@@ -531,7 +585,7 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f
}
}
- *side = best_side;
+ *r_side = best_side;
return best_face_index; /* will be -1 or a valid face */
}
@@ -718,7 +772,7 @@ static bool project_bucket_point_occluded(
int face_index;
int isect_ret;
float w[3]; /* not needed when clipping */
- const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
+ const bool do_clip = ps->rv3d ? (ps->rv3d->rflag & RV3D_CLIPPING) != 0 : 0;
/* we could return 0 for 1 face buckets, as long as this function assumes
* that the point its testing is only every originated from an existing face */
@@ -1228,22 +1282,22 @@ static void screen_px_from_persp(
static void project_face_pixel(
const MTFace *tf_other, ImBuf *ibuf_other, const float w[3],
- int side, unsigned char rgba_ub[4], float rgba_f[4])
+ bool side, unsigned char rgba_ub[4], float rgba_f[4])
{
const float *uvCo1, *uvCo2, *uvCo3;
float uv_other[2], x, y;
- uvCo1 = (float *)tf_other->uv[0];
+ uvCo1 = tf_other->uv[0];
if (side == 1) {
- uvCo2 = (float *)tf_other->uv[2];
- uvCo3 = (float *)tf_other->uv[3];
+ uvCo2 = tf_other->uv[2];
+ uvCo3 = tf_other->uv[3];
}
else {
- uvCo2 = (float *)tf_other->uv[1];
- uvCo3 = (float *)tf_other->uv[2];
+ uvCo2 = tf_other->uv[1];
+ uvCo3 = tf_other->uv[2];
}
- interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)w);
+ interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, w);
/* use */
uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y);
@@ -1262,7 +1316,7 @@ static void project_face_pixel(
static float project_paint_uvpixel_mask(
const ProjPaintState *ps,
const int face_index,
- const int side,
+ const bool side,
const float w[3])
{
float mask;
@@ -1327,7 +1381,7 @@ static float project_paint_uvpixel_mask(
/* calculate mask */
if (ps->do_mask_normal) {
MFace *mf = &ps->dm_mface[face_index];
- float no[3], angle;
+ float no[3], angle_cos;
if (mf->flag & ME_SMOOTH) {
const short *no1, *no2, *no3;
no1 = ps->dm_mvert[mf->v1].no;
@@ -1366,9 +1420,13 @@ static float project_paint_uvpixel_mask(
#endif
}
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(no);
+ }
+
/* now we can use the normal as a mask */
if (ps->is_ortho) {
- angle = angle_normalized_v3v3(ps->viewDir, no);
+ angle_cos = dot_v3v3(ps->viewDir, no);
}
else {
/* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
@@ -1389,15 +1447,18 @@ static float project_paint_uvpixel_mask(
viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1]));
viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2]));
normalize_v3(viewDirPersp);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(viewDirPersp);
+ }
- angle = angle_normalized_v3v3(viewDirPersp, no);
+ angle_cos = dot_v3v3(viewDirPersp, no);
}
- if (angle >= ps->normal_angle) {
+ if (angle_cos <= ps->normal_angle__cos) {
return 0.0f; /* outsize the normal limit*/
}
- else if (angle > ps->normal_angle_inner) {
- mask *= (ps->normal_angle - angle) / ps->normal_angle_range;
+ else if (angle_cos < ps->normal_angle_inner__cos) {
+ mask *= (ps->normal_angle - acosf(angle_cos)) / ps->normal_angle_range;
} /* otherwise no mask normal is needed, were within the limit */
}
@@ -1440,10 +1501,10 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
if (generate_tile) {
volatile void *undorect;
if (tinf->masked) {
- undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true);
+ undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true, false);
}
else {
- undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true);
+ undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true, false);
}
pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
@@ -1470,7 +1531,7 @@ static ProjPixel *project_paint_uvpixel_init(
const int face_index,
const float pixelScreenCo[4],
const float world_spaceCo[3],
- const int side,
+ const bool side,
const float w[3])
{
ProjPixel *projPixel;
@@ -1591,7 +1652,7 @@ static ProjPixel *project_paint_uvpixel_init(
}
else {
float co[2];
- sub_v2_v2v2(co, projPixel->projCoSS, (float *)ps->cloneOffset);
+ sub_v2_v2v2(co, projPixel->projCoSS, ps->cloneOffset);
/* no need to initialize the bucket, we're only checking buckets faces and for this
* the faces are already initialized in project_paint_delayed_face_init(...) */
@@ -1976,7 +2037,10 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa
#define ISECT_ALL4 ((1 << 4) - 1)
/* limit must be a fraction over 1.0f */
-static bool IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
+static bool IsectPT2Df_limit(
+ const float pt[2],
+ const float v1[2], const float v2[2], const float v3[2],
+ const float limit)
{
return ((area_tri_v2(pt, v1, v2) +
area_tri_v2(pt, v2, v3) +
@@ -2043,9 +2107,9 @@ static bool line_rect_clip(
static void project_bucket_clip_face(
- const bool is_ortho,
+ const bool is_ortho, const bool is_flip_object,
const rctf *bucket_bounds,
- float *v1coSS, float *v2coSS, float *v3coSS,
+ const float *v1coSS, const float *v2coSS, const float *v3coSS,
const float *uv1co, const float *uv2co, const float *uv3co,
float bucket_bounds_uv[8][2],
int *tot, bool cull)
@@ -2071,7 +2135,8 @@ static void project_bucket_clip_face(
inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
if (inside_bucket_flag == ISECT_ALL3) {
- flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) !=
+ /* is_flip_object is used here because we use the face winding */
+ flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) !=
(line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
/* all screenspace points are inside the bucket bounding box,
@@ -2193,7 +2258,7 @@ static void project_bucket_clip_face(
float cent[2] = {0.0f, 0.0f};
/*float up[2] = {0.0f, 1.0f};*/
int i;
- short doubles;
+ bool doubles;
(*tot) = 0;
@@ -2404,7 +2469,7 @@ static bool IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot)
{
int i;
- int side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
+ bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
for (i = 1; i < tot; i++) {
if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side)
@@ -2423,7 +2488,8 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot
static void project_paint_face_init(
const ProjPaintState *ps,
const int thread_index, const int bucket_index, const int face_index, const int image_index,
- const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v)
+ const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf,
+ const bool clamp_u, const bool clamp_v)
{
/* Projection vars, to get the 3D locations into screen space */
MemArena *arena = ps->arena_mt[thread_index];
@@ -2448,8 +2514,8 @@ static void project_paint_face_init(
float mask;
float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */
- int side;
- float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
+ bool side;
+ const float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
float *vCo[4]; /* vertex screenspace coords */
@@ -2473,6 +2539,7 @@ static void project_paint_face_init(
float uv_clip[8][2];
int uv_clip_tot;
const bool is_ortho = ps->is_ortho;
+ const bool is_flip_object = ps->is_flip_object;
const bool do_backfacecull = ps->do_backfacecull;
const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
@@ -2534,11 +2601,12 @@ static void project_paint_face_init(
/* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
project_bucket_clip_face(
- is_ortho, bucket_bounds,
+ is_ortho, is_flip_object,
+ bucket_bounds,
v1coSS, v2coSS, v3coSS,
uv1co, uv2co, uv3co,
uv_clip, &uv_clip_tot,
- ps->do_backfacecull || ps->do_occlude);
+ do_backfacecull || ps->do_occlude);
/* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
#if 0
@@ -2851,6 +2919,8 @@ static void project_paint_face_init(
}
}
}
+#else
+ UNUSED_VARS(vCo, threaded);
#endif // PROJ_DEBUG_NOSEAMBLEED
}
@@ -2902,7 +2972,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
ima = ps->projImages[0].ima;
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ project_paint_face_init(
+ ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0,
+ bucket_bounds, ibuf, &tmpibuf,
+ (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0);
}
}
else {
@@ -2926,7 +2999,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
}
/* context switching done */
- project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ project_paint_face_init(
+ ps, thread_index, bucket_index, face_index, image_index,
+ bucket_bounds, ibuf, &tmpibuf,
+ (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0);
}
}
@@ -3078,7 +3154,8 @@ static void proj_paint_state_non_cddm_init(ProjPaintState *ps)
}
}
-static void proj_paint_state_viewport_init(ProjPaintState *ps)
+static void proj_paint_state_viewport_init(
+ ProjPaintState *ps, const char symmetry_flag)
{
float mat[3][3];
float viewmat[4][4];
@@ -3088,7 +3165,19 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps)
ps->viewDir[1] = 0.0f;
ps->viewDir[2] = 1.0f;
- invert_m4_m4(ps->ob->imat, ps->ob->obmat);
+ copy_m4_m4(ps->obmat, ps->ob->obmat);
+
+ if (symmetry_flag) {
+ int i;
+ for (i = 0; i < 3; i++) {
+ if ((symmetry_flag >> i) & 1) {
+ negate_v3(ps->obmat[i]);
+ ps->is_flip_object = !ps->is_flip_object;
+ }
+ }
+ }
+
+ invert_m4_m4(ps->obmat_imat, ps->obmat);
if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
/* normal drawing */
@@ -3098,7 +3187,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps)
copy_m4_m4(viewmat, ps->rv3d->viewmat);
copy_m4_m4(viewinv, ps->rv3d->viewinv);
- ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat);
+ ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat);
ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true);
}
@@ -3151,24 +3240,27 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps)
}
/* same as #ED_view3d_ob_project_mat_get */
- mul_m4_m4m4(vmat, viewmat, ps->ob->obmat);
+ mul_m4_m4m4(vmat, viewmat, ps->obmat);
mul_m4_m4m4(ps->projectMat, winmat, vmat);
}
/* viewDir - object relative */
- invert_m4_m4(ps->ob->imat, ps->ob->obmat);
copy_m3_m4(mat, viewinv);
mul_m3_v3(mat, ps->viewDir);
- copy_m3_m4(mat, ps->ob->imat);
+ copy_m3_m4(mat, ps->obmat_imat);
mul_m3_v3(mat, ps->viewDir);
normalize_v3(ps->viewDir);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(ps->viewDir);
+ }
+
/* viewPos - object relative */
copy_v3_v3(ps->viewPos, viewinv[3]);
- copy_m3_m4(mat, ps->ob->imat);
+ copy_m3_m4(mat, ps->obmat_imat);
mul_m3_v3(mat, ps->viewPos);
- add_v3_v3(ps->viewPos, ps->ob->imat[3]);
+ add_v3_v3(ps->viewPos, ps->obmat_imat[3]);
}
static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int diameter)
@@ -3234,6 +3326,8 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
+#else
+ UNUSED_VARS(diameter);
#endif
}
else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */
@@ -3313,12 +3407,14 @@ static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_th
if (reset_threads)
ps->thread_tot = 1;
- if (ps->thread_tot > 1) {
- ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
- BLI_spin_init(ps->tile_lock);
- }
+ if (ps->is_shared_user == false) {
+ if (ps->thread_tot > 1) {
+ ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
+ BLI_spin_init(ps->tile_lock);
+ }
- image_undo_init_locks();
+ image_undo_init_locks();
+ }
for (a = 0; a < ps->thread_tot; a++) {
ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
@@ -3337,16 +3433,22 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
normal_short_to_float_v3(no, mv->no);
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(no);
+ }
if (ps->is_ortho) {
- if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
+ if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */
ps->vertFlags[a] |= PROJ_VERT_CULL;
}
}
else {
sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co);
normalize_v3(viewDirPersp);
- if (angle_normalized_v3v3(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
+ if (UNLIKELY(ps->is_flip_object)) {
+ negate_v3(viewDirPersp);
+ }
+ if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */
ps->vertFlags[a] |= PROJ_VERT_CULL;
}
}
@@ -3628,7 +3730,7 @@ static bool project_paint_backface_cull(
}
}
else {
- if (line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) {
+ if ((line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) != ps->is_flip_object) {
return true;
}
@@ -3670,7 +3772,8 @@ static void project_paint_prepare_all_faces(
ProjPaintState *ps, MemArena *arena,
const ProjPaintFaceLookup *face_lookup,
ProjPaintLayerClone *layer_clone,
- MTFace *tf_base)
+ MTFace *tf_base,
+ const bool is_multi_view)
{
/* Image Vars - keep track of images we have used */
LinkNode *image_LinkList = NULL;
@@ -3729,20 +3832,21 @@ static void project_paint_prepare_all_faces(
ProjPaintFaceCoSS coSS;
proj_paint_face_coSS_init(ps, mf, &coSS);
- if (project_paint_flt_max_cull(ps, &coSS)) {
- continue;
- }
+ if (is_multi_view == false) {
+ if (project_paint_flt_max_cull(ps, &coSS)) {
+ continue;
+ }
#ifdef PROJ_DEBUG_WINCLIP
- if (project_paint_winclip(ps, mf, &coSS)) {
- continue;
- }
+ if (project_paint_winclip(ps, mf, &coSS)) {
+ continue;
+ }
#endif //PROJ_DEBUG_WINCLIP
-
- if (project_paint_backface_cull(ps, mf, &coSS)) {
- continue;
+ if (project_paint_backface_cull(ps, mf, &coSS)) {
+ continue;
+ }
}
if (tpage_last != tpage) {
@@ -3767,18 +3871,22 @@ static void project_paint_prepare_all_faces(
}
/* build an array of images we use*/
- project_paint_build_proj_ima(ps, arena, image_LinkList);
+ if (ps->is_shared_user == false) {
+ project_paint_build_proj_ima(ps, arena, image_LinkList);
+ }
/* we have built the array, discard the linked list */
BLI_linklist_free(image_LinkList, NULL);
}
/* run once per stroke before projection painting */
-static void project_paint_begin(ProjPaintState *ps)
+static void project_paint_begin(
+ ProjPaintState *ps,
+ const bool is_multi_view, const char symmetry_flag)
{
ProjPaintLayerClone layer_clone;
ProjPaintFaceLookup face_lookup;
- MTFace *tf_base;
+ MTFace *tf_base = NULL;
MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
@@ -3792,10 +3900,13 @@ static void project_paint_begin(ProjPaintState *ps)
ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
+ ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0;
/* paint onto the derived mesh */
- if (!proj_paint_state_dm_init(ps)) {
- return;
+ if (ps->is_shared_user == false) {
+ if (!proj_paint_state_dm_init(ps)) {
+ return;
+ }
}
proj_paint_face_lookup_init(ps, &face_lookup);
@@ -3817,11 +3928,13 @@ static void project_paint_begin(ProjPaintState *ps)
}
/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
- proj_paint_state_non_cddm_init(ps);
+ if (ps->is_shared_user == false) {
+ proj_paint_state_non_cddm_init(ps);
- proj_paint_state_cavity_init(ps);
+ proj_paint_state_cavity_init(ps);
+ }
- proj_paint_state_viewport_init(ps);
+ proj_paint_state_viewport_init(ps, symmetry_flag);
/* calculate vert screen coords
* run this early so we can calculate the x/y resolution of our bucket rect */
@@ -3850,7 +3963,9 @@ static void project_paint_begin(ProjPaintState *ps)
ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
#ifndef PROJ_DEBUG_NOSEAMBLEED
- proj_paint_state_seam_bleed_init(ps);
+ if (ps->is_shared_user == false) {
+ proj_paint_state_seam_bleed_init(ps);
+ }
#endif
proj_paint_state_thread_init(ps, reset_threads);
@@ -3858,7 +3973,7 @@ static void project_paint_begin(ProjPaintState *ps)
proj_paint_state_vert_flags_init(ps);
- project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, tf_base);
+ project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, tf_base, is_multi_view);
}
static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
@@ -3867,7 +3982,7 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
if (ps->tool == PAINT_TOOL_CLONE) {
float projCo[4];
copy_v3_v3(projCo, ED_view3d_cursor3d_get(ps->scene, ps->v3d));
- mul_m4_v3(ps->ob->imat, projCo);
+ mul_m4_v3(ps->obmat_imat, projCo);
projCo[3] = 1.0f;
mul_m4_v4(ps->projectMat, projCo);
@@ -3879,14 +3994,16 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
static void project_paint_end(ProjPaintState *ps)
{
int a;
- ProjPaintImage *projIma;
image_undo_remove_masks();
/* dereference used image buffers */
- for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
- BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
- DAG_id_tag_update(&projIma->ima->id, 0);
+ if (ps->is_shared_user == false) {
+ ProjPaintImage *projIma;
+ for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
+ BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
+ DAG_id_tag_update(&projIma->ima->id, 0);
+ }
}
BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
@@ -3895,68 +4012,81 @@ static void project_paint_end(ProjPaintState *ps)
MEM_freeN(ps->bucketRect);
MEM_freeN(ps->bucketFaces);
MEM_freeN(ps->bucketFlags);
- MEM_freeN(ps->dm_mtface);
- if (ps->do_layer_clone)
- MEM_freeN(ps->dm_mtface_clone);
- if (ps->thread_tot > 1) {
- BLI_spin_end(ps->tile_lock);
- MEM_freeN((void *)ps->tile_lock);
- }
- image_undo_end_locks();
+
+ if (ps->is_shared_user == false) {
+
+ /* must be set for non-shared */
+ BLI_assert(ps->dm_mtface || ps->is_shared_user);
+ if (ps->dm_mtface)
+ MEM_freeN(ps->dm_mtface);
+
+ if (ps->do_layer_clone)
+ MEM_freeN(ps->dm_mtface_clone);
+ if (ps->thread_tot > 1) {
+ BLI_spin_end(ps->tile_lock);
+ MEM_freeN((void *)ps->tile_lock);
+ }
+
+ image_undo_end_locks();
#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->seam_bleed_px > 0.0f) {
- MEM_freeN(ps->vertFaces);
- MEM_freeN(ps->faceSeamFlags);
- MEM_freeN(ps->faceWindingFlags);
- MEM_freeN(ps->faceSeamUVs);
- }
+ if (ps->seam_bleed_px > 0.0f) {
+ MEM_freeN(ps->vertFaces);
+ MEM_freeN(ps->faceSeamFlags);
+ MEM_freeN(ps->faceWindingFlags);
+ MEM_freeN(ps->faceSeamUVs);
+ }
#endif
+ if (ps->do_mask_cavity) {
+ MEM_freeN(ps->cavities);
+ }
+
+ /* copy for subsurf/multires, so throw away */
+ if (ps->dm->type != DM_TYPE_CDDM) {
+ if (ps->dm_mvert) MEM_freeN(ps->dm_mvert);
+ if (ps->dm_mface) MEM_freeN(ps->dm_mface);
+ /* looks like these don't need copying */
+#if 0
+ if (ps->dm_mtface) MEM_freeN(ps->dm_mtface);
+ if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone);
+ if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil);
+#endif
+ }
+
+ if (ps->dm_release)
+ ps->dm->release(ps->dm);
+ }
+
if (ps->blurkernel) {
paint_delete_blur_kernel(ps->blurkernel);
MEM_freeN(ps->blurkernel);
}
- if (ps->do_mask_cavity) {
- MEM_freeN(ps->cavities);
- }
-
if (ps->vertFlags) MEM_freeN(ps->vertFlags);
for (a = 0; a < ps->thread_tot; a++) {
BLI_memarena_free(ps->arena_mt[a]);
}
+}
- /* copy for subsurf/multires, so throw away */
- if (ps->dm->type != DM_TYPE_CDDM) {
- if (ps->dm_mvert) MEM_freeN(ps->dm_mvert);
- if (ps->dm_mface) MEM_freeN(ps->dm_mface);
- /* looks like these don't need copying */
-#if 0
- if (ps->dm_mtface) MEM_freeN(ps->dm_mtface);
- if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone);
- if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil);
-#endif
- }
+/* 1 = an undo, -1 is a redo. */
+static void partial_redraw_single_init(ImagePaintPartialRedraw *pr)
+{
+ pr->x1 = 10000000;
+ pr->y1 = 10000000;
- if (ps->dm_release)
- ps->dm->release(ps->dm);
+ pr->x2 = -1;
+ pr->y2 = -1;
+
+ pr->enabled = 1;
}
-/* 1 = an undo, -1 is a redo. */
static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
{
int tot = PROJ_BOUNDBOX_SQUARED;
while (tot--) {
- pr->x1 = 10000000;
- pr->y1 = 10000000;
-
- pr->x2 = -1;
- pr->y2 = -1;
-
- pr->enabled = 1;
-
+ partial_redraw_single_init(pr);
pr++;
}
}
@@ -4000,6 +4130,8 @@ static bool project_image_refresh_tagged(ProjPaintState *ps)
imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
redraw = 1;
}
+
+ partial_redraw_single_init(pr);
}
projIma->touch = 0; /* clear for reuse */
@@ -4414,7 +4546,8 @@ static void *do_projectpaint_thread(void *ph_v)
const float brush_radius = ps->brush_size;
const float brush_radius_sq = brush_radius * brush_radius; /* avoid a square root with every dist comparison */
- short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA;
+ const bool lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ?
+ 0 : (brush->flag & BRUSH_LOCK_ALPHA) != 0;
LinkNode *smearPixels = NULL;
LinkNode *smearPixels_f = NULL;
@@ -4818,7 +4951,8 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
/* calculate pivot for rotation around seletion if needed */
if (U.uiflag & USER_ORBIT_SELECTION) {
float w[3];
- int side, index;
+ int index;
+ int side;
index = project_paint_PickFace(ps, pos, w, &side);
@@ -4837,7 +4971,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
}
ups->average_stroke_counter++;
- mul_m4_v3(ps->ob->obmat, world);
+ mul_m4_v3(ps->obmat, world);
add_v3_v3(ups->average_stroke_accum, world);
ups->last_stroke_valid = true;
}
@@ -4847,33 +4981,21 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
}
-void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], const float pos[2], const bool eraser, float pressure, float distance, float size)
+static void paint_proj_stroke_ps(
+ const bContext *UNUSED(C), void *ps_handle_p, const float prev_pos[2], const float pos[2],
+ const bool eraser, float pressure, float distance, float size,
+ /* extra view */
+ ProjPaintState *ps
+ )
{
- ProjPaintState *ps = pps;
+ ProjStrokeHandle *ps_handle = ps_handle_p;
Brush *brush = ps->brush;
Scene *scene = ps->scene;
- int a;
ps->brush_size = size;
ps->blend = brush->blend;
if (eraser)
ps->blend = IMB_BLEND_ERASE_ALPHA;
-
- /* clone gets special treatment here to avoid going through image initialization */
- if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
- View3D *v3d = ps->v3d;
- float *cursor = ED_view3d_cursor3d_get(scene, v3d);
- int mval_i[2] = {(int)pos[0], (int)pos[1]};
-
- view3d_operator_needs_opengl(C);
-
- if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor, false, NULL))
- return;
-
- ED_region_tag_redraw(ps->ar);
-
- return;
- }
/* handle gradient and inverted stroke color here */
if (ps->tool == PAINT_TOOL_DRAW) {
@@ -4894,14 +5016,42 @@ void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], co
}
}
- /* continue adding to existing partial redraw rects until redraw */
- if (!ps->need_redraw) {
- for (a = 0; a < ps->image_tot; a++)
- partial_redraw_array_init(ps->projImages[a].partRedrawRect);
+ if (project_paint_op(ps, prev_pos, pos)) {
+ ps_handle->need_redraw = true;
+ project_image_refresh_tagged(ps);
}
+}
+
+
+void paint_proj_stroke(
+ const bContext *C, void *ps_handle_p, const float prev_pos[2], const float pos[2],
+ const bool eraser, float pressure, float distance, float size)
+{
+ int i;
+ ProjStrokeHandle *ps_handle = ps_handle_p;
+
+ /* clone gets special treatment here to avoid going through image initialization */
+ if (ps_handle->is_clone_cursor_pick) {
+ Scene *scene = ps_handle->scene;
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ float *cursor = ED_view3d_cursor3d_get(scene, v3d);
+ int mval_i[2] = {(int)pos[0], (int)pos[1]};
+
+ view3d_operator_needs_opengl(C);
+
+ if (!ED_view3d_autodist(scene, ar, v3d, mval_i, cursor, false, NULL))
+ return;
- if (project_paint_op(ps, prev_pos, pos))
- ps->need_redraw = true;
+ ED_region_tag_redraw(ar);
+
+ return;
+ }
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+ paint_proj_stroke_ps(C, ps_handle_p, prev_pos, pos, eraser, pressure, distance, size, ps);
+ }
}
@@ -5001,6 +5151,9 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
if (ps->normal_angle_range <= 0.0f)
ps->do_mask_normal = false; /* no need to do blending */
+ ps->normal_angle__cos = cosf(ps->normal_angle);
+ ps->normal_angle_inner__cos = cosf(ps->normal_angle_inner);
+
ps->dither = settings->imapaint.dither;
return;
@@ -5008,51 +5161,116 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int mode)
{
- ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
+ ProjStrokeHandle *ps_handle;
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ int i;
+ bool is_multi_view;
+ char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0};
- project_state_init(C, ob, ps, mode);
+ ps_handle = MEM_callocN(sizeof(ProjStrokeHandle), "ProjStrokeHandle");
+ ps_handle->scene = scene;
+ ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint);
- if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) {
+ /* bypass regular stroke logic */
+ if ((ps_handle->brush->imagepaint_tool == PAINT_TOOL_CLONE) &&
+ (mode == BRUSH_STROKE_INVERT))
+ {
view3d_operator_needs_opengl(C);
- return ps;
+ ps_handle->is_clone_cursor_pick = true;
+ return ps_handle;
}
- paint_brush_init_tex(ps->brush);
+ ps_handle->orig_brush_size = BKE_brush_size_get(scene, ps_handle->brush);
- ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW;
+ ps_handle->symmetry_flags = settings->imapaint.paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ ps_handle->ps_views_tot = 1 + (pow_i(2, count_bits_i(ps_handle->symmetry_flags)) - 1);
+ is_multi_view = (ps_handle->ps_views_tot != 1);
- if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
- MEM_freeN(ps);
- return NULL;
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
+ ps_handle->ps_views[i] = ps;
}
- ps->orig_brush_size = BKE_brush_size_get(ps->scene, ps->brush);
+ if (ps_handle->symmetry_flags) {
+ int index = 0;
+
+ int x = 0;
+ do {
+ int y = 0;
+ do {
+ int z = 0;
+ do {
+ symmetry_flag_views[index++] = (
+ (x ? PAINT_SYMM_X : 0) |
+ (y ? PAINT_SYMM_Y : 0) |
+ (z ? PAINT_SYMM_Z : 0));
+ BLI_assert(index <= ps_handle->ps_views_tot);
+ } while ((z++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Z));
+ } while ((y++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Y));
+ } while ((x++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_X));
+ BLI_assert(index == ps_handle->ps_views_tot);
+ }
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+
+ project_state_init(C, ob, ps, mode);
+
+ if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
+ ps_handle->ps_views_tot = i + 1;
+ goto fail;
+ }
+ }
/* Don't allow brush size below 2 */
- if (BKE_brush_size_get(ps->scene, ps->brush) < 2)
- BKE_brush_size_set(ps->scene, ps->brush, 2 * U.pixelsize);
+ if (BKE_brush_size_get(scene, ps_handle->brush) < 2)
+ BKE_brush_size_set(scene, ps_handle->brush, 2 * U.pixelsize);
/* allocate and initialize spatial data structures */
- project_paint_begin(ps);
- if (ps->dm == NULL) {
- MEM_freeN(ps);
- return NULL;
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+
+ ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW;
+ project_image_refresh_tagged(ps);
+
+ /* re-use! */
+ if (i != 0) {
+ ps->is_shared_user = true;
+ PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]);
+ }
+
+ project_paint_begin(ps, is_multi_view, symmetry_flag_views[i]);
+
+ paint_proj_begin_clone(ps, mouse);
+
+ if (ps->dm == NULL) {
+ goto fail;
+ return NULL;
+ }
}
- paint_proj_begin_clone(ps, mouse);
+ paint_brush_init_tex(ps_handle->brush);
- return ps;
+ return ps_handle;
+
+
+fail:
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps = ps_handle->ps_views[i];
+ MEM_freeN(ps);
+ }
+ MEM_freeN(ps_handle);
+ return NULL;
}
-void paint_proj_redraw(const bContext *C, void *pps, bool final)
+void paint_proj_redraw(const bContext *C, void *ps_handle_p, bool final)
{
- ProjPaintState *ps = pps;
-
- if (ps->need_redraw) {
- project_image_refresh_tagged(ps);
+ ProjStrokeHandle *ps_handle = ps_handle_p;
- ps->need_redraw = false;
+ if (ps_handle->need_redraw) {
+ ps_handle->need_redraw = false;
}
else if (!final) {
return;
@@ -5067,19 +5285,34 @@ void paint_proj_redraw(const bContext *C, void *pps, bool final)
}
}
-void paint_proj_stroke_done(void *pps)
+void paint_proj_stroke_done(void *ps_handle_p)
{
- ProjPaintState *ps = pps;
- if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
- MEM_freeN(ps);
+ ProjStrokeHandle *ps_handle = ps_handle_p;
+ Scene *scene = ps_handle->scene;
+ int i;
+
+ if (ps_handle->is_clone_cursor_pick) {
+ MEM_freeN(ps_handle);
return;
}
- BKE_brush_size_set(ps->scene, ps->brush, ps->orig_brush_size);
- paint_brush_exit_tex(ps->brush);
+ for (i = 1; i < ps_handle->ps_views_tot; i++) {
+ PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]);
+ }
- project_paint_end(ps);
- MEM_freeN(ps);
+ BKE_brush_size_set(scene, ps_handle->brush, ps_handle->orig_brush_size);
+
+ paint_brush_exit_tex(ps_handle->brush);
+
+ for (i = 0; i < ps_handle->ps_views_tot; i++) {
+ ProjPaintState *ps;
+ ps = ps_handle->ps_views[i];
+ project_paint_end(ps);
+ MEM_freeN(ps);
+
+ }
+
+ MEM_freeN(ps_handle);
}
/* use project paint to re-apply an image */
static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
@@ -5159,7 +5392,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
ED_image_undo_restore, ED_image_undo_free, NULL);
/* allocate and initialize spatial data structures */
- project_paint_begin(&ps);
+ project_paint_begin(&ps, false, 0);
if (ps.dm == NULL) {
BKE_brush_size_set(scene, ps.brush, orig_brush_size);
@@ -5241,7 +5474,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- image = BKE_image_add_from_imbuf(ibuf);
+ image = BKE_image_add_from_imbuf(ibuf, "image_view");
/* Drop reference to ibuf so that the image owns it */
IMB_freeImBuf(ibuf);
@@ -5271,8 +5504,6 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
array[2] = is_ortho ? 1.0f : 0.0f;
IDP_AddToGroup(idgroup, view_data);
-
- rename_id(&image->id, "image_view");
}
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 77059a22de7..fd7e053fea3 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -145,7 +145,7 @@ typedef struct ImagePaintPartialRedraw {
int image_texture_paint_poll(struct bContext *C);
void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate);
-void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj);
+void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj, bool find_prev);
void image_undo_remove_masks(void);
void image_undo_init_locks(void);
void image_undo_end_locks(void);
@@ -160,7 +160,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final);
void paint_2d_stroke_done(void *ps);
void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size);
void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
-void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
+void paint_2d_gradient_fill(const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size);
void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index f5a65be880e..f0963cae1ce 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -1015,7 +1015,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
return false;
}
-static void paint_stroke_line_constrain (PaintStroke *stroke, float mouse[2])
+static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
{
if (stroke->constrain_line) {
float line[2];
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index b19cced2f8e..f1edf8a5fd9 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -379,7 +379,7 @@ static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *
return 0;
/* sample only on the exact position */
- *r_index = view3d_sample_backbuf(vc, mval[0], mval[1]);
+ *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]);
if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
return 0;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 9bca0fd2976..1a31442faf4 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -209,7 +209,7 @@ static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag)
{
/* if no mcol: do not do */
/* if tface: only the involved faces, otherwise all */
- const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
MFace *mface;
int a;
short *scolmain, *scol;
@@ -280,7 +280,7 @@ static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag)
static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const bool do_tessface)
{
- const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
MPoly *mp;
int (*scol)[4];
int i, j;
@@ -878,7 +878,7 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x
* brushes with size > 64, why is this here? */
/*if (size > 64.0) size = 64.0;*/
- ibuf = view3d_read_backbuf(vc, x - size, y - size, x + size, y + size);
+ ibuf = ED_view3d_backbuf_read(vc, x - size, y - size, x + size, y + size);
if (ibuf) {
unsigned int *rt = ibuf->rect;
@@ -1091,7 +1091,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even
me = BKE_mesh_from_object(vc.obact);
if (me && me->dvert && vc.v3d && vc.rv3d) {
- const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int v_idx_best = -1;
unsigned int index;
@@ -1177,7 +1177,7 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
- const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
bool found = false;
unsigned int index;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 40ef8970d68..1d2f623bf9d 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4966,6 +4966,9 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
sd->symmetrize_direction, 0.00001f);
sculpt_dynamic_topology_triangulate(ss->bm);
+ /* bisect operator flags edges (keep tags clean for edge queue) */
+ BM_mesh_elem_hflag_disable_all(ss->bm, BM_EDGE, BM_ELEM_TAG, false);
+
/* Finish undo */
BM_log_all_added(ss->bm, ss->bm_log);
sculpt_undo_push_end();
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index bce9a375091..8a3b48125d0 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -51,6 +51,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_library.h"
#include "BKE_packedFile.h"
#include "BKE_scene.h"
#include "BKE_sound.h"
@@ -105,8 +106,9 @@ static int sound_open_exec(bContext *C, wmOperator *op)
if (!op->customdata)
sound_open_init(C, op);
- if (sound == NULL || sound->playback_handle == NULL) {
+ if (sound->playback_handle == NULL) {
if (op->customdata) MEM_freeN(op->customdata);
+ BKE_libblock_free(bmain, sound);
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 73091e7f261..bc42f1dd5bb 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -59,6 +59,7 @@
#include "RNA_access.h"
+#include "ED_buttons.h"
#include "ED_armature.h"
#include "ED_screen.h"
#include "ED_physics.h"
@@ -1179,3 +1180,33 @@ ID *buttons_context_id_path(const bContext *C)
return NULL;
}
+
+void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id)
+{
+ if (sbuts->pinid == id) {
+ sbuts->pinid = NULL;
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
+
+ if (sbuts->path) {
+ ButsContextPath *path = sbuts->path;
+ int i;
+
+ for (i = 0; i < path->len; i++) {
+ if (path->ptr[i].id.data == id) {
+ break;
+ }
+ }
+
+ if (i == path->len) {
+ /* pass */
+ }
+ else if (i == 0) {
+ MEM_SAFE_FREE(sbuts->path);
+ }
+ else {
+ memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
+ path->len = i;
+ }
+ }
+}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 6c55d8d034e..d0210025183 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -1123,7 +1123,9 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
{
bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
bool is_selected_track = (plane_track->flag & SELECT) != 0;
- bool draw_plane_quad = plane_track->image == NULL || plane_track->image_opacity == 0.0f;
+ const bool has_image = plane_track->image != NULL &&
+ BKE_image_has_ibuf(plane_track->image, NULL);
+ const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
float px[2];
if (draw_outline) {
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 17783e1412d..1d398177d9f 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -658,7 +658,7 @@ void CLIP_OT_view_zoom(wmOperatorType *ot)
ot->poll = ED_space_clip_view_clip_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* properties */
prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 5f919c9b51d..48f8f587106 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -177,9 +177,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
MovieTracking *tracking = &clip->tracking;
MovieTrackingStabilization *stab = &tracking->stabilization;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
- MovieTrackingPlaneTrack *plane_track, *next_plane_track;
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
bool has_bundle = false, update_stab = false;
char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2];
@@ -197,49 +195,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
has_bundle = true;
/* Make sure no plane will use freed track */
- for (plane_track = plane_tracks_base->first;
- plane_track;
- plane_track = next_plane_track)
- {
- bool found = false;
- int i;
-
- next_plane_track = plane_track->next;
-
- for (i = 0; i < plane_track->point_tracksnr; i++) {
- if (plane_track->point_tracks[i] == track) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- continue;
- }
-
- if (plane_track->point_tracksnr > 4) {
- int track_index;
- MovieTrackingTrack **new_point_tracks;
-
- new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * plane_track->point_tracksnr,
- "new point tracks array");
-
- for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
- if (plane_track->point_tracks[i] != track) {
- new_point_tracks[track_index++] = plane_track->point_tracks[i];
- }
- }
-
- MEM_freeN(plane_track->point_tracks);
- plane_track->point_tracks = new_point_tracks;
- plane_track->point_tracksnr--;
- }
- else {
- /* Delete planes with less than 3 point tracks in it. */
- BKE_tracking_plane_track_free(plane_track);
- BLI_freelinkN(plane_tracks_base, plane_track);
- }
- }
+ BKE_tracking_plane_tracks_remove_point_track(tracking, track);
/* Delete f-curves associated with the track (such as weight, i.e.) */
BLI_strescape(track_name_escaped, track->name, sizeof(track_name_escaped));
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index fc2c0d3d45c..5ba82f7f71f 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -206,7 +206,7 @@ static void clip_scopes_tag_refresh(ScrArea *sa)
if (sc->mode != SC_MODE_TRACKING)
return;
- /* only while proeprties are visible */
+ /* only while properties are visible */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->regiontype == RGN_TYPE_UI && ar->flag & RGN_FLAG_HIDDEN)
return;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index db8881a865e..538c1a4e5ea 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -825,12 +825,8 @@ static void apply_mouse_slide(bContext *C, SlideMarkerData *data)
plane_track = plane_track->next)
{
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
- int i;
- for (i = 0; i < plane_track->point_tracksnr; i++) {
- if (plane_track->point_tracks[i] == data->track) {
- BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
- break;
- }
+ if (BKE_tracking_plane_track_has_point_track(plane_track, data->track)) {
+ BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
}
}
}
@@ -1070,7 +1066,7 @@ void CLIP_OT_slide_marker(wmOperatorType *ot)
ot->modal = slide_marker_modal;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
/* properties */
RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -1883,7 +1879,7 @@ void CLIP_OT_clear_track_path(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* proeprties */
+ /* properties */
RNA_def_enum(ot->srna, "action", clear_path_actions, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
RNA_def_boolean(ot->srna, "clear_active", 0, "Clear Active", "Clear active track only instead of all selected tracks");
}
@@ -3117,6 +3113,12 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
if (tracking->stabilization.rot_track == track)
tracking->stabilization.rot_track = act_track;
+ /* TODO(sergey): Re-evaluate planes with auto-key. */
+ BKE_tracking_plane_tracks_replace_point_track(tracking,
+ track,
+ act_track);
+
+
BKE_tracking_track_free(track);
BLI_freelinkN(tracksbase, track);
}
@@ -4181,7 +4183,7 @@ void CLIP_OT_slide_plane_marker(wmOperatorType *ot)
ot->modal = slide_plane_marker_modal;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
}
/********************** Insert track keyframe operator *********************/
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index 0b29c253f3a..8a2bf17c667 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -997,6 +997,6 @@ void CLIP_OT_select_grouped(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* proeprties */
+ /* properties */
RNA_def_enum(ot->srna, "group", select_group_items, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute");
}
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index a6f3a73841e..d5b9c169192 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -307,10 +307,10 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in
/* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict (for buttons it works) */
rect.xmin = sx;
- rect.xmax = (int)(sx + ceil(width + 4.0f));
+ rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC));
rect.ymin = sy - height;
rect.ymax = sy;
-
+
UI_fontstyle_draw(&fs, &rect, fname);
}
@@ -329,6 +329,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int
float fx, fy;
float dx, dy;
int xco, yco;
+ float ui_imbx, ui_imby;
float scaledx, scaledy;
float scale;
int ex, ey;
@@ -336,23 +337,26 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int
BLI_assert(imb != NULL);
- if ((imb->x * UI_DPI_FAC > layout->prv_w) ||
- (imb->y * UI_DPI_FAC > layout->prv_h))
+ ui_imbx = imb->x * UI_DPI_FAC;
+ ui_imby = imb->y * UI_DPI_FAC;
+ /* Unlike thumbnails, icons are not scaled up. */
+ if (((ui_imbx > layout->prv_w) || (ui_imby > layout->prv_h)) ||
+ (!is_icon && ((ui_imbx < layout->prv_w) || (ui_imby < layout->prv_h))))
{
if (imb->x > imb->y) {
scaledx = (float)layout->prv_w;
- scaledy = ( (float)imb->y / (float)imb->x) * layout->prv_w;
+ scaledy = ((float)imb->y / (float)imb->x) * layout->prv_w;
scale = scaledx / imb->x;
}
else {
scaledy = (float)layout->prv_h;
- scaledx = ( (float)imb->x / (float)imb->y) * layout->prv_h;
+ scaledx = ((float)imb->x / (float)imb->y) * layout->prv_h;
scale = scaledy / imb->y;
}
}
else {
- scaledx = (float)imb->x * UI_DPI_FAC;
- scaledy = (float)imb->y * UI_DPI_FAC;
+ scaledx = ui_imbx;
+ scaledy = ui_imby;
scale = UI_DPI_FAC;
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 87e6183f4f8..2853ee9c053 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1349,7 +1349,7 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float
else if (limg->flags & FILE_TYPE_FTFONT) {
source = THB_SOURCE_FONT;
}
- limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, source);
+ limg->img = IMB_thumb_manage(limg->path, THB_LARGE, source);
*do_update = true;
PIL_sleep_ms(10);
limg = limg->next;
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 6858f536e92..82409c9ecb4 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -102,6 +102,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
/* set path to most recently opened .blend */
BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
sfile->params->filter_glob[0] = '\0';
+ /* set the default thumbnails size */
+ sfile->params->thumbnail_size = 128;
}
params = sfile->params;
@@ -527,8 +529,8 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->textheight = textheight;
if (params->display == FILE_IMGDISPLAY) {
- layout->prv_w = 4.8f * UI_UNIT_X;
- layout->prv_h = 4.8f * UI_UNIT_Y;
+ layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
+ layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
layout->tile_border_x = 0.3f * UI_UNIT_X;
layout->tile_border_y = 0.3f * UI_UNIT_X;
layout->prv_border_x = 0.3f * UI_UNIT_X;
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index c6ee6875403..fdf7b458865 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -565,7 +565,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
- if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII))
+ if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8))
continue;
/* Exclude "all my files" as it makes no sense in blender fileselector */
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index c398d32dad5..e52eea248ed 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -312,10 +312,11 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *
static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
{
- if (RE_RenderViewGetRectf(rr, 0)) {
+ RenderView *rv = RE_RenderViewGetById(rr, 0);
+ if (rv->rectf) {
return IFACE_("Composite");
}
- else if (RE_RenderViewGetRect32(rr, 0)) {
+ else if (rv->rect32) {
return IFACE_("Sequence");
}
else {
@@ -580,7 +581,7 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
ImageUser *iuser = iuser_v;
RenderLayer *rl;
RenderPass *rp;
- RenderPass *prev= NULL;
+ RenderPass *prev = NULL;
int layer = iuser->layer;
if (RE_HasFakeLayer(rr))
@@ -728,12 +729,12 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
}
}
-static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, short *render_slot)
+static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser,
+ int menus_width, short *render_slot)
{
uiBlock *block = uiLayoutGetBlock(layout);
uiLayout *row;
uiBut *but;
- const float dpi_fac = UI_DPI_FAC;
row = uiLayoutRow(layout, true);
@@ -750,7 +751,7 @@ static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, Ren
but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_RIGHT, 0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Layer"));
UI_but_func_set(but, image_multi_inclay_cb, rr, iuser);
- uiblock_layer_pass_buttons(row, image, rr, iuser, 230 * dpi_fac, render_slot);
+ uiblock_layer_pass_buttons(row, image, rr, iuser, menus_width, render_slot);
/* decrease, increase arrows */
but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_LEFT, 0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Pass"));
@@ -867,10 +868,17 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
else if (ima->type == IMA_TYPE_R_RESULT) {
/* browse layer/passes */
RenderResult *rr;
+ const float dpi_fac = UI_DPI_FAC;
+ const int menus_width = 230 * dpi_fac;
/* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
rr = BKE_image_acquire_renderresult(scene, ima);
- uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, &ima->render_slot);
+ if (rr) {
+ uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ }
+ else {
+ uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ }
BKE_image_release_renderresult(scene, ima);
}
}
@@ -903,7 +911,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
/* multilayer? */
if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
- uiblock_layer_pass_arrow_buttons(layout, ima, ima->rr, iuser, NULL);
+ const float dpi_fac = UI_DPI_FAC;
+ uiblock_layer_pass_arrow_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
}
else if (ima->source != IMA_SRC_GENERATED) {
if (compact == 0) {
@@ -1211,12 +1220,20 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser
/* render layers and passes */
if (ima && iuser) {
- const float dpi_fac = UI_DPI_FAC;
RenderResult *rr;
+ const float dpi_fac = UI_DPI_FAC;
+ const int menus_width = 160 * dpi_fac;
+ const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT);
/* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
rr = BKE_image_acquire_renderresult(scene, ima);
- uiblock_layer_pass_buttons(layout, ima, rr, iuser, 160 * dpi_fac, (ima->type == IMA_TYPE_R_RESULT) ? &ima->render_slot : NULL);
+ if (rr && is_render_result) {
+ uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ }
+ else {
+ uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width,
+ is_render_result ? &ima->render_slot : NULL);
+ }
BKE_image_release_renderresult(scene, ima);
}
}
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 5a3c3e90618..36419ccd10d 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -836,14 +836,30 @@ void draw_image_main(const bContext *C, ARegion *ar)
ibuf = ED_space_image_acquire_buffer(sima, &lock);
/* draw the image or grid */
- if (ibuf == NULL)
+ if (ibuf == NULL) {
ED_region_grid_draw(ar, zoomx, zoomy);
- else if (sima->flag & SI_DRAW_TILE)
- draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy);
- else if (ima && (ima->tpageflag & IMA_TILES))
- draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
- else
- draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+ }
+ else {
+
+ if (sima->flag & SI_DRAW_TILE)
+ draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy);
+ else if (ima && (ima->tpageflag & IMA_TILES))
+ draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
+ else
+ draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+
+ if (sima->flag & SI_DRAW_METADATA) {
+ int x, y;
+ rctf frame;
+
+ BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
+ UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
+
+ ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx, zoomy);
+ }
+ }
+
+ ED_space_image_release_buffer(sima, ibuf, lock);
/* paint helpers */
if (show_paint)
@@ -866,8 +882,6 @@ void draw_image_main(const bContext *C, ARegion *ar)
}
#endif
- ED_space_image_release_buffer(sima, ibuf, lock);
-
if (show_viewer) {
BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 756f90fe560..75e6f77ba49 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -378,7 +378,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot)
ot->poll = space_image_main_area_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
/* properties */
RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -594,7 +594,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
ot->poll = space_image_main_area_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS;
/* properties */
prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor",
@@ -1672,6 +1672,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
goto cleanup;
}
}
+ BKE_imbuf_stamp_info(rr, ibuf);
}
/* fancy multiview OpenEXR */
@@ -1693,6 +1694,7 @@ 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);
}
@@ -1931,7 +1933,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
uiLayout *layout = op->layout;
ImageFormatData *imf = op->customdata;
PointerRNA imf_ptr, ptr;
- const bool is_multiview = RNA_boolean_get(op->ptr, "use_multiview");
+ const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview");
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr);
@@ -1943,7 +1945,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
/* multiview template */
if (is_multiview)
- uiTemplateImageFormatViews(layout, &imf_ptr, NULL);
+ uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr);
}
static int image_save_as_poll(bContext *C)
@@ -2404,7 +2406,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
const bool b = RNA_boolean_get(op->ptr, "invert_b");
const bool a = RNA_boolean_get(op->ptr, "invert_a");
- int i;
+ size_t i;
if (ibuf == NULL) /* TODO: this should actually never happen, but does for render-results -> cleanup */
return OPERATOR_CANCELLED;
@@ -2415,13 +2417,13 @@ static int image_invert_exec(bContext *C, wmOperator *op)
/* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
* but better do this right in case someone copies this for a tool that uses partial redraw better */
ED_imapaint_clear_partial_redraw();
- ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false);
}
/* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */
if (ibuf->rect_float) {
float *fp = (float *) ibuf->rect_float;
- for (i = ibuf->x * ibuf->y; i > 0; i--, fp += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, fp += 4) {
if (r) fp[0] = 1.0f - fp[0];
if (g) fp[1] = 1.0f - fp[1];
if (b) fp[2] = 1.0f - fp[2];
@@ -2435,7 +2437,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
else if (ibuf->rect) {
char *cp = (char *) ibuf->rect;
- for (i = ibuf->x * ibuf->y; i > 0; i--, cp += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, cp += 4) {
if (r) cp[0] = 255 - cp[0];
if (g) cp[1] = 255 - cp[1];
if (b) cp[2] = 255 - cp[2];
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 32584a3a2df..a9a5e601e10 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -683,7 +683,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
//View2DScrollers *scrollers;
float col[3];
-
+
/* XXX not supported yet, disabling for now */
scene->r.scemode &= ~R_COMP_CROP;
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 240d8baa6f2..a1f90f16bbf 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -134,7 +134,7 @@ static int autopack_toggle_exec(bContext *C, wmOperator *op)
G.fileflags &= ~G_AUTOPACK;
}
else {
- packAll(bmain, op->reports);
+ packAll(bmain, op->reports, true);
G.fileflags |= G_AUTOPACK;
}
@@ -161,7 +161,7 @@ static int pack_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- packAll(bmain, op->reports);
+ packAll(bmain, op->reports, true);
G.fileflags |= G_AUTOPACK;
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index a0dfb285a1c..48a39cd79fc 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -56,6 +56,8 @@
#include "ED_info.h"
#include "ED_armature.h"
+#include "GPU_extensions.h"
+
#define MAX_INFO_LEN 512
#define MAX_INFO_NUM_LEN 16
@@ -381,6 +383,7 @@ static void stats_string(Scene *scene)
Object *ob = (scene->basact) ? scene->basact->object : NULL;
uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
+ char gpumemstr[MAX_INFO_MEM_LEN] = "";
char *s;
size_t ofs = 0;
@@ -416,11 +419,22 @@ static void stats_string(Scene *scene)
/* get memory statistics */
- s = memstr;
- ofs += BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" | Mem:%.2fM"),
+ ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"),
(double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
if (mmap_in_use)
- BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
+ BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
+
+ if (GPU_mem_stats_supported()) {
+ int gpu_free_mem, gpu_tot_memory;
+
+ GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem);
+
+ ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0);
+
+ if (gpu_tot_memory) {
+ BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0);
+ }
+ }
s = stats->infostr;
ofs = 0;
@@ -447,22 +461,23 @@ static void stats_string(Scene *scene)
}
ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
+ ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs);
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s"),
- stats_fmt.totbonesel, stats_fmt.totbone, memstr);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s%s"),
+ stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr);
}
else if (stats_is_object_dynamic_topology_sculpt(ob)) {
- ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s"), stats_fmt.totvert,
- stats_fmt.tottri);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert,
+ stats_fmt.tottri, gpumemstr);
}
else {
ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
- IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s"),
+ IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s%s"),
stats_fmt.totvert, stats_fmt.totface,
stats_fmt.tottri, stats_fmt.totobjsel,
stats_fmt.totobj, stats_fmt.totlampsel,
- stats_fmt.totlamp, memstr);
+ stats_fmt.totlamp, memstr, gpumemstr);
}
if (ob)
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 52156a2394e..4d37fcc9276 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -433,7 +433,7 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i
/* just print the name and the range */
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
- str_len = BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index);
+ str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index);
}
else {
str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str));
@@ -490,11 +490,11 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
* while also preserving some accuracy, since we do use floats
*/
/* start frame */
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start);
UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col);
/* end frame */
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end);
UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col);
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 87a64e95e63..e27cb041dc5 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -163,14 +163,14 @@ void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree)
ntreeTexCheckCyclics(ntree);
}
-static int compare_nodes(bNode *a, bNode *b)
+static bool compare_nodes(const bNode *a, const bNode *b)
{
bNode *parent;
/* These tell if either the node or any of the parent nodes is selected.
* A selected parent means an unselected node is also in foreground!
*/
- int a_select = (a->flag & NODE_SELECT), b_select = (b->flag & NODE_SELECT);
- int a_active = (a->flag & NODE_ACTIVE), b_active = (b->flag & NODE_ACTIVE);
+ bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0;
+ bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0;
/* if one is an ancestor of the other */
/* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 360087d77c7..ffd51bcc44e 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -740,6 +740,34 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
}
}
+void ED_node_id_unref(SpaceNode *snode, const ID *id)
+{
+ if (GS(id->name) == ID_SCE) {
+ if (snode->id == id) {
+ /* nasty DNA logic for SpaceNode:
+ * ideally should be handled by editor code, but would be bad level call
+ */
+ bNodeTreePath *path, *path_next;
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
+ BLI_listbase_clear(&snode->treepath);
+
+ snode->id = NULL;
+ snode->from = NULL;
+ snode->nodetree = NULL;
+ snode->edittree = NULL;
+ }
+ }
+ else if (GS(id->name) == ID_OB) {
+ if (snode->from == id) {
+ snode->flag &= ~SNODE_PIN;
+ snode->from = NULL;
+ }
+ }
+}
+
void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
{
/* XXX This does not work due to layout functions relying on node->block,
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index b69808d4e81..f1d9d4efcc6 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -456,8 +456,8 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo
/* add internal links to the ntree */
for (link = ngroup->links.first; link; link = link_next) {
- int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
- int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
+ const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
+ const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
link_next = link->next;
if (make_copy) {
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index dda84eb0cbf..8c5d2d82468 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -292,7 +292,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot)
ot->cancel = snode_bg_viewmove_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
static int backimage_zoom_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 62cb0bc73cd..de90c417bdd 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -203,12 +203,10 @@ void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_lengt
value[0] = '\0';
for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
if (i == 0) {
- BLI_strncpy(value, path->node_name, max_length);
- size = strlen(path->node_name);
+ size = BLI_strncpy_rlen(value, path->node_name, max_length);
}
else {
- BLI_snprintf(value, max_length, "/%s", path->node_name);
- size = strlen(path->node_name) + 1;
+ size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name);
}
max_length -= size;
if (max_length <= 0)
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 798dae2cef3..058b8c4de5a 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -39,20 +39,24 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_mempool.h"
#include "BLF_translation.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_outliner_treehash.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_material.h"
#include "BKE_group.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_keyframing.h"
@@ -1952,3 +1956,35 @@ void OUTLINER_OT_group_link(wmOperatorType *ot)
/* properties */
RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
}
+
+/******** Utils to clear any ref to freed ID... **********/
+
+void ED_outliner_id_unref(SpaceOops *so, const ID *id)
+{
+ /* Some early out checks. */
+ if (!TREESTORE_ID_TYPE(id)) {
+ return; /* ID type is not used by outilner... */
+ }
+
+ if (so->search_tse.id == id) {
+ so->search_tse.id = NULL;
+ }
+
+ if (so->treestore) {
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+ bool changed = false;
+
+ BLI_mempool_iternew(so->treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ if (tselem->id == id) {
+ tselem->id = NULL;
+ changed = true;
+ }
+ }
+ if (so->treehash && changed) {
+ /* rebuild hash table, because it depends on ids too */
+ BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore);
+ }
+ }
+}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index b4b73a11a14..38672ef14dd 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -57,6 +57,10 @@ typedef struct TreeElement {
PointerRNA rnaptr; // RNA Pointer
} TreeElement;
+#define TREESTORE_ID_TYPE(_id) \
+ (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
+ ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS))
+
/* TreeElement->flag */
#define TE_ACTIVE 1
#define TE_ICONROW 2
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index e5833103658..66863b8061b 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -427,8 +427,7 @@ static void group_instance_cb(bContext *C, Scene *scene, TreeElement *UNUSED(te)
{
Group *group = (Group *)tselem->id;
- Object *ob = ED_object_add_type(C, OB_EMPTY, scene->cursor, NULL, false, scene->layact);
- rename_id(&ob->id, group->id.name + 2);
+ Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, scene->cursor, NULL, false, scene->layact);
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
id_lib_extern(&group->id);
@@ -1654,9 +1653,14 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
+ uiBut *but = UI_context_active_but_get(C);
TreeElement *te;
float fmval[2];
+ if (but) {
+ UI_but_tooltip_timer_remove(C, but);
+ }
+
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 17a6e952ee1..4b07c400220 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -855,6 +855,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
return NULL;
}
+ if (type == 0) {
+ /* Zero type means real ID, ensure we do not get non-outliner ID types here... */
+ BLI_assert(TREESTORE_ID_TYPE(id));
+ }
+
te = MEM_callocN(sizeof(TreeElement), "tree elem");
/* add to the visual tree */
BLI_addtail(lb, te);
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 373095d68f9..f4b1afba6c4 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <math.h>
#include <string.h>
+#include <ctype.h>
#include "MEM_guardedalloc.h"
@@ -751,11 +752,94 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
}
+int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe)
+{
+ int minframe = INT32_MAX, maxframe = INT32_MIN;
+
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ char *filename = NULL, *filename_stripped;
+ int frame;
+ /* just get the first filename */
+ filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+
+ if (filename) {
+ bool is_numeric;
+
+ filename_stripped = filename;
+
+ /* strip numeric extensions */
+ while (*filename_stripped && isdigit(*filename_stripped)) {
+ filename_stripped++;
+ }
+
+ is_numeric = (filename_stripped != filename && *filename_stripped == '.');
+
+ if (is_numeric) {
+ /* was the number really an extension? */
+ *filename_stripped = 0;
+ frame = atoi(filename);
+ minframe = min_ii(minframe, frame);
+ maxframe = max_ii(maxframe, frame);
+ }
+
+ MEM_freeN(filename);
+ }
+ }
+ RNA_END;
+
+ if (minframe == INT32_MAX) {
+ minframe = sfra;
+ maxframe = minframe + 1;
+ }
+
+ *r_minframe = minframe;
+
+ return maxframe - minframe + 1;
+}
+
+void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe)
+{
+ int i;
+ char *filename = NULL, *filename_stripped;
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ /* just get the first filename */
+ filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ break;
+ }
+ RNA_END;
+
+ filename_stripped = filename;
+
+ if (filename_stripped) {
+
+ /* strip numeric extensions */
+ while (*filename_stripped && isdigit(*filename_stripped)) {
+ filename_stripped++;
+ }
+
+ /* was the number really an extension? */
+ if (*filename_stripped == '.')
+ filename_stripped++;
+ else {
+ filename_stripped = filename;
+ }
+
+ for (i = 0; i < len; i++, se++) {
+ BLI_snprintf(se->name, sizeof(se->name), "%04d.%s", minframe + i, filename_stripped);
+ }
+
+ MEM_freeN(filename);
+ }
+}
+
+
/* add image operator */
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
{
+ int minframe;
/* cant use the generic function for this */
-
Scene *scene = CTX_data_scene(C); /* only for sound */
Editing *ed = BKE_sequencer_editing_get(scene, true);
SeqLoadInfo seq_load;
@@ -763,11 +847,17 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
Strip *strip;
StripElem *se;
+ const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
seq_load_operator_info(&seq_load, op);
/* images are unique in how they handle this - 1 per strip elem */
- seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ if (use_placeholders) {
+ seq_load.len = sequencer_image_seq_get_minmax_frame(op, seq_load.start_frame, &minframe);
+ }
+ else {
+ seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ }
if (seq_load.len == 0)
return OPERATOR_CANCELLED;
@@ -775,20 +865,24 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
if (seq_load.flag & SEQ_LOAD_REPLACE_SEL)
ED_sequencer_deselect_all(scene);
-
/* main adding function */
seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load);
strip = seq->strip;
se = strip->stripdata;
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(se->name, filename, sizeof(se->name));
- MEM_freeN(filename);
- se++;
+ if (use_placeholders) {
+ sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe);
+ }
+ else {
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ BLI_strncpy(se->name, filename, sizeof(se->name));
+ MEM_freeN(filename);
+ se++;
+ }
+ RNA_END;
}
- RNA_END;
if (seq_load.len == 1) {
if (seq_load.start_frame < seq_load.end_frame) {
@@ -861,6 +955,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
+
+ RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip");
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index baadc28cd65..0c811ca1af7 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -63,6 +63,7 @@
#include "ED_markers.h"
#include "ED_mask.h"
#include "ED_sequencer.h"
+#include "ED_screen.h"
#include "ED_space_api.h"
#include "UI_interface.h"
@@ -425,12 +426,12 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
size_t numstr_len;
if (direction == SEQ_LEFTHANDLE) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp);
x1 = rx1;
y1 -= 0.45f;
}
else {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1);
x1 = x2 - handsize_clamped * 0.75f;
y1 = y2 + 0.05f;
}
@@ -980,6 +981,76 @@ static void sequencer_display_size(Scene *scene, SpaceSeq *sseq, float r_viewrec
}
}
+static void sequencer_draw_gpencil(const bContext *C)
+{
+ /* draw grease-pencil (image aligned) */
+ ED_gpencil_draw_2dimage(C);
+
+ /* ortho at pixel level */
+ UI_view2d_view_restore(C);
+
+ /* draw grease-pencil (screen aligned) */
+ ED_gpencil_draw_view2d(C, 0);
+}
+
+/* draws content borders plus safety borders if needed */
+static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene)
+{
+ float x1 = v2d->tot.xmin;
+ float y1 = v2d->tot.ymin;
+ float x2 = v2d->tot.xmax;
+ float y2 = v2d->tot.ymax;
+
+ /* border */
+ setlinestyle(3);
+
+ UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(x1 - 0.5f, y1 - 0.5f);
+ glVertex2f(x1 - 0.5f, y2 + 0.5f);
+ glVertex2f(x2 + 0.5f, y2 + 0.5f);
+ glVertex2f(x2 + 0.5f, y1 - 0.5f);
+ glEnd();
+
+ /* safety border */
+ if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title,
+ scene->safe_areas.action);
+
+ if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
+ UI_draw_safe_areas(
+ x1, x2, y1, y2,
+ scene->safe_areas.title_center,
+ scene->safe_areas.action_center);
+ }
+ }
+
+ setlinestyle(0);
+}
+
+/* draws checkerboard background for transparent content */
+static void sequencer_draw_background(const SpaceSeq *sseq, View2D *v2d, const float viewrect[2])
+{
+ /* setting up the view */
+ UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f);
+ UI_view2d_curRect_validate(v2d);
+ UI_view2d_view_ortho(v2d);
+
+ /* only draw alpha for main buffer */
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ if (sseq->flag & SEQ_USE_ALPHA) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ }
+ }
+}
+
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop)
{
struct Main *bmain = CTX_data_main(C);
@@ -996,7 +1067,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
int format, type;
bool glsl_used = false;
+ const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd);
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
+ bool draw_metadata = false;
if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
/* stop all running jobs, except screen one. currently previews frustrate Render
@@ -1018,6 +1091,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glClear(GL_COLOR_BUFFER_BIT);
}
+ /* without this colors can flicker from previous opengl state */
+ glColor4ub(255, 255, 255, 255);
+
/* only initialize the preview if a render is in progress */
if (G.is_rendering)
return;
@@ -1029,15 +1105,24 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* for now we only support Left/Right */
ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]);
- if (ibuf == NULL)
- return;
+ if ((ibuf == NULL) ||
+ (ibuf->rect == NULL && ibuf->rect_float == NULL))
+ {
+ /* gpencil can also be drawn if no imbuf is invalid */
+ if (draw_gpencil && is_imbuf) {
+ sequencer_display_size(scene, sseq, viewrect);
+
+ sequencer_draw_background(sseq, v2d, viewrect);
+ sequencer_draw_borders(sseq, v2d, scene);
- if (ibuf->rect == NULL && ibuf->rect_float == NULL)
+ sequencer_draw_gpencil(C);
+ }
return;
+ }
sequencer_display_size(scene, sseq, viewrect);
- if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) {
+ if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
SequencerScopes *scopes = &sseq->scopes;
sequencer_check_scopes(scopes, ibuf);
@@ -1096,28 +1181,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
- /* without this colors can flicker from previous opengl state */
- glColor4ub(255, 255, 255, 255);
-
if (!draw_backdrop) {
- UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f);
- UI_view2d_curRect_validate(v2d);
-
- /* setting up the view - actual drawing starts here */
- UI_view2d_view_ortho(v2d);
-
- /* only draw alpha for main buffer */
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
- if (sseq->flag & SEQ_USE_ALPHA) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
- glColor4f(1.0, 1.0, 1.0, 1.0);
- }
- }
+ sequencer_draw_background(sseq, v2d, viewrect);
}
-
+
if (scope) {
IMB_freeImBuf(ibuf);
ibuf = scope;
@@ -1238,10 +1305,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
else if (draw_backdrop) {
- float aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);
+ float aspect;
float image_aspect = viewrect[0] / viewrect[1];
float imagex, imagey;
-
+
+ aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);
+
if (aspect >= image_aspect) {
imagex = image_aspect / aspect;
imagey = 1.0f;
@@ -1250,28 +1319,22 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
imagex = 1.0f;
imagey = aspect / image_aspect;
}
-
+
glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
}
else {
+ draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0);
+
glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
}
glEnd();
-
- if (draw_backdrop) {
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
-
- }
-
+
glBindTexture(GL_TEXTURE_2D, last_texid);
glDisable(GL_TEXTURE_2D);
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
@@ -1286,63 +1349,29 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (!scope)
IMB_freeImBuf(ibuf);
-
+
+ if (draw_metadata) {
+ ED_region_image_metadata_draw(0.0, 0.0, ibuf, v2d->tot, 1.0, 1.0);
+ }
+
if (draw_backdrop) {
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
return;
}
-
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
-
- float x1 = v2d->tot.xmin;
- float y1 = v2d->tot.ymin;
- float x2 = v2d->tot.xmax;
- float y2 = v2d->tot.ymax;
-
- /* border */
- setlinestyle(3);
-
- UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
- glBegin(GL_LINE_LOOP);
- glVertex2f(x1 - 0.5f, y1 - 0.5f);
- glVertex2f(x1 - 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y1 - 0.5f);
- glEnd();
-
- /* safety border */
- if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
- UI_draw_safe_areas(
- x1, x2, y1, y2,
- scene->safe_areas.title,
- scene->safe_areas.action);
-
- if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
- UI_draw_safe_areas(
- x1, x2, y1, y2,
- scene->safe_areas.title_center,
- scene->safe_areas.action_center);
- }
- }
-
- setlinestyle(0);
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ sequencer_draw_borders(sseq, v2d, scene);
}
-
- if (sseq->flag & SEQ_SHOW_GPENCIL) {
- if (is_imbuf) {
- /* draw grease-pencil (image aligned) */
- ED_gpencil_draw_2dimage(C);
- }
+
+ if (draw_gpencil && is_imbuf) {
+ sequencer_draw_gpencil(C);
}
-
- /* ortho at pixel level */
- UI_view2d_view_restore(C);
-
- if (sseq->flag & SEQ_SHOW_GPENCIL) {
- if (is_imbuf) {
- /* draw grease-pencil (screen aligned) */
- ED_gpencil_draw_view2d(C, 0);
- }
+ else {
+ /* ortho at pixel level */
+ UI_view2d_view_restore(C);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 138d9b943fc..39023f5c0a3 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -3694,12 +3694,21 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = BKE_sequencer_active_get(scene);
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
+ int minframe;
if (seq->type == SEQ_TYPE_IMAGE) {
char directory[FILE_MAX];
- const int len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ int len;
StripElem *se;
+ /* need to find min/max frame for placeholders */
+ if (use_placeholders) {
+ len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe);
+ }
+ else {
+ len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
+ }
if (len == 0)
return OPERATOR_CANCELLED;
@@ -3717,14 +3726,19 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
}
seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem");
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
- BLI_strncpy(se->name, filename, sizeof(se->name));
- MEM_freeN(filename);
- se++;
+ if (use_placeholders) {
+ sequencer_image_seq_reserve_frames(op, se, len, minframe);
+ }
+ else {
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
+ BLI_strncpy(se->name, filename, sizeof(se->name));
+ MEM_freeN(filename);
+ se++;
+ }
+ RNA_END;
}
- RNA_END;
/* reset these else we wont see all the images */
seq->anim_startofs = seq->anim_endofs = 0;
@@ -3799,4 +3813,5 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE,
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES,
FILE_DEFAULTDISPLAY);
+ RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip");
}
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 78255507321..0158a2d4872 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -45,6 +45,8 @@ struct ARegion;
struct ARegionType;
struct Scene;
struct Main;
+struct wmOperator;
+struct StripElem;
/* space_sequencer.c */
struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
@@ -202,5 +204,9 @@ void SEQUENCER_OT_sample(struct wmOperatorType *ot);
/* sequencer_preview.c */
void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
+/* sequencer_add */
+int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r_minframe);
+void sequencer_image_seq_reserve_frames(struct wmOperator *op, struct StripElem *se, int len, int minframe);
+
#endif /* __SEQUENCER_INTERN_H__ */
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 7a7f189b187..769718e1567 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -564,7 +564,10 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
SpaceSeq *sseq = sa->spacedata.first;
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
- int show_split = scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW && sseq->mainb == SEQ_DRAW_IMG_IMBUF;
+ const bool show_split = (
+ scene->ed &&
+ (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) &&
+ (sseq->mainb == SEQ_DRAW_IMG_IMBUF));
/* XXX temp fix for wrong setting in sseq->mainb */
if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index ad8050a50e8..fce864d975f 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -2233,7 +2233,7 @@ void TEXT_OT_scroll(wmOperatorType *ot)
ot->poll = text_scroll_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_INTERNAL;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index b1f8d112765..b374ce64319 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -775,7 +775,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) {
short matnr = mp->mat_nr;
- int mf_smooth = mp->flag & ME_SMOOTH;
+ const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0;
Material *mat = (me->mat) ? me->mat[matnr] : NULL;
int mode = mat ? mat->game.flag : GEMAT_INVISIBLE;
@@ -1107,7 +1107,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
Mesh *me = ob->data;
TexMatCallback data = {scene, ob, me, dm};
bool (*set_face_cb)(void *, int);
- int glsl, picking = (G.f & G_PICKSEL);
+ bool glsl, picking = (G.f & G_PICKSEL) != 0;
/* face hiding callback depending on mode */
if (ob == scene->obedit)
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index bc966345fc5..da1d053657c 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -736,11 +736,7 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3],
const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
float verts[CIRCLE_RESOL][3];
- /* using gldepthfunc guarantees that it does write z values,
- * but not checks for it, so centers remain visible independent order of drawing */
- if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
- /* write to near buffer always */
- glDepthRange(0.0, 0.0);
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
if (special_color) {
@@ -770,10 +766,9 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3],
/* finish up */
glDisableClientState(GL_VERTEX_ARRAY);
- glDepthRange(0.0, 1.0);
glDisable(GL_BLEND);
- if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
/* *********** text drawing for object/particles/armature ************* */
@@ -3373,7 +3368,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
unit->system, B_UNIT_LENGTH, do_split, false);
}
else {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
}
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
@@ -3450,7 +3445,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
angle = angle_normalized_v3v3(no_a, no_b);
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col);
}
@@ -3475,7 +3470,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
3, unit->system, B_UNIT_AREA, do_split, false); \
} \
else { \
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); \
} \
view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \
} (void)0
@@ -3593,7 +3588,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
angle = angle_v3v3v3(v1, v2, v3);
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col);
}
@@ -3624,7 +3619,7 @@ static void draw_em_indices(BMEditMesh *em)
UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col);
}
i++;
@@ -3636,7 +3631,7 @@ static void draw_em_indices(BMEditMesh *em)
UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
mid_v3_v3v3(pos, e->v1->co, e->v2->co);
view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
}
@@ -3650,7 +3645,7 @@ static void draw_em_indices(BMEditMesh *em)
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
BM_face_calc_center_mean(f, pos);
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i);
view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col);
}
i++;
@@ -4226,7 +4221,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
if (is_obact && BKE_paint_select_vert_test(ob)) {
- const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0;
glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
@@ -5398,15 +5393,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (part->draw & PART_DRAW_NUM) {
if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
}
else {
- numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d", a);
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a);
}
}
else {
if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health);
+ numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health);
}
}
@@ -5647,7 +5642,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
float vec_txt[3];
- numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a);
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a);
/* use worldspace because object matrix is already applied */
mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co);
view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
@@ -8031,9 +8026,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* don't show smoke before simulation starts, this could be made an option in the future */
if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) {
/* get view vector */
- copy_v3_v3(viewnormal, rv3d->viewinv[2]);
invert_m4_m4(ob->imat, ob->obmat);
- mul_mat3_m4_v3(ob->imat, viewnormal);
+ mul_v3_mat3_m4v3(viewnormal, ob->imat, rv3d->viewinv[2]);
normalize_v3(viewnormal);
/* set dynamic boundaries to draw the volume
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 50ccde6da01..d6691f431dd 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -105,7 +105,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
float cor[3] = {1.0f, 1.0f, 1.0f};
int gl_depth = 0, gl_blend = 0;
- int use_fire = (sds->active_fields & SM_ACTIVE_FIRE);
+ const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0;
/* draw slices of smoke is adapted from c++ code authored
* by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 3c4ab7efc56..1a47553ce43 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1014,7 +1014,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
break;
case NC_GPENCIL:
- if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
ED_region_tag_redraw(ar);
}
break;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index fd6288b1601..57b417ef1d7 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -472,7 +472,7 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
-static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
+static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
{
float grid, grid_scale;
unsigned char col_grid[3];
@@ -484,7 +484,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
grid = gridlines * grid_scale;
- glDepthMask(GL_FALSE);
+ if (!write_depth)
+ glDepthMask(GL_FALSE);
UI_GetThemeColor3ubv(TH_GRID, col_grid);
@@ -1327,12 +1328,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
/* do nothing */
}
else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
- v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
+ V3D_IS_ZBUF(v3d))
{
/* do nothing */
}
- else if (scene->obedit && v3d->drawtype > OB_WIRE &&
- (v3d->flag & V3D_ZBUF_SELECT))
+ else if (scene->obedit &&
+ V3D_IS_ZBUF(v3d))
{
/* do nothing */
}
@@ -1454,14 +1455,23 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h,
glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
}
-void view3d_validate_backbuf(ViewContext *vc)
+void ED_view3d_backbuf_validate(ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF)
backdrawview3d(vc->scene, vc->ar, vc->v3d);
}
+/**
+ * allow for small values [0.5 - 2.5],
+ * and large values, FLT_MAX by clamping by the area size
+ */
+int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
+{
+ return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
+}
+
/* samples a single pixel (copied from vpaint) */
-unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
+unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
{
unsigned int col;
@@ -1469,7 +1479,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
return 0;
}
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
@@ -1482,7 +1492,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
}
/* reads full rect, converts indices */
-ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+ImBuf *ED_view3d_backbuf_read(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
{
unsigned int *dr, *rd;
struct ImBuf *ibuf, *ibuf1;
@@ -1501,7 +1511,7 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax,
ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect);
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
view3d_opengl_read_pixels(vc->ar,
xminc, yminc,
@@ -1541,23 +1551,21 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax,
}
/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *r_dist, short strict,
- void *handle, bool (*indextest)(void *handle, unsigned int index))
+unsigned int ED_view3d_backbuf_sample_rect(
+ ViewContext *vc, const int mval[2], int size,
+ unsigned int min, unsigned int max, float *r_dist)
{
struct ImBuf *buf;
- unsigned int *bufmin, *bufmax, *tbuf;
+ const unsigned int *bufmin, *bufmax, *tbuf;
int minx, miny;
int a, b, rc, nr, amount, dirvec[4][2];
- int distance = 0;
unsigned int index = 0;
- bool indexok = false;
amount = (size - 1) / 2;
minx = mval[0] - (amount + 1);
miny = mval[1] - (amount + 1);
- buf = view3d_read_backbuf(vc, minx, miny, minx + size - 1, miny + size - 1);
+ buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1);
if (!buf) return 0;
rc = 0;
@@ -1575,21 +1583,19 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int
for (nr = 1; nr <= size; nr++) {
for (a = 0; a < 2; a++) {
- for (b = 0; b < nr; b++, distance++) {
- if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */
- if (strict) {
- indexok = indextest(handle, *tbuf - min + 1);
- if (indexok) {
- *r_dist = sqrtf((float)distance);
- index = *tbuf - min + 1;
- goto exit;
- }
- }
- else {
- *r_dist = sqrtf((float)distance); /* XXX, this distance is wrong - */
- index = *tbuf - min + 1; /* messy yah, but indices start at 1 */
- goto exit;
- }
+ for (b = 0; b < nr; b++) {
+ if (*tbuf && *tbuf >= min && *tbuf < max) {
+ /* we got a hit */
+
+ /* get x,y pixel coords from the offset
+ * (manhatten distance in keeping with other screen-based selection) */
+ *r_dist = (float)(
+ abs(((int)(tbuf - buf->rect) % size) - (size / 2)) +
+ abs(((int)(tbuf - buf->rect) / size) - (size / 2)));
+
+ /* indices start at 1 here */
+ index = (*tbuf - min) + 1;
+ goto exit;
}
tbuf += (dirvec[rc][0] + dirvec[rc][1]);
@@ -1616,17 +1622,19 @@ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, Ima
if ((ima->flag & IMA_IS_STEREO)) {
iuser->flag |= IMA_SHOW_STEREO;
- if ((scene->r.scemode & R_MULTIVIEW) == 0)
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
iuser->multiview_eye = STEREO_LEFT_ID;
-
- /* show only left or right camera */
- else if (v3d->stereo3d_camera != STEREO_3D_ID)
+ }
+ else if (v3d->stereo3d_camera != STEREO_3D_ID) {
+ /* show only left or right camera */
iuser->multiview_eye = v3d->stereo3d_camera;
+ }
BKE_image_multiview_index(ima, iuser);
}
- else
+ else {
iuser->flag &= ~IMA_SHOW_STEREO;
+ }
}
static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
@@ -2719,7 +2727,7 @@ static void view3d_draw_objects(
const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
/* only draw grids after in solid modes, else it hovers over mesh wires */
- const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE);
+ const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
bool do_composite_xray = false;
bool xrayclear = true;
@@ -2768,8 +2776,8 @@ static void view3d_draw_objects(
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(rv3d->viewmat);
}
- else {
- drawfloor(scene, v3d, grid_unit);
+ else if (!draw_grids_after) {
+ drawfloor(scene, v3d, grid_unit, true);
}
}
@@ -2847,7 +2855,7 @@ static void view3d_draw_objects(
/* perspective floor goes last to use scene depth and avoid writing to depth buffer */
if (draw_grids_after) {
- drawfloor(scene, v3d, grid_unit);
+ drawfloor(scene, v3d, grid_unit, false);
}
/* must be before xray draw which clears the depth buffer */
@@ -2932,21 +2940,41 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
if (glsl) {
RegionView3D *rv3d = ar->regiondata;
GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
+ bool material_not_bound;
/* calculate full shader for background */
GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
+ material_not_bound = !GPU_material_bound(gpumat);
+
+ if (material_not_bound) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glShadeModel(GL_SMOOTH);
- glBegin(GL_QUADS);
+ glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
- glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
+ glVertex3f(1.0, 1.0, 1.0);
glEnd();
glShadeModel(GL_FLAT);
+ if (material_not_bound) {
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+
GPU_material_unbind(gpumat);
glDepthFunc(GL_LEQUAL);
@@ -3160,7 +3188,7 @@ void ED_view3d_draw_offscreen(
}
/* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
- if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL))
+ 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_area_setup_view(scene, v3d, ar, viewmat, winmat);
@@ -3563,7 +3591,7 @@ static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d,
if (WM_stereo3d_enabled(win, true) == false)
return false;
- if ((v3d->camera == NULL) || 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) {
@@ -3701,7 +3729,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
#endif
/* framebuffer fx needed, we need to draw offscreen first */
- if (v3d->fx_settings.fx_flag) {
+ if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) {
GPUFXSettings fx_settings;
BKE_screen_gpu_fx_validate(&v3d->fx_settings);
fx_settings = v3d->fx_settings;
@@ -3714,9 +3742,6 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
fx_settings.dof = NULL;
}
- if (v3d->drawtype < OB_SOLID)
- fx_settings.ssao = NULL;
-
do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 236fefc7088..2ae638b22e4 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -517,6 +517,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
typedef struct ViewOpsData {
/* context pointers (assigned by viewops_data_alloc) */
+ Scene *scene;
ScrArea *sa;
ARegion *ar;
View3D *v3d;
@@ -589,6 +590,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
/* store data */
op->customdata = vod;
+ vod->scene = CTX_data_scene(C);
vod->sa = CTX_wm_area(C);
vod->ar = CTX_wm_region(C);
vod->v3d = vod->sa->spacedata.first;
@@ -1310,7 +1312,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
ot->cancel = viewrotate_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
/** \name NDOF Utility Functions
@@ -2053,7 +2055,7 @@ void VIEW3D_OT_move(wmOperatorType *ot)
ot->cancel = viewmove_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
}
/* ************************ viewzoom ******************************** */
@@ -2093,16 +2095,63 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
}
-static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
+static void view_zoom_mouseloc_camera(
+ Scene *scene, View3D *v3d,
+ ARegion *ar, float dfac, int mx, int my)
{
RegionView3D *rv3d = ar->regiondata;
+ const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
+ const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
+ const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
+
+
+ if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ float zoomfac_px;
+ rctf camera_frame_old;
+ rctf camera_frame_new;
+
+ const float pt_src[2] = {mx, my};
+ float pt_dst[2];
+ float delta_px[2];
+
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false);
+ BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
+
+ rv3d->camzoom = camzoom_new;
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false);
+ BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
+
+ BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
+ sub_v2_v2v2(delta_px, pt_dst, pt_src);
+
+ /* translate the camera offset using pixel space delta
+ * mapped back to the camera (same logic as panning in camera view) */
+ zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
+
+ rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px);
+ rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px);
+ CLAMP(rv3d->camdx, -1.0f, 1.0f);
+ CLAMP(rv3d->camdy, -1.0f, 1.0f);
+ }
+ else {
+ rv3d->camzoom = camzoom_new;
+ CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
+ }
+}
+
+static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ const float dist_new = rv3d->dist * dfac;
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
float dvec[3];
float tvec[3];
float tpos[3];
float mval_f[2];
- float new_dist;
+
float zfac;
negate_v3_v3(tpos, rv3d->ofs);
@@ -2119,105 +2168,133 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
negate_v3(tvec);
/* Offset to target position and dolly */
- new_dist = rv3d->dist * dfac;
-
copy_v3_v3(rv3d->ofs, tvec);
- rv3d->dist = new_dist;
+ rv3d->dist = dist_new;
/* Calculate final offset */
madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
}
else {
- rv3d->dist *= dfac;
+ rv3d->dist = dist_new;
}
}
-
-static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzoom, const short zoom_invert)
+static float viewzoom_scale_value(
+ const rcti *winrct,
+ const short viewzoom,
+ const bool zoom_invert, const bool zoom_invert_force,
+ const int xy[2], const int xy_orig[2],
+ const float val, const float val_orig,
+ double *r_timer_lastdraw)
{
- float zfac = 1.0;
- bool use_cam_zoom;
- float dist_range[2];
-
- use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d));
-
- ED_view3d_dist_range_get(vod->v3d, dist_range);
-
- if (use_cam_zoom) {
- float delta;
- delta = (xy[0] - vod->origx + xy[1] - vod->origy) / 10.0f;
- vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta);
-
- CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- }
+ float zfac;
if (viewzoom == USER_ZOOM_CONT) {
double time = PIL_check_seconds_timer();
- float time_step = (float)(time - vod->timer_lastdraw);
+ float time_step = (float)(time - *r_timer_lastdraw);
float fac;
if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(vod->origx - xy[0]);
+ fac = (float)(xy_orig[0] - xy[0]);
}
else {
- fac = (float)(vod->origy - xy[1]);
+ fac = (float)(xy_orig[1] - xy[1]);
}
- if (zoom_invert) {
+ if (zoom_invert != zoom_invert_force) {
fac = -fac;
}
/* oldstyle zoom */
zfac = 1.0f + ((fac / 20.0f) * time_step);
- vod->timer_lastdraw = time;
+ *r_timer_lastdraw = time;
}
else if (viewzoom == USER_ZOOM_SCALE) {
/* method which zooms based on how far you move the mouse */
const int ctr[2] = {
- BLI_rcti_cent_x(&vod->ar->winrct),
- BLI_rcti_cent_y(&vod->ar->winrct),
+ BLI_rcti_cent_x(winrct),
+ BLI_rcti_cent_y(winrct),
};
- const float len_new = 5 + len_v2v2_int(ctr, xy);
- const float len_old = 5 + len_v2v2_int(ctr, &vod->origx);
- zfac = vod->dist_prev * ((len_old + 5) / (len_new + 5)) / vod->rv3d->dist;
+ float len_new = 5 + len_v2v2_int(ctr, xy);
+ float len_old = 5 + len_v2v2_int(ctr, xy_orig);
+
+ /* intentionally ignore 'zoom_invert' for scale */
+ if (zoom_invert_force) {
+ SWAP(float, len_new, len_old);
+ }
+
+ zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
}
else { /* USER_ZOOM_DOLLY */
- float len1, len2;
-
+ float len_new = 5;
+ float len_old = 5;
+
if (U.uiflag & USER_ZOOM_HORIZ) {
- len1 = (vod->ar->winrct.xmax - xy[0]) + 5;
- len2 = (vod->ar->winrct.xmax - vod->origx) + 5;
+ len_new += (winrct->xmax - xy[0]);
+ len_old += (winrct->xmax - xy_orig[0]);
}
else {
- len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
- len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
- }
- if (zoom_invert) {
- SWAP(float, len1, len2);
+ len_new += (winrct->ymax - xy[1]);
+ len_old += (winrct->ymax - xy_orig[1]);
}
-
- if (use_cam_zoom) {
- /* zfac is ignored in this case, see below */
-#if 0
- zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom;
-#endif
- }
- else {
- zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist;
+
+ if (zoom_invert != zoom_invert_force) {
+ SWAP(float, len_new, len_old);
}
+
+ zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
}
- if (!use_cam_zoom) {
- if (zfac != 1.0f) {
- const float zfac_min = dist_range[0] / vod->rv3d->dist;
- const float zfac_max = dist_range[1] / vod->rv3d->dist;
- CLAMP(zfac, zfac_min, zfac_max);
- if (zfac != 1.0f) {
- view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
- }
- }
+ return zfac;
+}
+
+static void viewzoom_apply_camera(
+ ViewOpsData *vod, const int xy[2],
+ const short viewzoom, const bool zoom_invert)
+{
+ float zfac;
+ float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f;
+ float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
+
+ zfac = viewzoom_scale_value(
+ &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx,
+ zoomfac, zoomfac_prev,
+ &vod->timer_lastdraw);
+
+ if (zfac != 1.0f && zfac != 0.0f) {
+ /* calculate inverted, then invert again (needed because of camera zoom scaling) */
+ zfac = 1.0f / zfac;
+ view_zoom_mouseloc_camera(
+ vod->scene, vod->v3d,
+ vod->ar, zfac, vod->oldx, vod->oldy);
+ }
+
+ ED_region_tag_redraw(vod->ar);
+}
+
+static void viewzoom_apply_3d(
+ ViewOpsData *vod, const int xy[2],
+ const short viewzoom, const bool zoom_invert)
+{
+ float zfac;
+ float dist_range[2];
+
+ ED_view3d_dist_range_get(vod->v3d, dist_range);
+
+ zfac = viewzoom_scale_value(
+ &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx,
+ vod->rv3d->dist, vod->dist_prev,
+ &vod->timer_lastdraw);
+
+ if (zfac != 1.0f) {
+ const float zfac_min = dist_range[0] / vod->rv3d->dist;
+ const float zfac_max = dist_range[1] / vod->rv3d->dist;
+ CLAMP(zfac, zfac_min, zfac_max);
+
+ view_zoom_mouseloc_3d(
+ vod->ar, zfac, vod->oldx, vod->oldy);
}
/* these limits were in old code too */
@@ -2231,6 +2308,19 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo
ED_region_tag_redraw(vod->ar);
}
+static void viewzoom_apply(
+ ViewOpsData *vod, const int xy[2],
+ const short viewzoom, const bool zoom_invert)
+{
+ if ((vod->rv3d->persp == RV3D_CAMOB) &&
+ (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0)
+ {
+ viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert);
+ }
+ else {
+ viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert);
+ }
+}
static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -2291,6 +2381,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int viewzoom_exec(bContext *C, wmOperator *op)
{
+ Scene *scene = CTX_data_scene(C);
View3D *v3d;
RegionView3D *rv3d;
ScrArea *sa;
@@ -2323,22 +2414,26 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
ED_view3d_dist_range_get(v3d, dist_range);
if (delta < 0) {
+ const float step = 1.2f;
/* this min and max is also in viewmove() */
if (use_cam_zoom) {
- rv3d->camzoom -= 10.0f;
- if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV3D_CAMZOOM_MIN;
+ view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my);
}
- else if (rv3d->dist < dist_range[1]) {
- view_zoom_mouseloc(ar, 1.2f, mx, my);
+ else {
+ if (rv3d->dist < dist_range[1]) {
+ view_zoom_mouseloc_3d(ar, step, mx, my);
+ }
}
}
else {
+ const float step = 1.0f / 1.2f;
if (use_cam_zoom) {
- rv3d->camzoom += 10.0f;
- if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV3D_CAMZOOM_MAX;
+ view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my);
}
- else if (rv3d->dist > dist_range[0]) {
- view_zoom_mouseloc(ar, 0.83333f, mx, my);
+ else {
+ if (rv3d->dist > dist_range[0]) {
+ view_zoom_mouseloc_3d(ar, step, mx, my);
+ }
}
}
@@ -2468,7 +2563,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
ot->cancel = viewzoom_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
@@ -2722,7 +2817,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
ot->cancel = viewdolly_cancel;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index a3dfd62ba6b..469a7e63903 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -296,10 +296,10 @@ static void fly_update_header(bContext *C, FlyInfo *fly)
"Ctrl: free look, "
"X: Upright x axis (%s), "
"Z: Upright z axis (%s), "
- "(+/- | Wheel): speed"),
+ "(+/- | Wheel): speed"),
WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF),
- WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF));
+ WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF));
ED_area_headerprint(CTX_wm_area(C), header);
#undef HEADER_LENGTH
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 74e3fde0eec..ba0626c58ea 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -605,6 +605,14 @@ void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pm
mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
}
+void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obmat[4][4], float pmat[4][4])
+{
+ float vmat[4][4];
+
+ mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, obmat);
+ mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
+}
+
/**
* Uses window coordinates (x,y) and depth component z to find a point in
* modelspace */
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index eba31866f54..98b1e846c70 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -187,8 +187,9 @@ typedef struct RulerInfo {
/* wm state */
wmWindow *win;
- ARegion *ar;
+ ScrArea *sa;
void *draw_handle_pixel;
+ ARegion *ar; /* re-assigned every modal update */
} RulerInfo;
/* -------------------------------------------------------------------- */
@@ -435,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
UnitSettings *unit = &scene->unit;
RulerItem *ruler_item;
RulerInfo *ruler_info = arg;
- RegionView3D *rv3d = ruler_info->ar->regiondata;
+ RegionView3D *rv3d = ar->regiondata;
// ARegion *ar = ruler_info->ar;
const float cap_size = 4.0f;
const float bg_margin = 4.0f * U.pixelsize;
@@ -798,12 +799,14 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
op->customdata = ruler_info;
ruler_info->win = win;
- ruler_info->ar = ar;
+ ruler_info->sa = sa;
ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel,
ruler_info, REGION_DRAW_POST_PIXEL);
view3d_ruler_header_update(sa);
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+
WM_cursor_modal_set(win, BC_CROSSCURSOR);
WM_event_add_modal_handler(C, op);
@@ -825,15 +828,17 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
int exit_code = OPERATOR_RUNNING_MODAL;
RulerInfo *ruler_info = op->customdata;
ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = ruler_info->ar;
+ ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
/* its possible to change spaces while running the operator [#34894] */
- if (UNLIKELY(ar != CTX_wm_region(C))) {
+ if (UNLIKELY(sa != ruler_info->sa)) {
exit_code = OPERATOR_FINISHED;
goto exit;
}
+ ruler_info->ar = ar;
+
switch (event->type) {
case LEFTMOUSE:
if (event->val == KM_RELEASE) {
@@ -1019,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
+ }
+ else {
+ op->flag |= OP_IS_MODAL_CURSOR_REGION;
+ }
+
if (do_draw) {
view3d_ruler_header_update(sa);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 2e30f38c053..1847de3c6a2 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -727,7 +727,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv,
}
static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
- const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Object *ob = vc->obact;
Mesh *me = ob->data;
rcti rect;
@@ -1645,7 +1645,7 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con
}
static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
- const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Mesh *me;
MVert *mvert;
struct ImBuf *ibuf;
@@ -1666,7 +1666,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo
if (use_zbuf) {
selar = MEM_callocN(me->totvert + 1, "selar");
- view3d_validate_backbuf(vc);
+ ED_view3d_backbuf_validate(vc);
ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
rt = ibuf->rect;
@@ -2192,7 +2192,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
static bool mouse_weight_paint_vertex_select(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, Object *obact)
{
View3D *v3d = CTX_wm_view3d(C);
- const int use_zbuf = (v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (v3d->flag & V3D_ZBUF_SELECT) != 0;
Mesh *me = obact->data; /* already checked for NULL */
unsigned int index = 0;
@@ -2462,7 +2462,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv,
}
static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
{
- const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Object *ob = vc->obact;
Mesh *me = ob->data;
bool bbsel;
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 11756e4feca..fb98f8b91a7 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -344,7 +344,7 @@ static void walk_update_header(bContext *C, WalkInfo *walk)
char header[HEADER_LENGTH];
BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB/Return: confirm, Esc/RMB: cancel, "
- "Tab: gravity (%s), "
+ "Tab: gravity (%s), "
"WASD: move around, "
"Shift: fast, Alt: slow, "
"QE: up and down, MMB/Space: teleport, V: jump, "
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index f8e529aa4bf..3cf0c53d564 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -54,6 +54,7 @@
#include "BLI_memarena.h"
#include "BKE_nla.h"
+#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
@@ -911,7 +912,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
{
if (!(t->flag & T_NO_CONSTRAINT)) {
int constraint_axis, constraint_plane;
- int edit_2d = (t->flag & T_2D_EDIT);
+ const bool edit_2d = (t->flag & T_2D_EDIT) != 0;
const char *msg1 = "", *msg2 = "", *msg3 = "";
char axis;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 4d7537a02f9..844a4bbc33b 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -39,9 +39,6 @@
#include "DNA_listBase.h"
-#include "BLI_smallhash.h"
-#include "BKE_editmesh.h"
-
/* ************************** Types ***************************** */
struct TransInfo;
@@ -261,7 +258,7 @@ typedef struct EdgeSlideData {
typedef struct TransDataVertSlideVert {
/* TransDataGenericSlideVert */
- BMVert *v;
+ struct BMVert *v;
struct LinkNode **cd_loop_groups;
float co_orig_3d[3];
/* end generic */
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 0bf419b3f75..14bea356cac 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -31,6 +31,7 @@
#include <string.h>
#include <math.h>
+#include <limits.h>
#include "DNA_anim_types.h"
#include "DNA_brush_types.h"
@@ -342,20 +343,20 @@ static void createTransEdge(TransInfo *t)
BMIter iter;
float mtx[3][3], smtx[3][3];
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
int cd_edge_float_offset;
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
}
if (countsel == 0)
return;
- if (propmode) {
+ if (is_prop_edit) {
t->total = count;
}
else {
@@ -381,7 +382,7 @@ static void createTransEdge(TransInfo *t)
BLI_assert(cd_edge_float_offset != -1);
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) {
float *fl_ptr;
/* need to set center for center calculations */
mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
@@ -1331,18 +1332,18 @@ static void createTransMBallVerts(TransInfo *t)
TransDataExtension *tx;
float mtx[3][3], smtx[3][3];
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
/* count totals */
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (ml->flag & SELECT) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(MBall EditMode)");
@@ -1352,7 +1353,7 @@ static void createTransMBallVerts(TransInfo *t)
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (propmode || (ml->flag & SELECT)) {
+ if (is_prop_edit || (ml->flag & SELECT)) {
td->loc = &ml->x;
copy_v3_v3(td->iloc, td->loc);
copy_v3_v3(td->center, td->loc);
@@ -1465,7 +1466,7 @@ static void createTransCurveVerts(TransInfo *t)
float mtx[3][3], smtx[3][3];
int a;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
ListBase *nurbs;
@@ -1480,13 +1481,13 @@ static void createTransCurveVerts(TransInfo *t)
if (bezt->hide == 0) {
if (hide_handles) {
if (bezt->f2 & SELECT) countsel += 3;
- if (propmode) count += 3;
+ if (is_prop_edit) count += 3;
}
else {
if (bezt->f1 & SELECT) countsel++;
if (bezt->f2 & SELECT) countsel++;
if (bezt->f3 & SELECT) countsel++;
- if (propmode) count += 3;
+ if (is_prop_edit) count += 3;
}
}
}
@@ -1494,7 +1495,7 @@ static void createTransCurveVerts(TransInfo *t)
else {
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
- if (propmode) count++;
+ if (is_prop_edit) count++;
if (bp->f1 & SELECT) countsel++;
}
}
@@ -1503,7 +1504,7 @@ static void createTransCurveVerts(TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
@@ -1538,7 +1539,7 @@ static void createTransCurveVerts(TransInfo *t)
}
}
- if (propmode ||
+ if (is_prop_edit ||
((bezt->f2 & SELECT) && hide_handles) ||
((bezt->f1 & SELECT) && hide_handles == 0))
{
@@ -1572,7 +1573,7 @@ static void createTransCurveVerts(TransInfo *t)
}
/* This is the Curve Point, the other two are handles */
- if (propmode || (bezt->f2 & SELECT)) {
+ if (is_prop_edit || (bezt->f2 & SELECT)) {
copy_v3_v3(td->iloc, bezt->vec[1]);
td->loc = bezt->vec[1];
copy_v3_v3(td->center, td->loc);
@@ -1608,7 +1609,7 @@ static void createTransCurveVerts(TransInfo *t)
count++;
tail++;
}
- if (propmode ||
+ if (is_prop_edit ||
((bezt->f2 & SELECT) && hide_handles) ||
((bezt->f3 & SELECT) && hide_handles == 0))
{
@@ -1645,12 +1646,12 @@ static void createTransCurveVerts(TransInfo *t)
(void)hdata; /* quiet warning */
}
- else if (propmode && head != tail) {
+ else if (is_prop_edit && head != tail) {
calc_distanceCurveVerts(head, tail - 1);
head = tail;
}
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
/* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
@@ -1665,7 +1666,7 @@ static void createTransCurveVerts(TransInfo *t)
head = tail = td;
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
- if (propmode || (bp->f1 & SELECT)) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
copy_v3_v3(td->center, td->loc);
@@ -1690,12 +1691,12 @@ static void createTransCurveVerts(TransInfo *t)
tail++;
}
}
- else if (propmode && head != tail) {
+ else if (is_prop_edit && head != tail) {
calc_distanceCurveVerts(head, tail - 1);
head = tail;
}
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
}
}
@@ -1711,14 +1712,14 @@ static void createTransLatticeVerts(TransInfo *t)
float mtx[3][3], smtx[3][3];
int a;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
bp = latt->def;
a = latt->pntsu * latt->pntsv * latt->pntsw;
while (a--) {
if (bp->hide == 0) {
if (bp->f1 & SELECT) countsel++;
- if (propmode) count++;
+ if (is_prop_edit) count++;
}
bp++;
}
@@ -1726,7 +1727,7 @@ static void createTransLatticeVerts(TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) return;
- if (propmode) t->total = count;
+ if (is_prop_edit) t->total = count;
else t->total = countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)");
@@ -1737,7 +1738,7 @@ static void createTransLatticeVerts(TransInfo *t)
bp = latt->def;
a = latt->pntsu * latt->pntsv * latt->pntsw;
while (a--) {
- if (propmode || (bp->f1 & SELECT)) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
if (bp->hide == 0) {
copy_v3_v3(td->iloc, bp->vec);
td->loc = bp->vec;
@@ -1778,7 +1779,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
float mat[4][4];
int i, k, transformparticle;
int count = 0, hasselected = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
@@ -1800,7 +1801,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
hasselected = 1;
transformparticle = 1;
}
- else if (propmode)
+ else if (is_prop_edit)
transformparticle = 1;
}
}
@@ -1850,7 +1851,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
if (key->flag & PEK_SELECT)
td->flag |= TD_SELECTED;
- else if (!propmode)
+ else if (!is_prop_edit)
td->flag |= TD_SKIP;
unit_m3(td->mtx);
@@ -1879,7 +1880,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
tx++;
tail++;
}
- if (propmode && head != tail)
+ if (is_prop_edit && head != tail)
calc_distanceCurveVerts(head, tail - 1);
}
}
@@ -1895,7 +1896,8 @@ void flushTransParticles(TransInfo *t)
PTCacheEditKey *key;
TransData *td;
float mat[4][4], imat[4][4], co[3];
- int i, k, propmode = t->flag & T_PROP_EDIT;
+ int i, k;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
if (psys)
psmd = psys_get_modifier(ob, psys);
@@ -1916,7 +1918,7 @@ void flushTransParticles(TransInfo *t)
/* optimization for proportional edit */
- if (!propmode || !compare_v3v3(key->co, co, 0.0001f)) {
+ if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
copy_v3_v3(key->co, co);
point->flag |= PEP_EDIT_RECALC;
}
@@ -2487,7 +2489,7 @@ static void createTransEditVerts(TransInfo *t)
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
float *dists = NULL;
int a;
- int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
+ const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
int mirror = 0;
int cd_vert_bweight_offset = -1;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
@@ -2527,7 +2529,7 @@ static void createTransEditVerts(TransInfo *t)
cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
}
- if (propmode) {
+ if (prop_mode) {
unsigned int count = 0;
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
@@ -2538,7 +2540,7 @@ static void createTransEditVerts(TransInfo *t)
t->total = count;
/* allocating scratch arrays */
- if (propmode & T_PROP_CONNECTED)
+ if (prop_mode & T_PROP_CONNECTED)
dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
}
else {
@@ -2560,7 +2562,7 @@ static void createTransEditVerts(TransInfo *t)
* matrix inversion still works and we can still moving along the other */
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
- if (propmode & T_PROP_CONNECTED) {
+ if (prop_mode & T_PROP_CONNECTED) {
editmesh_set_connectivity_distance(em->bm, mtx, dists);
}
@@ -2589,7 +2591,7 @@ static void createTransEditVerts(TransInfo *t)
{
mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit);
quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
- BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !propmode);
+ BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
if (mappedcos)
MEM_freeN(mappedcos);
}
@@ -2614,7 +2616,7 @@ static void createTransEditVerts(TransInfo *t)
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ?
&island_info[island_vert_map[a]] : NULL;
float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
@@ -2627,8 +2629,8 @@ static void createTransEditVerts(TransInfo *t)
if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
tob->flag |= TD_SELECTED;
- if (propmode) {
- if (propmode & T_PROP_CONNECTED) {
+ if (prop_mode) {
+ if (prop_mode & T_PROP_CONNECTED) {
tob->dist = dists[a];
}
else {
@@ -2933,15 +2935,15 @@ static void createTransUVs(bContext *C, TransInfo *t)
UvElementMap *elementmap = NULL;
BLI_bitmap *island_enabled = NULL;
int count = 0, countsel = 0, count_rejected = 0;
- const bool propmode = (t->flag & T_PROP_EDIT) != 0;
- const bool propconnected = (t->flag & T_PROP_CONNECTED) != 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
if (!ED_space_image_show_uvedit(sima, t->obedit)) return;
/* count */
- if (propconnected) {
+ if (is_prop_connected) {
/* create element map with island information */
if (ts->uv_flag & UV_SYNC_SELECTION) {
elementmap = BM_uv_element_map_create(em->bm, false, true);
@@ -2965,14 +2967,14 @@ static void createTransUVs(bContext *C, TransInfo *t)
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
countsel++;
- if (propconnected) {
+ if (is_prop_connected) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
BLI_BITMAP_ENABLE(island_enabled, element->island);
}
}
- if (propmode) {
+ if (is_prop_edit) {
count++;
}
}
@@ -2980,13 +2982,13 @@ static void createTransUVs(bContext *C, TransInfo *t)
/* note: in prop mode we need at least 1 selected */
if (countsel == 0) {
- if (propconnected) {
+ if (is_prop_connected) {
MEM_freeN(island_enabled);
}
return;
}
- t->total = (propmode) ? count : countsel;
+ t->total = (is_prop_edit) ? count : countsel;
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(UV Editing)");
/* for each 2d uv coord a 3d vector is allocated, so that they can be
* treated just as if they were 3d verts */
@@ -3003,10 +3005,10 @@ static void createTransUVs(bContext *C, TransInfo *t)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (!propmode && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
+ if (!is_prop_edit && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
continue;
- if (propconnected) {
+ if (is_prop_connected) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
if (!BLI_BITMAP_TEST(island_enabled, element->island)) {
count_rejected++;
@@ -3019,7 +3021,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
}
}
- if (propconnected) {
+ if (is_prop_connected) {
t->total -= count_rejected;
BM_uv_element_map_free(elementmap);
MEM_freeN(island_enabled);
@@ -3534,7 +3536,7 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act)
/* ----------------------------- */
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit)
+static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool is_prop_edit)
{
BezTriple *bezt;
int i, count = 0, count_all = 0;
@@ -3554,13 +3556,13 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit)
}
}
- if (propedit && count > 0)
+ if (is_prop_edit && count > 0)
return count_all;
else return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool propedit)
+static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool is_prop_edit)
{
bGPDframe *gpf;
int count = 0, count_all = 0;
@@ -3577,14 +3579,14 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool prop
}
}
- if (propedit && count > 0)
+ if (is_prop_edit && count > 0)
return count_all;
else
return count;
}
/* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool propedit)
+static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool is_prop_edit)
{
MaskLayerShape *masklayer_shape;
int count = 0, count_all = 0;
@@ -3601,7 +3603,7 @@ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, boo
}
}
- if (propedit && count > 0)
+ if (is_prop_edit && count > 0)
return count_all;
else
return count;
@@ -3631,7 +3633,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypo
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool propedit, float ypos)
+static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool is_prop_edit, float ypos)
{
BezTriple *bezt;
TransData2D *td2d = *td2dv;
@@ -3642,7 +3644,7 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
/* only add selected keyframes (for now, proportional edit is not enabled) */
- if (propedit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */
+ if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */
/* only add if on the right 'side' of the current frame */
if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
TimeToTransData(td, bezt->vec[1], adt, ypos);
@@ -3700,14 +3702,14 @@ void flushTransIntFrameActionData(TransInfo *t)
* The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
* on the named side are used.
*/
-static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool propedit, float ypos)
+static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool is_prop_edit, float ypos)
{
bGPDframe *gpf;
int count = 0;
/* check for select frames on right side of current frame */
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- if (propedit || (gpf->flag & GP_FRAME_SELECT)) {
+ if (is_prop_edit || (gpf->flag & GP_FRAME_SELECT)) {
if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) {
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = &tfd->val;
@@ -3731,14 +3733,14 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl,
}
/* refer to comment above #GPLayerToTransData, this is the same but for masks */
-static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool propedit, float ypos)
+static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool is_prop_edit, float ypos)
{
MaskLayerShape *masklay_shape;
int count = 0;
/* check for select frames on right side of current frame */
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
- if (propedit || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
+ if (is_prop_edit || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
/* memory is calloc'ed, so that should zero everything nicely for us */
td->val = &tfd->val;
@@ -3781,7 +3783,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
- const bool propedit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
int count = 0;
float cfra;
@@ -3824,11 +3826,11 @@ static void createTransActionData(bContext *C, TransInfo *t)
cfra = (float)CFRA;
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
- adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, propedit);
+ adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, is_prop_edit);
else if (ale->type == ANIMTYPE_GPLAYER)
- adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, propedit);
+ adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
else if (ale->type == ANIMTYPE_MASKLAYER)
- adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, propedit);
+ adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, is_prop_edit);
else
BLI_assert(0);
@@ -3874,7 +3876,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt;
- if (propedit && !ale->tag)
+ if (is_prop_edit && !ale->tag)
continue;
adt = ANIM_nla_mapping_get(&ac, ale);
@@ -3887,7 +3889,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
bGPDlayer *gpl = (bGPDlayer *)ale->data;
int i;
- i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, propedit, ypos);
+ i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos);
td += i;
tfd += i;
}
@@ -3895,7 +3897,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
MaskLayer *masklay = (MaskLayer *)ale->data;
int i;
- i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, propedit, ypos);
+ i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos);
td += i;
tfd += i;
}
@@ -3903,7 +3905,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
- td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, propedit, ypos);
+ td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos);
}
}
@@ -3933,7 +3935,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
}
/* calculate distances for proportional editing */
- if (propedit) {
+ if (is_prop_edit) {
td = t->data;
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -3959,13 +3961,14 @@ static void createTransActionData(bContext *C, TransInfo *t)
}
else {
bGPDframe *gpf_iter;
- float min = FLT_MAX;
+ int min = INT_MAX;
for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) {
if (gpf_iter->flag & GP_FRAME_SELECT) {
if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) {
- float val = fabsf(gpf->framenum - gpf_iter->framenum);
- if (val < min)
+ int val = abs(gpf->framenum - gpf_iter->framenum);
+ if (val < min) {
min = val;
+ }
}
}
}
@@ -3985,13 +3988,14 @@ static void createTransActionData(bContext *C, TransInfo *t)
}
else {
MaskLayerShape *masklay_iter;
- float min = FLT_MAX;
+ int min = INT_MAX;
for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) {
if (masklay_iter->flag & MASK_SHAPE_SELECT) {
if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) {
- float val = fabsf(masklay_shape->frame - masklay_iter->frame);
- if (val < min)
+ int val = abs(masklay_shape->frame - masklay_iter->frame);
+ if (val < min) {
min = val;
+ }
}
}
}
@@ -4181,7 +4185,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
const bool is_translation_mode = graph_edit_is_translation_mode(t);
const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
const bool use_local_center = graph_edit_use_local_center(t);
- const bool propedit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
/* determine what type of data we are operating on */
@@ -4235,7 +4239,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2;
const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2;
- if (propedit) {
+ if (is_prop_edit) {
curvecount += 3;
if (sel2 || sel1 || sel3)
selected = true;
@@ -4259,7 +4263,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
}
}
- if (propedit) {
+ if (is_prop_edit) {
if (selected) {
count += curvecount;
ale->tag = true;
@@ -4315,7 +4319,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
float cfra;
/* F-Curve may not have any keyframes */
- if (fcu->bezt == NULL || (propedit && ale->tag == 0))
+ if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0))
continue;
/* convert current-frame to action-time (slightly less accurate, especially under
@@ -4338,7 +4342,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
TransDataCurveHandleFlags *hdata = NULL;
/* short h1=1, h2=1; */ /* UNUSED */
- if (propedit) {
+ if (is_prop_edit) {
bool is_sel = (sel2 || sel1 || sel3);
/* we always select all handles for proportional editing if central handle is selected */
initTransDataCurveHandles(td, bezt);
@@ -4410,7 +4414,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
testhandles_fcurve(fcu, use_handle);
}
- if (propedit) {
+ if (is_prop_edit) {
/* loop 2: build transdata arrays */
td = t->data;
@@ -6529,7 +6533,7 @@ static void createTransObject(bContext *C, TransInfo *t)
TransData *td = NULL;
TransDataExtension *tx;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
set_trans_object_base_flags(t);
@@ -6542,7 +6546,7 @@ static void createTransObject(bContext *C, TransInfo *t)
return;
}
- if (propmode) {
+ if (is_prop_edit) {
t->total += count_proportional_objects(t);
}
@@ -6575,7 +6579,7 @@ static void createTransObject(bContext *C, TransInfo *t)
}
CTX_DATA_END;
- if (propmode) {
+ if (is_prop_edit) {
View3D *v3d = t->view;
Base *base;
@@ -7332,9 +7336,10 @@ static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which
}
}
-static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
- TransData *td, TransData2D *td2d, TransDataMasking *tdm,
- const int propmode, const float asp[2])
+static void MaskPointToTransData(
+ Scene *scene, MaskSplinePoint *point,
+ TransData *td, TransData2D *td2d, TransDataMasking *tdm,
+ const bool is_prop_edit, const float asp[2])
{
BezTriple *bezt = &point->bezt;
const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point);
@@ -7344,7 +7349,7 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
invert_m3_m3(parent_inverse_matrix, parent_matrix);
- if (propmode || is_sel_point) {
+ if (is_prop_edit || is_sel_point) {
int i;
tdm->point = point;
@@ -7464,7 +7469,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
TransData2D *td2d = NULL;
TransDataMasking *tdm = NULL;
int count = 0, countsel = 0;
- int propmode = t->flag & T_PROP_EDIT;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT);
float asp[2];
t->total = 0;
@@ -7514,7 +7519,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
}
}
- if (propmode)
+ if (is_prop_edit)
count += 3;
}
}
@@ -7527,7 +7532,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]);
- t->total = (propmode) ? count : countsel;
+ t->total = (is_prop_edit) ? count : countsel;
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mask Editing)");
/* for each 2d uv coord a 3d vector is allocated, so that they can be
* treated just as if they were 3d verts */
@@ -7550,10 +7555,10 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
- if (propmode || MASKPOINT_ISSEL_ANY(point)) {
- MaskPointToTransData(scene, point, td, td2d, tdm, propmode, asp);
+ if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) {
+ MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp);
- if (propmode || MASKPOINT_ISSEL_KNOT(point)) {
+ if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) {
td += 3;
td2d += 3;
tdm += 3;
@@ -7796,8 +7801,8 @@ static void createTransGPencil(bContext *C, TransInfo *t)
const Scene *scene = CTX_data_scene(C);
const int cfra = CFRA;
- const int propedit = (t->flag & T_PROP_EDIT);
- const int propedit_connected = (t->flag & T_PROP_CONNECTED);
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0;
/* == Grease Pencil Strokes to Transform Data ==
@@ -7828,9 +7833,9 @@ static void createTransGPencil(bContext *C, TransInfo *t)
continue;
}
- if (propedit) {
+ if (is_prop_edit) {
/* Proportional Editing... */
- if (propedit_connected) {
+ if (is_prop_edit_connected) {
/* connected only - so only if selected */
if (gps->flag & GP_STROKE_SELECT)
t->total += gps->totpoints;
@@ -7937,8 +7942,8 @@ static void createTransGPencil(bContext *C, TransInfo *t)
}
/* What we need to include depends on proportional editing settings... */
- if (propedit) {
- if (propedit_connected) {
+ if (is_prop_edit) {
+ if (is_prop_edit_connected) {
/* A) "Connected" - Only those in selected strokes */
stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0;
}
@@ -7957,7 +7962,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
bGPDspoint *pt;
int i;
-#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or propedit breaks */
+#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */
const float ninv = 1.0f / gps->totpoints;
float center[3] = {0.0f};
@@ -7972,7 +7977,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
bool point_ok;
/* include point? */
- if (propedit) {
+ if (is_prop_edit) {
/* Always all points in strokes that get included */
point_ok = true;
}
@@ -8015,7 +8020,7 @@ static void createTransGPencil(bContext *C, TransInfo *t)
}
/* March over these points, and calculate the proportional editing distances */
- if (propedit && (head != tail)) {
+ if (is_prop_edit && (head != tail)) {
/* XXX: for now, we are similar enough that this works... */
calc_distanceCurveVerts(head, tail - 1);
}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index fc8e6cd0286..ae8cbc721e3 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -895,6 +895,11 @@ static void postOrtho(const bool ortho)
}
}
+BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags)
+{
+ return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z));
+}
+
static void draw_manipulator_rotate(
View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo,
const bool is_moving, const bool is_picksel)
@@ -908,8 +913,8 @@ static void draw_manipulator_rotate(
const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB;
bool ortho;
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_ROT_C) == 0) return;
+ /* skip drawing if all axes are locked */
+ if (manipulator_rotate_is_visible(drawflags) == false) return;
/* Init stuff */
glDisable(GL_DEPTH_TEST);
@@ -1448,8 +1453,8 @@ static void draw_manipulator_rotate_cyl(
int axis_order[3] = {2, 0, 1};
int i;
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_ROT_C) == 0) return;
+ /* skip drawing if all axes are locked */
+ if (manipulator_rotate_is_visible(drawflags) == false) return;
manipulator_axis_order(rv3d, axis_order);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index e33bc19fc92..8e0b3d708e2 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -38,6 +38,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_report.h"
+#include "BKE_editmesh.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -488,7 +489,7 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* add temp handler */
WM_event_add_modal_handler(C, op);
- op->flag |= OP_GRAB_POINTER; // XXX maybe we want this with the manipulator only?
+ op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the manipulator only?
return OPERATOR_RUNNING_MODAL;
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index fd189e91141..e8a0f35c6b0 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -1400,11 +1400,8 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
if (arm->edbo) {
EditBone *eBone;
@@ -1762,11 +1759,8 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
switch (snap_mode) {
case SCE_SNAP_MODE_VERTEX:
@@ -2111,12 +2105,8 @@ static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4],
transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
/* If number of vert is more than an arbitrary limit,
* test against boundbox first
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index f4189a18da4..d1495d85e64 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../bmesh
+ ../../imbuf
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 438eb1f3864..433c7603f35 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -38,6 +38,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_packedFile_types.h"
@@ -58,9 +59,12 @@
#include "BKE_paint.h"
#include "ED_armature.h"
+#include "ED_buttons.h"
#include "ED_image.h"
#include "ED_mesh.h"
+#include "ED_node.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_paint.h"
#include "ED_space_api.h"
#include "ED_util.h"
@@ -318,3 +322,25 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
glEnd();
setlinestyle(0);
}
+
+/**
+ * Use to free ID references within runtime data (stored outside of DNA)
+ *
+ * \note Typically notifiers take care of this,
+ * but there are times we have to free references immediately, see: T44376
+ */
+void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id)
+{
+
+ switch (sl->spacetype) {
+ case SPACE_OUTLINER:
+ ED_outliner_id_unref((SpaceOops *)sl, id);
+ break;
+ case SPACE_BUTS:
+ ED_buttons_id_unref((SpaceButs *)sl, id);
+ break;
+ case SPACE_NODE:
+ ED_node_id_unref((SpaceNode *)sl, id);
+ break;
+ }
+}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 444c579a62b..2ec7fe677ae 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -3098,9 +3098,10 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ?
- (ts->selectmode == SCE_SELECT_FACE) :
- (ts->uv_selectmode == UV_SELECT_FACE);
+ const bool use_face_center = (
+ (ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode == SCE_SELECT_FACE) :
+ (ts->uv_selectmode == UV_SELECT_FACE));
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 793f84b05ec..f915a4b2e51 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -681,7 +681,7 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
/* identifiers */
ot->name = "Minimize Stretch";
ot->idname = "UV_OT_minimize_stretch";
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
ot->description = "Reduce UV stretching by relaxing angles";
/* api callbacks */
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
index add7420b89a..5cd2e16847d 100644
--- a/source/blender/freestyle/intern/application/Controller.cpp
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -927,6 +927,12 @@ void Controller::InsertStyleModule(unsigned index, const char *iFileName)
_Canvas->InsertStyleModule(index, sm);
}
+void Controller::InsertStyleModule(unsigned index, const char *iName, const char *iBuffer)
+{
+ StyleModule *sm = new BufferedStyleModule(iBuffer, iName, _inter);
+ _Canvas->InsertStyleModule(index, sm);
+}
+
void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText)
{
StyleModule *sm = new BlenderStyleModule(iText, iName, _inter);
diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h
index 9fe57d92cf4..a09964a4e79 100644
--- a/source/blender/freestyle/intern/application/Controller.h
+++ b/source/blender/freestyle/intern/application/Controller.h
@@ -90,6 +90,7 @@ public:
Render *RenderStrokes(Render *re, bool render);
void SwapStyleModules(unsigned i1, unsigned i2);
void InsertStyleModule(unsigned index, const char *iFileName);
+ void InsertStyleModule(unsigned index, const char *iName, const char *iBuffer);
void InsertStyleModule(unsigned index, const char *iName, struct Text *iText);
void AddStyleModule(const char *iFileName);
void RemoveStyleModule(unsigned index);
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 0e8f6222c8c..1ddc311b1ae 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -126,7 +126,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
BKE_scene_set_background(freestyle_bmain, freestyle_scene);
// Camera
- Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA);
+ Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL);
Camera *camera = (Camera *)object_camera->data;
camera->type = CAM_ORTHO;
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
index 2bc43798878..1d73125f627 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
@@ -36,6 +36,34 @@ struct Text;
namespace Freestyle {
+class BufferedStyleModule : public StyleModule
+{
+public:
+ BufferedStyleModule(const string& buffer, const string& file_name, Interpreter *inter) : StyleModule(file_name, inter)
+ {
+ _buffer = buffer;
+ }
+
+ virtual ~BufferedStyleModule()
+ {
+ }
+
+protected:
+ virtual int interpret()
+ {
+ PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter);
+ BLI_assert(py_inter != 0);
+ return py_inter->interpretString(_buffer, getFileName());
+ }
+
+private:
+ string _buffer;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BufferedStyleModule")
+#endif
+};
+
class BlenderStyleModule : public StyleModule
{
public:
@@ -62,7 +90,6 @@ private:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStyleModule")
#endif
-
};
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index 6b102410aa6..291ed98f905 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -211,16 +211,12 @@ static char *escape_quotes(char *name)
return s;
}
-static Text *create_lineset_handler(Main *bmain, char *layer_name, char *lineset_name)
+static char * create_lineset_handler(char *layer_name, char *lineset_name)
{
+ const char *fmt = "__import__('parameter_editor').process('%s', '%s')\n";
char *s1 = escape_quotes(layer_name);
char *s2 = escape_quotes(lineset_name);
- Text *text = BKE_text_add(bmain, lineset_name);
- BKE_text_write(text, "import parameter_editor; parameter_editor.process('");
- BKE_text_write(text, s1);
- BKE_text_write(text, "', '");
- BKE_text_write(text, s2);
- BKE_text_write(text, "')\n");
+ char *text = BLI_sprintfN(fmt, s1, s2);
MEM_freeN(s1);
MEM_freeN(s2);
return text;
@@ -293,7 +289,7 @@ static bool test_edge_type_conditions(struct edge_type_condition *conditions,
return true;
}
-static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl)
+static void prepare(Render *re, SceneRenderLayer *srl)
{
// load mesh
re->i.infostr = "Freestyle: Mesh loading";
@@ -369,9 +365,10 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl)
cout << " " << layer_count+1 << ": " << lineset->name << " - " <<
(lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl;
}
- Text *text = create_lineset_handler(bmain, srl->name, lineset->name);
- controller->InsertStyleModule(layer_count, lineset->name, text);
+ char *buffer = create_lineset_handler(srl->name, lineset->name);
+ controller->InsertStyleModule(layer_count, lineset->name, buffer);
controller->toggleLayer(layer_count, true);
+ MEM_freeN(buffer);
if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) {
++use_ridges_and_valleys;
++use_suggestive_contours;
@@ -584,9 +581,7 @@ void FRS_init_stroke_rendering(Render *re)
Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
{
- Main *freestyle_bmain = re->freestyle_bmain;
Render *freestyle_render = NULL;
- Text *text, *next_text;
if (!render)
return controller->RenderStrokes(re, false);
@@ -607,7 +602,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
// - add style modules
// - set parameters
// - compute view map
- prepare(freestyle_bmain, re, srl);
+ prepare(re, srl);
if (re->test_break(re->tbh)) {
controller->CloseFile();
@@ -635,14 +630,6 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
}
}
- // Free temp main (currently only text blocks are stored there)
- for (text = (Text *)freestyle_bmain->text.first; text; text = next_text) {
- next_text = (Text *) text->id.next;
-
- BKE_text_unlink(freestyle_bmain, text);
- BKE_libblock_free(freestyle_bmain, text);
- }
-
return freestyle_render;
}
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
index a214fc444c7..1b2b18c2c99 100644
--- a/source/blender/freestyle/intern/python/BPy_Operators.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -34,6 +34,8 @@
#include "BPy_StrokeShader.h"
#include "BPy_Convert.h"
+#include <sstream>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -539,7 +541,15 @@ static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyOb
PyErr_SetString(PyExc_TypeError, "Operators.create(): 2nd argument must be a list of StrokeShader objects");
return NULL;
}
- shaders.push_back(((BPy_StrokeShader *)py_ss)->ss);
+ StrokeShader *shader = ((BPy_StrokeShader *)py_ss)->ss;
+ if (!shader) {
+ stringstream ss;
+ ss << "Operators.create(): item " << (i + 1)
+ << " of the shaders list is invalid likely due to missing call of StrokeShader.__init__()";
+ PyErr_SetString(PyExc_TypeError, ss.str().c_str());
+ return NULL;
+ }
+ shaders.push_back(shader);
}
if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) {
if (!PyErr_Occurred())
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h
index 60193590944..ddb79b2df0b 100644
--- a/source/blender/freestyle/intern/system/PythonInterpreter.h
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.h
@@ -51,6 +51,8 @@ extern "C" {
#include "BKE_text.h"
#include "BPY_extern.h"
+
+#include "bpy_util.h"
}
namespace Freestyle {
@@ -105,6 +107,26 @@ public:
return 0;
}
+ int interpretString(const string& str, const string& name)
+ {
+ ReportList *reports = CTX_wm_reports(_context);
+
+ BKE_reports_clear(reports);
+
+ if (BPY_string_exec(_context, str.c_str()) != 0) {
+ BPy_errors_to_report(reports);
+ cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl;
+ cerr << "Name: " << name << endl;
+ cerr << "Errors: " << endl;
+ BKE_reports_print(reports, RPT_ERROR);
+ return 1;
+ }
+
+ BKE_reports_clear(reports);
+
+ return 0;
+ }
+
int interpretText(struct Text *text, const string& name)
{
ReportList *reports = CTX_wm_reports(_context);
diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h
index a74c0e7c67b..f89df2b54aa 100644
--- a/source/blender/gpu/GPU_debug.h
+++ b/source/blender/gpu/GPU_debug.h
@@ -63,7 +63,7 @@ void gpu_assert_no_gl_errors(const char *file, int line, const char *str);
#ifdef WITH_GPU_DEBUG
/* inserts a debug marker message for the debug context messaging system */
-void gpu_string_marker (size_t size, const char *str);
+void gpu_string_marker(size_t size, const char *str);
# define GPU_STRING_MARKER(size, str) gpu_string_marker((size), (str))
#else /* WITH_GPU_DEBUG */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 20aa4919416..845ae9d2b30 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -104,11 +104,11 @@ void GPU_render_text(struct MTFace *tface, int mode,
/* Mipmap settings
* - these will free textures on changes */
-void GPU_set_mipmap(int mipmap);
-int GPU_get_mipmap(void);
-void GPU_set_linear_mipmap(int linear);
-int GPU_get_linear_mipmap(void);
-void GPU_paint_set_mipmap(int mipmap);
+void GPU_set_mipmap(bool mipmap);
+bool GPU_get_mipmap(void);
+void GPU_set_linear_mipmap(bool linear);
+bool GPU_get_linear_mipmap(void);
+void GPU_paint_set_mipmap(bool mipmap);
/* Anisotropic filtering settings
* - these will free textures on changes */
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 27a4396e5d8..f3927ba960b 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -71,6 +71,9 @@ int GPU_max_texture_size(void);
int GPU_color_depth(void);
void GPU_get_dfdy_factors(float fac[2]);
+bool GPU_mem_stats_supported(void);
+void GPU_mem_stats_get(int *totalmem, int *freemem);
+
void GPU_code_generate_glsl_lib(void);
/* GPU Types */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index b61bdf969cc..7bb044a1ae3 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -186,7 +186,7 @@ bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, stru
void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, 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 obcol[4], float autobumpscale);
void GPU_material_unbind(GPUMaterial *material);
-int GPU_material_bound(GPUMaterial *material);
+bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index a0dde9c8f3b..7bcc51aef31 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -356,6 +356,7 @@ void gpu_assert_no_gl_errors(const char* file, int line, const char* str)
GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
BLI_assert(gl_ok);
+ (void) gl_ok;
}
}
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index daf6b90f604..a24067fc381 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -117,7 +117,7 @@ void GPU_render_text(MTFace *tface, int mode,
/* color has been set */
if (tface->mode & TF_OBCOL)
- col= NULL;
+ col = NULL;
else if (!col)
glColor3f(1.0f, 1.0f, 1.0f);
@@ -239,8 +239,12 @@ static struct GPUTextureState {
int curtileYRep, tileYRep;
Image *ima, *curima;
- int domipmap, linearmipmap;
- int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */
+ /* also controls min/mag filtering */
+ bool domipmap;
+ /* only use when 'domipmap' is set */
+ bool linearmipmap;
+ /* store this so that new images created while texture painting won't be set to mipmapped */
+ bool texpaint;
int alphablend;
float anisotropic;
@@ -281,49 +285,53 @@ static void gpu_generate_mipmap(GLenum target)
glDisable(target);
}
-void GPU_set_mipmap(int mipmap)
+void GPU_set_mipmap(bool mipmap)
{
- if (GTS.domipmap != (mipmap != 0)) {
+ if (GTS.domipmap != mipmap) {
GPU_free_images();
- GTS.domipmap = mipmap != 0;
+ GTS.domipmap = mipmap;
}
}
-void GPU_set_linear_mipmap(int linear)
+void GPU_set_linear_mipmap(bool linear)
{
- if (GTS.linearmipmap != (linear != 0)) {
- GPU_free_images();
- GTS.linearmipmap = linear != 0;
+ if (GTS.linearmipmap != linear) {
+ GTS.linearmipmap = linear;
}
}
-int GPU_get_mipmap(void)
+bool GPU_get_mipmap(void)
{
return GTS.domipmap && !GTS.texpaint;
}
-int GPU_get_linear_mipmap(void)
+bool GPU_get_linear_mipmap(void)
{
return GTS.linearmipmap;
}
-static GLenum gpu_get_mipmap_filter(int mag)
+static GLenum gpu_get_mipmap_filter(bool mag)
{
/* linearmipmap is off by default *when mipmapping is off,
* use unfiltered display */
if (mag) {
- if (GTS.linearmipmap || GTS.domipmap)
+ if (GTS.domipmap)
return GL_LINEAR;
else
return GL_NEAREST;
}
else {
- if (GTS.linearmipmap)
- return GL_LINEAR_MIPMAP_LINEAR;
- else if (GTS.domipmap)
- return GL_LINEAR_MIPMAP_NEAREST;
- else
+ if (GTS.domipmap) {
+ if (GTS.linearmipmap) {
+ return GL_LINEAR_MIPMAP_LINEAR;
+ }
+ else {
+ return GL_LINEAR_MIPMAP_NEAREST;
+ }
+ }
+ else {
return GL_NEAREST;
+ }
}
}
@@ -931,7 +939,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
* temporary disabling/enabling mipmapping on all images for quick texture
* updates with glTexSubImage2D. images that didn't change don't have to be
* re-uploaded to OpenGL */
-void GPU_paint_set_mipmap(int mipmap)
+void GPU_paint_set_mipmap(bool mipmap)
{
Image *ima;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 0d735d11902..54e3339eb29 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -560,7 +560,8 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
GPUTexture *tex;
GLenum type, format, internalformat;
void *pixels = NULL;
- const float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ int r_width;
+ bool rescale = false;
if (!GLEW_VERSION_1_2)
return NULL;
@@ -603,37 +604,90 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
internalformat = GL_INTENSITY;
}
+ /* 3D textures are quite heavy, test if it's possible to create them first */
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+
+ while (r_width == 0) {
+ rescale = true;
+ tex->w /= 2;
+ tex->h /= 2;
+ tex->depth /= 2;
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ }
+
+ /* really unlikely to happen but keep this just in case */
+ tex->w = max_ii(tex->w, 1);
+ tex->h = max_ii(tex->h, 1);
+ tex->depth = max_ii(tex->depth, 1);
+
#if 0
if (fpixels)
pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
#endif
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
-
GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
- if (fpixels) {
- if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
- /* clear first to avoid unitialized pixels */
- float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
- glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero);
- MEM_freeN(zero);
+ /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
+ * for gooseberry */
+ if (rescale && fpixels) {
+ unsigned int i, j, k;
+ unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
+ float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
+
+ GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+ for (k = 0; k < tex->depth; k++) {
+ for (j = 0; j < tex->h; j++) {
+ for (i = 0; i < tex->w; i++) {
+ /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
+ float xb = i * xf;
+ float yb = j * yf;
+ float zb = k * zf;
+ unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+ unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+
+ if (channels == 4) {
+ tex3d[offset * 4] = fpixels[offset_orig * 4];
+ tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+ tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+ tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+ }
+ else
+ tex3d[offset] = fpixels[offset_orig];
+ }
+ }
}
- glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
- GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
+
+ MEM_freeN(tex3d);
+ }
+ else {
+ if (fpixels) {
+ if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
+ /* clear first to avoid unitialized pixels */
+ float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero);
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
+ MEM_freeN(zero);
+ }
+ else {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
+ }
+
+ GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
+ }
}
- glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
- GPU_ASSERT_NO_GL_ERRORS("3D GL_TEXTURE_BORDER_COLOR");
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- GPU_ASSERT_NO_GL_ERRORS("3D GL_LINEAR");
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- GPU_ASSERT_NO_GL_ERRORS("3D GL_CLAMP_TO_BORDER");
if (pixels)
MEM_freeN(pixels);
@@ -2030,6 +2084,34 @@ void GPU_shader_free_builtin_shaders(void)
}
}
+bool GPU_mem_stats_supported(void)
+{
+ return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
+}
+
+
+void GPU_mem_stats_get(int *totalmem, int *freemem)
+{
+ if (GLEW_NVX_gpu_memory_info) {
+ /* returned value in Kb */
+ glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
+
+ glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
+ }
+ else if (GLEW_ATI_meminfo) {
+ int stats[4];
+
+ glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
+ *freemem = stats[0];
+ *totalmem = 0;
+ }
+ else {
+ *totalmem = 0;
+ *freemem = 0;
+ }
+}
+
+
#if 0 /* unused */
/* GPUPixelBuffer */
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 4d46ef3af7b..12672b5f5af 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -102,7 +102,6 @@ struct GPUMaterial {
/* for binding the material */
GPUPass *pass;
GPUVertexAttribs attribs;
- int bound;
int builtins;
int alpha, obcolalpha;
int dynproperty;
@@ -114,6 +113,7 @@ struct GPUMaterial {
int cameratexcofacloc;
ListBase lamps;
+ bool bound;
};
struct GPULamp {
@@ -400,7 +400,7 @@ void GPU_material_unbind(GPUMaterial *material)
}
}
-int GPU_material_bound(GPUMaterial *material)
+bool GPU_material_bound(GPUMaterial *material)
{
return material->bound;
}
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index a39832dd1cb..7c7f2db09d2 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -547,8 +547,21 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
const float col[4], struct ColorManagedDisplay *display,
int x1, int y1, int x2, int y2);
-/* defined in metadata.c */
+/**
+ *
+ * \attention Defined in metadata.c
+ */
+/** read the field from the image info into the field
+ * \param img - the ImBuf that contains the image data
+ * \param key - the key of the field
+ * \param value - the data in the field, first one found with key is returned,
+ * memory has to be allocated by user.
+ * \param len - length of value buffer allocated by user.
+ * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise
+ */
+bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len);
bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field);
+void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb);
/* exported for image tools in blender, to quickly allocate 32 bits rect */
bool imb_addrectImBuf(struct ImBuf *ibuf);
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 9327c15c415..0e6438fb729 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -88,7 +88,7 @@ int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags);
/* jpeg */
int imb_is_a_jpeg(unsigned char *mem);
int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags);
-struct ImBuf *imb_load_jpeg (unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
+struct ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
/* bmp */
int imb_is_a_bmp(unsigned char *buf);
diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h
index 5d4a0028ee1..bc0b2c70ecb 100644
--- a/source/blender/imbuf/intern/IMB_metadata.h
+++ b/source/blender/imbuf/intern/IMB_metadata.h
@@ -47,16 +47,6 @@ struct ImBuf;
/* free blender ImMetaData struct */
void IMB_metadata_free(struct ImBuf *img);
-/** read the field from the image info into the field
- * \param img - the ImBuf that contains the image data
- * \param key - the key of the field
- * \param value - the data in the field, first one found with key is returned,
- * memory has to be allocated by user.
- * \param len - length of value buffer allocated by user.
- * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise
- */
-bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len);
-
/** set user data in the ImMetaData struct, which has to be allocated with IMB_metadata_create
* before calling this function.
* \param img - the ImBuf that contains the image data
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index b28d19e3e15..79f869968d3 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -210,6 +210,8 @@ ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
rval = IMB_dupImBuf(ibuf);
+ IMB_metadata_copy(rval, ibuf);
+
IMB_freeImBuf(ibuf);
return rval;
@@ -465,10 +467,10 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
if (ibuf2 == NULL) return NULL;
if (flags & IB_rect)
- memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int));
+ memcpy(ibuf2->rect, ibuf1->rect, ((size_t)x) * y * sizeof(int));
if (flags & IB_rectfloat)
- memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float));
+ memcpy(ibuf2->rect_float, ibuf1->rect_float, ((size_t)ibuf1->channels) * x * y * sizeof(float));
if (ibuf1->encodedbuffer) {
ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 20baa1614c9..d6fdcad0819 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1306,8 +1306,8 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
float dither = ibuf->dither;
bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0;
- int offset = channels * start_line * ibuf->x;
- int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x;
+ size_t offset = ((size_t)channels) * start_line * ibuf->x;
+ size_t display_buffer_byte_offset = ((size_t)DISPLAY_BUFFER_CHANNELS) * start_line * ibuf->x;
memset(handle, 0, sizeof(DisplayBufferThread));
@@ -1344,7 +1344,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
int channels = handle->channels;
int width = handle->width;
- int buffer_size = channels * width * height;
+ size_t buffer_size = ((size_t)channels) * width * height;
bool is_data = handle->is_data;
bool is_data_display = handle->cm_processor->is_data_result;
@@ -1357,11 +1357,11 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
float *fp;
unsigned char *cp;
- int i;
+ size_t i;
/* first convert byte buffer to float, keep in image space */
for (i = 0, fp = linear_buffer, cp = byte_buffer;
- i < width * height;
+ i < ((size_t)width) * height;
i++, fp += channels, cp += channels)
{
if (channels == 3) {
@@ -1440,7 +1440,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
else {
bool is_straight_alpha, predivide;
- float *linear_buffer = MEM_mallocN(channels * width * height * sizeof(float),
+ float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float),
"color conversion linear buffer");
display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha);
@@ -1467,14 +1467,14 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
if (display_buffer) {
- memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float));
+ memcpy(display_buffer, linear_buffer, ((size_t)width) * height * channels * sizeof(float));
if (is_straight_alpha && channels == 4) {
- int i;
+ size_t i;
float *fp;
for (i = 0, fp = display_buffer;
- i < width * height;
+ i < ((size_t)width) * height;
i++, fp += channels)
{
straight_to_premul_v4(fp);
@@ -2959,7 +2959,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
- float *pixel = buffer + channels * (y * width + x);
+ float *pixel = buffer + channels * (((size_t)y) * width + x);
curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels);
}
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index 15c8d86d61c..6bf82776afe 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -60,6 +60,7 @@
#include <PixelFormat.h>
#include <stdio.h> // printf
+#include <stdlib.h> // malloc
#include <math.h> // sqrt
#include <sys/types.h>
@@ -1147,7 +1148,7 @@ void* DirectDrawSurface::readData(uint &rsize)
uint size = stream.size - header_size;
rsize = size;
- unsigned char *data = new unsigned char[size];
+ unsigned char *data = (unsigned char *)malloc(sizeof(*data) * size);
stream.seek(header_size);
mem_read(stream, data, size);
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 3417fe2fc1d..455b78bce4d 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -184,16 +184,16 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
if (channels_from == 1) {
/* single channel input */
- const float *from = rect_from + stride_from * y;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]);
}
else if (channels_from == 3) {
/* RGB input */
- const float *from = rect_from + stride_from * y * 3;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* no color space conversion */
@@ -221,8 +221,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
}
else if (channels_from == 4) {
/* RGBA input */
- const float *from = rect_from + stride_from * y * 4;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
float straight[4];
@@ -334,8 +334,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from,
if (channels_from == 1) {
/* single channel input */
- const float *from = rect_from + stride_from * y;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
if (*mask++ == FILTER_MASK_USED)
@@ -343,8 +343,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from,
}
else if (channels_from == 3) {
/* RGB input */
- const float *from = rect_from + stride_from * y * 3;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from += 3, to += 4) {
if (*mask++ == FILTER_MASK_USED) {
@@ -355,8 +355,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from,
}
else if (channels_from == 4) {
/* RGBA input */
- const float *from = rect_from + stride_from * y * 4;
- uchar *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
float straight[4];
@@ -408,7 +408,7 @@ void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
/* RGBA input */
for (y = 0; y < height; y++) {
const uchar *from = rect_from + stride_from * y * 4;
- float *to = rect_to + stride_to * y * 4;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* no color space conversion */
@@ -460,8 +460,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
if (channels_from == 1) {
/* single channel input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
to[0] = to[1] = to[2] = to[3] = from[0];
@@ -470,8 +470,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
else if (channels_from == 3) {
/* RGB input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 3;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* no color space conversion */
@@ -499,12 +499,12 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
else if (channels_from == 4) {
/* RGBA input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 4;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* same profile, copy */
- memcpy(to, from, sizeof(float) * 4 * width);
+ memcpy(to, from, sizeof(float) * ((size_t)4) * width);
}
else if (profile_to == IB_PROFILE_LINEAR_RGB) {
/* convert to sRGB to linear */
@@ -541,8 +541,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in
if (channels_from == 1) {
/* single channel input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from++, to += 4)
if (*mask++ == FILTER_MASK_USED)
@@ -552,8 +552,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in
else if (channels_from == 3) {
/* RGB input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 3;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 3;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from += 3, to += 4) {
if (*mask++ == FILTER_MASK_USED) {
@@ -566,8 +566,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in
else if (channels_from == 4) {
/* RGBA input */
for (y = 0; y < height; y++) {
- const float *from = rect_from + stride_from * y * 4;
- float *to = rect_to + stride_to * y * 4;
+ const float *from = rect_from + ((size_t)stride_from) * y * 4;
+ float *to = rect_to + ((size_t)stride_to) * y * 4;
for (x = 0; x < width; x++, from += 4, to += 4)
if (*mask++ == FILTER_MASK_USED)
@@ -590,8 +590,8 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
/* always RGBA input */
for (y = 0; y < height; y++) {
- const uchar *from = rect_from + stride_from * y * 4;
- uchar *to = rect_to + stride_to * y * 4;
+ const uchar *from = rect_from + ((size_t)stride_from) * y * 4;
+ uchar *to = rect_to + ((size_t)stride_to) * y * 4;
if (profile_to == profile_from) {
/* same profile, copy */
@@ -690,8 +690,8 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
imb_addrectImBuf(ibuf);
/* do conversion */
- rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
- rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4;
+ rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
+ rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;
if (is_data) {
/* exception for non-color data, just copy float */
@@ -734,9 +734,9 @@ void IMB_float_from_rect(ImBuf *ibuf)
*/
rect_float = ibuf->rect_float;
if (rect_float == NULL) {
- int size;
+ size_t size;
- size = ibuf->x * ibuf->y;
+ size = ((size_t)ibuf->x) * ibuf->y;
size = size * 4 * sizeof(float);
ibuf->channels = 4;
@@ -771,22 +771,22 @@ void IMB_color_to_bw(ImBuf *ibuf)
{
float *rct_fl = ibuf->rect_float;
uchar *rct = (uchar *)ibuf->rect;
- int i;
+ size_t i;
if (rct_fl) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4)
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4)
rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl);
}
if (rct) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4)
+ for (i = ((size_t)ibuf->x * ibuf->y); i > 0; i--, rct += 4)
rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct);
}
}
void IMB_buffer_float_clamp(float *buf, int width, int height)
{
- int i, total = width * height * 4;
+ size_t i, total = ((size_t)width) * height * 4;
for (i = 0; i < total; i++) {
buf[i] = min_ff(1.0, buf[i]);
}
@@ -794,7 +794,7 @@ void IMB_buffer_float_clamp(float *buf, int width, int height)
void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
{
- int total = width * height;
+ size_t total = ((size_t)width) * height;
float *fp = buf;
while (total--) {
premul_to_straight_v4(fp);
@@ -804,7 +804,7 @@ void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
void IMB_buffer_float_premultiply(float *buf, int width, int height)
{
- int total = width * height;
+ size_t total = ((size_t)width) * height;
float *fp = buf;
while (total--) {
straight_to_premul_v4(fp);
@@ -816,14 +816,14 @@ void IMB_buffer_float_premultiply(float *buf, int width, int height)
void IMB_saturation(ImBuf *ibuf, float sat)
{
- int i;
+ size_t i;
unsigned char *rct = (unsigned char *)ibuf->rect;
float *rct_fl = ibuf->rect_float;
float hsv[3];
if (rct) {
float rgb[3];
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) {
rgb_uchar_to_float(rgb, rct);
rgb_to_hsv_v(rgb, hsv);
hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2);
@@ -832,7 +832,7 @@ void IMB_saturation(ImBuf *ibuf, float sat)
}
if (rct_fl) {
- for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) {
+ for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) {
rgb_to_hsv_v(rct_fl, hsv);
hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2);
}
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index 8234b01992b..90219461772 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -343,7 +343,7 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_
void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3])
{
- int a = x * y;
+ size_t a = ((size_t)x) * y;
float *fp = rect_float;
while (a--) {
@@ -366,7 +366,7 @@ void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[
void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3])
{
- int a = x * y;
+ size_t a = ((size_t)x) * y;
unsigned char *cp = rect;
while (a--) {
diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c
index 8cb5070dd62..134bbe88f15 100644
--- a/source/blender/imbuf/intern/metadata.c
+++ b/source/blender/imbuf/intern/metadata.c
@@ -79,6 +79,13 @@ bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, con
return retval;
}
+void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb)
+{
+ if (simb->metadata) {
+ dimb->metadata = IDP_CopyProperty(simb->metadata);
+ }
+}
+
bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value)
{
IDProperty *prop;
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 1262f0af95d..58c5be8b110 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -111,8 +111,8 @@ extern "C"
static struct ExrPass *imb_exr_get_pass(ListBase *lb, char *passname);
static bool exr_has_multiview(MultiPartInputFile& file);
static bool exr_has_multipart_file(MultiPartInputFile& file);
-static int exr_has_alpha(MultiPartInputFile& file);
-static int exr_has_zbuffer(MultiPartInputFile& file);
+static bool exr_has_alpha(MultiPartInputFile& file);
+static bool exr_has_zbuffer(MultiPartInputFile& file);
static void exr_printf(const char *__restrict format, ...);
static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views,
bool *r_singlelayer, bool *r_multilayer, bool *r_multiview);
@@ -368,8 +368,8 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags
ImBuf * (*getbuffer)(void *base, const size_t view_id))
{
const int channels = ibuf->channels;
- const int is_alpha = (channels >= 4) && (ibuf->planes == 32);
- const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
+ const bool is_alpha = (channels >= 4) && (ibuf->planes == 32);
+ const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
const int width = ibuf->x;
const int height = ibuf->y;
const bool is_multiview = (flags & IB_multiview) && ibuf->userdata;
@@ -485,8 +485,8 @@ static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flag
ImBuf * (*getbuffer)(void *base, const size_t view_id))
{
const int channels = ibuf->channels;
- const int is_alpha = (channels >= 4) && (ibuf->planes == 32);
- const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
+ const bool is_alpha = (channels >= 4) && (ibuf->planes == 32);
+ const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
const int width = ibuf->x;
const int height = ibuf->y;
const bool is_multiview = (flags & IB_multiview) && ibuf->userdata;
@@ -1235,9 +1235,15 @@ void IMB_exr_multilayer_convert(void *handle, void *base,
ExrLayer *lay;
ExrPass *pass;
- /* add views to RenderResult */
- for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) {
- addview(base, (*i).c_str());
+ /* RenderResult needs at least one RenderView */
+ if (data->multiView->size() == 0) {
+ addview(base, "");
+ }
+ else {
+ /* add views to RenderResult */
+ for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) {
+ addview(base, (*i).c_str());
+ }
}
if (BLI_listbase_is_empty(&data->layers)) {
@@ -1266,7 +1272,7 @@ void IMB_exr_multiview_convert(void *handle, void *base,
ExrLayer *lay;
ExrPass *pass;
ImBuf *ibuf = NULL;
- const int is_alpha = exr_has_alpha(*file);
+ const bool is_alpha = exr_has_alpha(*file);
Box2i dw = file->header(0).dataWindow();
const size_t width = dw.max.x - dw.min.x + 1;
const size_t height = dw.max.y - dw.min.y + 1;
@@ -1691,12 +1697,12 @@ static bool exr_has_chroma(MultiPartInputFile& file)
file.header(0).channels().findChannel("RY") != NULL;
}
-static int exr_has_zbuffer(MultiPartInputFile& file)
+static bool exr_has_zbuffer(MultiPartInputFile& file)
{
return !(file.header(0).channels().findChannel("Z") == NULL);
}
-static int exr_has_alpha(MultiPartInputFile& file)
+static bool exr_has_alpha(MultiPartInputFile& file)
{
return !(file.header(0).channels().findChannel("A") == NULL);
}
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 4001b681ad9..c7b347cb20c 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -322,30 +322,30 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float);
if (do_char) {
- drect = dbuf->rect + desty * dbuf->x + destx;
- orect = obuf->rect + origy * obuf->x + origx;
+ drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx;
+ orect = obuf->rect + ((size_t)origy) * obuf->x + origx;
}
if (do_float) {
- drectf = dbuf->rect_float + (desty * dbuf->x + destx) * 4;
- orectf = obuf->rect_float + (origy * obuf->x + origx) * 4;
+ drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4;
+ orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4;
}
if (dmaskrect)
- dmaskrect += origy * obuf->x + origx;
+ dmaskrect += ((size_t)origy) * obuf->x + origx;
destskip = dbuf->x;
origskip = obuf->x;
if (sbuf) {
- if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx;
- if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
+ if (do_char) srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx;
+ if (do_float) srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4;
srcskip = sbuf->x;
if (cmaskrect)
- cmaskrect += srcy * sbuf->x + srcx;
+ cmaskrect += ((size_t)srcy) * sbuf->x + srcx;
if (texmaskrect)
- texmaskrect += srcy * sbuf->x + srcx;
+ texmaskrect += ((size_t)srcy) * sbuf->x + srcx;
}
else {
srect = drect;
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 2318553eecc..a608aa0db34 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -283,9 +283,14 @@ static bool thumbpath_from_uri(const char *uri, char *path, const int path_len,
void IMB_thumb_makedirs(void)
{
char tpath[FILE_MAX];
+#if 0 /* UNUSED */
if (get_thumb_dir(tpath, THB_NORMAL)) {
BLI_dir_create_recursive(tpath);
}
+#endif
+ if (get_thumb_dir(tpath, THB_LARGE)) {
+ BLI_dir_create_recursive(tpath);
+ }
if (get_thumb_dir(tpath, THB_FAIL)) {
BLI_dir_create_recursive(tpath);
}
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 205ed7e7380..40c028c3aa1 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -157,6 +157,7 @@ typedef struct Nurb {
short tilt_interp; /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */
short radius_interp;
+ /* only used for dynamically generated Nurbs created from OB_FONT's */
int charidx;
} Nurb;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 0e4a0c77950..725f2e9fb42 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -657,8 +657,10 @@ typedef struct RenderData {
/* render simplify */
int simplify_flag;
short simplify_subsurf;
- short simplify_shadowsamples;
+ short simplify_subsurf_render;
+ short simplify_shadowsamples, pad9;
float simplify_particles;
+ float simplify_particles_render;
float simplify_aosss;
/* cineon */
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 84ac0c5e792..eb76c90c0fc 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -281,6 +281,8 @@ enum {
AREA_FLAG_TEMP_TYPE = (1 << 6),
/* for temporary fullscreens (file browser, image editor render) that are opened above user set fullscreens */
AREA_FLAG_STACKED_FULLSCREEN = (1 << 7),
+ /* update action zones (even if the mouse is not intersecting them) */
+ AREA_FLAG_ACTIONZONES_UPDATE = (1 << 8),
};
#define EDGEWIDTH 1
@@ -372,6 +374,8 @@ enum {
RGN_TYPE_TOOL_PROPS = 6,
RGN_TYPE_PREVIEW = 7
};
+/* use for function args */
+#define RGN_TYPE_ANY -1
/* region alignment */
#define RGN_ALIGN_NONE 0
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 29b78c158fd..d6785da7486 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -534,6 +534,7 @@ typedef enum eSpaceSeq_Flag {
SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */
SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */
SEQ_SHOW_SAFE_CENTER = (1 << 9),
+ SEQ_SHOW_METADATA = (1 << 10),
} eSpaceSeq_Flag;
/* sseq->view */
@@ -590,6 +591,8 @@ typedef struct FileSelectParams {
int active_file;
int sel_first;
int sel_last;
+ unsigned short thumbnail_size;
+ short pad;
/* short */
short type; /* XXXXX for now store type here, should be moved to the operator */
@@ -834,6 +837,7 @@ typedef enum eSpaceImage_Flag {
SI_COLOR_CORRECTION = (1 << 24),
SI_NO_DRAW_TEXPAINT = (1 << 25),
+ SI_DRAW_METADATA = (1 << 26)
} eSpaceImage_Flag;
/* Text Editor ============================================ */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index afa1f03a8ca..e0b51a1b25b 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -338,6 +338,9 @@ typedef struct ThemeSpace {
char paint_curve_pivot[4];
char paint_curve_handle[4];
+
+ char metadatabg[4];
+ char metadatatext[4];
} ThemeSpace;
diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h
index a7921be44d5..6f2e347c84d 100644
--- a/source/blender/makesdna/DNA_view2d_types.h
+++ b/source/blender/makesdna/DNA_view2d_types.h
@@ -43,7 +43,7 @@ typedef struct View2D {
rcti mask; /* mask - region (in screenspace) within which 'cur' can be viewed */
float min[2], max[2]; /* min/max sizes of 'cur' rect (only when keepzoom not set) */
- float minzoom, maxzoom; /* self explanatory. allowable zoom factor range (only when keepzoom set) */
+ float minzoom, maxzoom; /* allowable zoom factor range (only when (keepzoom & V2D_LIMITZOOM)) is set */
short scroll; /* scroll - scrollbars to display (bitflag) */
short scroll_ui; /* scroll_ui - temp settings used for UI drawing of scrollers */
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 66ee1fe4242..a0516590d43 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -379,6 +379,9 @@ enum {
#define RV3D_CAMZOOM_MIN -30
#define RV3D_CAMZOOM_MAX 600
-#endif
+/* #BKE_screen_view3d_zoom_to_fac() values above */
+#define RV3D_CAMZOOM_MIN_FACTOR 0.1657359312880714853f
+#define RV3D_CAMZOOM_MAX_FACTOR 44.9852813742385702928f
+#endif
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 6eb2f2487b0..51ed8bb6c0d 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -390,10 +390,16 @@ enum {
/* wmOperator flag */
enum {
- OP_GRAB_POINTER = (1 << 0),
/* low level flag so exec() operators can tell if they were invoked, use with care.
* typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */
- OP_IS_INVOKE = (1 << 1),
+ OP_IS_INVOKE = (1 << 0),
+
+ /* When the cursor is grabbed */
+ OP_IS_MODAL_GRAB_CURSOR = (1 << 1),
+
+ /* allow modal operators to have the region under the cursor for their context
+ * (the regiontype is maintained to prevent errors) */
+ OP_IS_MODAL_CURSOR_REGION = (1 << 2),
};
#endif /* __DNA_WINDOWMANAGER_TYPES_H__ */
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index 481d139a9de..6140a34b271 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -828,7 +828,8 @@ static void rna_def_sun_lamp(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_shadow_box", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SHOW_SHADOW_BOX);
- RNA_def_property_ui_text(prop, "Show Shadow Box", "Draw box in 3D view to visualize which object are contained in it");
+ RNA_def_property_ui_text(prop, "Show Shadow Box",
+ "Draw a box in 3D view to visualize which objects are contained in it");
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
}
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 59c3befad9e..168f23ceaa1 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -61,6 +61,7 @@
#include "BKE_image.h"
#include "BKE_texture.h"
#include "BKE_scene.h"
+#include "BKE_sound.h"
#include "BKE_text.h"
#include "BKE_action.h"
#include "BKE_group.h"
@@ -87,6 +88,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_speaker_types.h"
+#include "DNA_sound_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"
#include "DNA_group_types.h"
@@ -548,6 +550,25 @@ static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRN
}
}
+static bSound *rna_Main_sounds_load(Main *bmain, const char *name)
+{
+ bSound *sound = BKE_sound_new_file(bmain, name);
+ id_us_min(&sound->id);
+ return sound;
+}
+static void rna_Main_sounds_remove(Main *bmain, ReportList *reports, PointerRNA *sound_ptr)
+{
+ Speaker *sound = sound_ptr->data;
+ if (ID_REAL_USERS(sound) <= 0) {
+ BKE_libblock_free(bmain, sound);
+ RNA_POINTER_INVALIDATE(sound_ptr);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "Sound '%s' must have zero users to be removed, found %d",
+ sound->id.name + 2, ID_REAL_USERS(sound));
+ }
+}
+
static Text *rna_Main_texts_new(Main *bmain, const char *name)
{
return BKE_text_add(bmain, name);
@@ -1585,7 +1606,21 @@ void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_sdna(srna, "Main");
RNA_def_struct_ui_text(srna, "Main Sounds", "Collection of sounds");
- /* TODO, 'load' */
+ /* load func */
+ func = RNA_def_function(srna, "load", "rna_Main_sounds_load");
+ RNA_def_function_ui_description(func, "Add a new sound to the main database from a file");
+ parm = RNA_def_string_file_path(func, "filepath", "Path", FILE_MAX, "", "path for the datablock");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "sound", "Sound", "", "New text datablock");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Main_sounds_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a sound from the current blendfile");
+ parm = RNA_def_pointer(func, "sound", "Sound", "", "Sound to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
func = RNA_def_function(srna, "tag", "rna_Main_sounds_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index b1f0adb0d98..400e98befd0 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -1143,6 +1143,37 @@ static int rna_MeshSkinVertexLayer_data_length(PointerRNA *ptr)
/* End skin vertices */
+/* Paint mask */
+DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_paint_mask, vdata, CD_PAINT_MASK)
+
+static char *rna_MeshPaintMaskLayer_path(PointerRNA *ptr)
+{
+ CustomDataLayer *cdl = ptr->data;
+ char name_esc[sizeof(cdl->name) * 2];
+ BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
+ return BLI_sprintfN("vertex_paint_masks[\"%s\"]", name_esc);
+}
+
+static char *rna_MeshPaintMask_path(PointerRNA *ptr)
+{
+ return rna_VertCustomData_data_path(ptr, "vertex_paint_masks", CD_PAINT_MASK);
+}
+
+static void rna_MeshPaintMaskLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totvert, 0, NULL);
+}
+
+static int rna_MeshPaintMaskLayer_data_length(PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ return me->totvert;
+}
+
+/* End paint mask */
+
static void rna_TexturePoly_image_set(PointerRNA *ptr, PointerRNA value)
{
MTexPoly *tf = (MTexPoly *)ptr->data;
@@ -1783,6 +1814,7 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void)
{
/* unused functions made by macros */
(void)rna_Mesh_skin_vertice_index_range;
+ (void)rna_Mesh_vertex_paint_mask_index_range;
(void)rna_Mesh_tessface_uv_texture_active_set;
(void)rna_Mesh_tessface_uv_texture_clone_get;
(void)rna_Mesh_tessface_uv_texture_clone_index_get;
@@ -3172,6 +3204,36 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
+static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MeshPaintMaskLayer", NULL);
+ RNA_def_struct_ui_text(srna, "Mesh Paint Mask Layer", "Per-vertex paint mask data");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_path_func(srna, "rna_MeshPaintMaskLayer_path");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MeshPaintMaskProperty");
+ RNA_def_property_ui_text(prop, "Data", "");
+
+ RNA_def_property_collection_funcs(prop, "rna_MeshPaintMaskLayer_data_begin", "rna_iterator_array_next",
+ "rna_iterator_array_end", "rna_iterator_array_get",
+ "rna_MeshPaintMaskLayer_data_length", NULL, NULL, NULL);
+
+ srna = RNA_def_struct(brna, "MeshPaintMaskProperty", NULL);
+ RNA_def_struct_sdna(srna, "MFloatProperty");
+ RNA_def_struct_ui_text(srna, "Mesh Paint Mask Property",
+ "Floating point paint mask value");
+ RNA_def_struct_path_func(srna, "rna_MeshPaintMask_path");
+
+ prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "f");
+ RNA_def_property_ui_text(prop, "Value", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+}
+
static void rna_def_mesh(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3376,6 +3438,16 @@ static void rna_def_mesh(BlenderRNA *brna)
rna_def_skin_vertices(brna, prop);
/* End skin vertices */
+ /* Paint mask */
+ prop = RNA_def_property(srna, "vertex_paint_masks", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
+ RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_paint_masks_begin", NULL, NULL, NULL,
+ "rna_Mesh_vertex_paint_masks_length", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MeshPaintMaskLayer");
+ RNA_def_property_ui_text(prop, "Vertex Paint Mask", "Vertex paint mask");
+ rna_def_paint_mask(brna, prop);
+ /* End paint mask */
+
prop = RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH);
RNA_def_property_ui_text(prop, "Auto Smooth",
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index da77b9ee6ea..f1b12963c6a 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -2258,8 +2258,13 @@ static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *
nodeFindNode(ntree, sock, &node, NULL);
}
- if (node)
+ if (node) {
nodeSynchronizeID(node, true);
+
+ /* extra update for sockets that get synced to material */
+ if (node->id && ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT))
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, node->id);
+ }
}
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index f5d50f5dfe1..d3d6e0a6ad5 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1010,7 +1010,7 @@ static int rna_GameObjectSettings_physics_type_get(PointerRNA *ptr)
static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
{
Object *ob = (Object *)ptr->id.data;
- const int was_navmesh = (ob->gameflag & OB_NAVMESH);
+ const int gameflag_prev = ob->gameflag;
ob->body_type = value;
switch (ob->body_type) {
@@ -1068,7 +1068,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
break;
}
- if (was_navmesh != (ob->gameflag & OB_NAVMESH)) {
+ if ((gameflag_prev & OB_NAVMESH) != (ob->gameflag & OB_NAVMESH)) {
if (ob->type == OB_MESH) {
/* this is needed to refresh the derived meshes draw func */
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
@@ -1687,6 +1687,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "physics_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "body_type");
RNA_def_property_enum_items(prop, body_type_items);
+ RNA_def_property_enum_default(prop, OB_BODY_TYPE_STATIC);
RNA_def_property_enum_funcs(prop, "rna_GameObjectSettings_physics_type_get",
"rna_GameObjectSettings_physics_type_set", NULL);
RNA_def_property_ui_text(prop, "Physics Type", "Select the type of physical representation");
@@ -1706,12 +1707,14 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.01, 10000.0);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Mass", "Mass of the object");
prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "inertia");
RNA_def_property_range(prop, 0.01f, FLT_MAX);
RNA_def_property_ui_range(prop, 0.01f, 10.0f, 1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Radius", "Radius of bounding sphere and material physics");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
@@ -1722,11 +1725,13 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "damping");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.04f);
RNA_def_property_ui_text(prop, "Damping", "General movement damping");
prop = RNA_def_property(srna, "rotation_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rdamping");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop, "Rotation Damping", "General rotation damping");
prop = RNA_def_property(srna, "velocity_min", PROP_FLOAT, PROP_NONE);
@@ -1743,16 +1748,19 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "step_height");
RNA_def_property_range(prop, 0.01, 1.0);
+ RNA_def_property_float_default(prop, 0.15f);
RNA_def_property_ui_text(prop, "Step Height", "Maximum height of steps the character can run over");
prop = RNA_def_property(srna, "jump_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "jump_speed");
RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_float_default(prop, 10.0f);
RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping");
prop = RNA_def_property(srna, "fall_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fall_speed");
RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_float_default(prop, 55.0f);
RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall");
/* Collision Masks */
@@ -1813,6 +1821,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "form_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "formfactor");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.4f);
RNA_def_property_ui_text(prop, "Form Factor", "Form factor scales the inertia tensor");
prop = RNA_def_property(srna, "use_anisotropic_friction", PROP_BOOLEAN, PROP_NONE);
@@ -1845,6 +1854,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "margin");
RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_default(prop, 0.04f);
RNA_def_property_ui_text(prop, "Collision Margin",
"Extra margin around object for collision detection, small amount required "
"for stability");
@@ -1860,6 +1870,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "obstacle_radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "obstacleRad");
RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Obstacle Radius", "Radius of object representation in obstacle simulation");
/* state */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 44f2013f2cc..9ea4a40b7ab 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -134,6 +134,7 @@ EnumPropertyItem proportional_falloff_curve_only_items[] = {
{PROP_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", "Smooth falloff"},
{PROP_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", "Spherical falloff"},
{PROP_ROOT, "ROOT", ICON_ROOTCURVE, "Root", "Root falloff"},
+ {PROP_INVSQUARE, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", "Inverse Square falloff"},
{PROP_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", "Sharp falloff"},
{PROP_LIN, "LINEAR", ICON_LINCURVE, "Linear", "Linear falloff"},
{0, NULL, 0, NULL, NULL}
@@ -373,10 +374,8 @@ EnumPropertyItem stereo3d_display_items[] = {
"(anaglyph glasses are required)"},
{S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace",
"Render views for left and right eyes interlaced in a single image (3D-ready monitor is required)"},
-#ifdef DEBUG /* MULTIVIEW_TODO: quadbuffer mode not fully working */
{S3D_DISPLAY_PAGEFLIP, "TIMESEQUENTIAL", 0, "Time Sequential",
"Render alternate eyes (also known as page flip, quad buffer support in the graphic card is required)"},
-#endif
{S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render views for left and right eyes side-by-side"},
{S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render views for left and right eyes one above another"},
{0, NULL, 0, NULL, NULL}
@@ -3493,36 +3492,42 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "cellsize");
RNA_def_property_ui_range(prop, 0.1, 1, 1, 2);
+ RNA_def_property_float_default(prop, 0.3f);
RNA_def_property_ui_text(prop, "Cell Size", "Rasterized cell size");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "cell_height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "cellheight");
RNA_def_property_ui_range(prop, 0.1, 1, 1, 2);
+ RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_ui_text(prop, "Cell Height", "Rasterized cell height");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "agent_height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "agentheight");
RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+ RNA_def_property_float_default(prop, 2.0f);
RNA_def_property_ui_text(prop, "Agent Height", "Minimum height where the agent can still walk");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "agent_radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "agentradius");
RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+ RNA_def_property_float_default(prop, 0.6f);
RNA_def_property_ui_text(prop, "Agent Radius", "Radius of the agent");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "climb_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "agentmaxclimb");
RNA_def_property_ui_range(prop, 0.1, 5, 1, 2);
+ RNA_def_property_float_default(prop, 0.9f);
RNA_def_property_ui_text(prop, "Max Climb", "Maximum height between grid cells the agent can climb");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "slope_max", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "agentmaxslope");
RNA_def_property_range(prop, 0, M_PI_2);
+ RNA_def_property_float_default(prop, M_PI_4);
RNA_def_property_ui_text(prop, "Max Slope", "Maximum walkable slope angle");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3530,42 +3535,49 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "region_min_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "regionminsize");
RNA_def_property_ui_range(prop, 0, 150, 1, 2);
+ RNA_def_property_float_default(prop, 8.0f);
RNA_def_property_ui_text(prop, "Min Region Size", "Minimum regions size (smaller regions will be deleted)");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "region_merge_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "regionmergesize");
RNA_def_property_ui_range(prop, 0, 150, 1, 2);
+ RNA_def_property_float_default(prop, 20.0f);
RNA_def_property_ui_text(prop, "Merged Region Size", "Minimum regions size (smaller regions will be merged)");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "edge_max_len", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "edgemaxlen");
RNA_def_property_ui_range(prop, 0, 50, 1, 2);
+ RNA_def_property_float_default(prop, 12.0f);
RNA_def_property_ui_text(prop, "Max Edge Length", "Maximum contour edge length");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "edge_max_error", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "edgemaxerror");
RNA_def_property_ui_range(prop, 0.1, 3.0, 1, 2);
+ RNA_def_property_float_default(prop, 1.3f);
RNA_def_property_ui_text(prop, "Max Edge Error", "Maximum distance error from contour to cells");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "verts_per_poly", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "vertsperpoly");
RNA_def_property_ui_range(prop, 3, 12, 1, -1);
+ RNA_def_property_int_default(prop, 6);
RNA_def_property_ui_text(prop, "Verts Per Poly", "Max number of vertices per polygon");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "sample_dist", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "detailsampledist");
RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2);
+ RNA_def_property_float_default(prop, 6.0f);
RNA_def_property_ui_text(prop, "Sample Distance", "Detail mesh sample spacing");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "sample_max_error", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "detailsamplemaxerror");
RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Max Sample Error", "Detail mesh simplification max sample error");
RNA_def_property_update(prop, NC_SCENE, NULL);
}
@@ -3777,12 +3789,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "xplay");
RNA_def_property_range(prop, 4, 10000);
+ RNA_def_property_int_default(prop, 640);
RNA_def_property_ui_text(prop, "Resolution X", "Number of horizontal pixels in the screen");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "yplay");
RNA_def_property_range(prop, 4, 10000);
+ RNA_def_property_int_default(prop, 480);
RNA_def_property_ui_text(prop, "Resolution Y", "Number of vertical pixels in the screen");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3799,12 +3813,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "depth");
RNA_def_property_range(prop, 8, 32);
+ RNA_def_property_int_default(prop, 32);
RNA_def_property_ui_text(prop, "Bits", "Display bit depth of full screen display");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "exit_key", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "exitkey");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_enum_default(prop, ESCKEY);
RNA_def_property_enum_funcs(prop, NULL, "rna_GameSettings_exit_key_set", NULL);
RNA_def_property_ui_text(prop, "Exit Key", "The key that exits the Game Engine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3819,6 +3835,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "freqplay");
RNA_def_property_range(prop, 4, 2000);
+ RNA_def_property_int_default(prop, 60);
RNA_def_property_ui_text(prop, "Freq", "Display clock frequency of fullscreen display");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3856,12 +3873,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "stereo_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "stereomode");
RNA_def_property_enum_items(prop, stereo_modes_items);
+ RNA_def_property_enum_default(prop, STEREO_ANAGLYPH);
RNA_def_property_ui_text(prop, "Stereo Mode", "Stereographic techniques");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "stereo_eye_separation", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "eyeseparation");
RNA_def_property_range(prop, 0.01, 5.0);
+ RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop, "Eye Separation",
"Set the distance between the eyes - the camera focal distance/30 should be fine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3876,18 +3895,21 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "dome_tessellation", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dome.res");
RNA_def_property_ui_range(prop, 1, 8, 1, 1);
+ RNA_def_property_int_default(prop, 4);
RNA_def_property_ui_text(prop, "Tessellation", "Tessellation level - check the generated mesh in wireframe mode");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "dome_buffer_resolution", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "dome.resbuf");
RNA_def_property_ui_range(prop, 0.1, 1.0, 0.1, 2);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Buffer Resolution", "Buffer Resolution - decrease it to increase speed");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "dome_angle", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dome.angle");
RNA_def_property_ui_range(prop, 90, 250, 1, 1);
+ RNA_def_property_int_default(prop, 180);
RNA_def_property_ui_text(prop, "Angle", "Field of View of the Dome - it only works in mode Fisheye and Truncated");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3908,6 +3930,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "physics_engine", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "physicsEngine");
RNA_def_property_enum_items(prop, physics_engine_items);
+ RNA_def_property_enum_default(prop, WOPHY_BULLET);
RNA_def_property_ui_text(prop, "Physics Engine", "Physics engine used for physics simulation in the game engine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3915,6 +3938,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "gravity");
RNA_def_property_ui_range(prop, 0.0, 25.0, 1, 2);
RNA_def_property_range(prop, 0.0, 10000.0);
+ RNA_def_property_float_default(prop, 9.8f);
RNA_def_property_ui_text(prop, "Physics Gravity",
"Gravitational constant used for physics simulation in the game engine");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3922,6 +3946,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "occlusion_culling_resolution", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "occlusionRes");
RNA_def_property_range(prop, 128.0, 1024.0);
+ RNA_def_property_int_default(prop, 128);
RNA_def_property_ui_text(prop, "Occlusion Resolution",
"Size of the occlusion buffer, use higher value for better precision (slower)");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3930,6 +3955,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "ticrate");
RNA_def_property_ui_range(prop, 1, 60, 1, 1);
RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_int_default(prop, 60);
RNA_def_property_ui_text(prop, "Frames Per Second",
"Nominal number of game frames per second "
"(physics fixed timestep = 1/fps, independently of actual frame rate)");
@@ -3939,6 +3965,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "maxlogicstep");
RNA_def_property_range(prop, 1, 10000);
RNA_def_property_ui_range(prop, 1, 50, 1, 1);
+ RNA_def_property_int_default(prop, 5);
RNA_def_property_ui_text(prop, "Max Logic Steps",
"Maximum number of logic frame per game frame if graphics slows down the game, "
"higher value allows better synchronization with physics");
@@ -3948,6 +3975,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "maxphystep");
RNA_def_property_range(prop, 1, 10000);
RNA_def_property_ui_range(prop, 1, 50, 1, 1);
+ RNA_def_property_int_default(prop, 5);
RNA_def_property_ui_text(prop, "Max Physics Steps",
"Maximum number of physics step per game frame if graphics slows down the game, "
"higher value allows physics to keep up with realtime");
@@ -3957,6 +3985,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "physubstep");
RNA_def_property_range(prop, 1, 50);
RNA_def_property_ui_range(prop, 1, 5, 1, 1);
+ RNA_def_property_int_default(prop, 1);
RNA_def_property_ui_text(prop, "Physics Sub Steps",
"Number of simulation substep per physic timestep, "
"higher value give better physics precision");
@@ -3966,6 +3995,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "lineardeactthreshold");
RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3);
RNA_def_property_range(prop, 0.001, 10000.0);
+ RNA_def_property_float_default(prop, 0.8f);
RNA_def_property_ui_text(prop, "Deactivation Linear Threshold",
"Linear velocity that an object must be below before the deactivation timer can start");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -3974,6 +4004,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "angulardeactthreshold");
RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3);
RNA_def_property_range(prop, 0.001, 10000.0);
+ RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Deactivation Angular Threshold",
"Angular velocity that an object must be below before the deactivation timer can start");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -4117,6 +4148,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "level_height", PROP_FLOAT, PROP_ACCELERATION);
RNA_def_property_float_sdna(prop, NULL, "levelHeight");
RNA_def_property_range(prop, 0.0f, 200.0f);
+ RNA_def_property_float_default(prop, 2.0f);
RNA_def_property_ui_text(prop, "Level height",
"Max difference in heights of obstacles to enable their interaction");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -4145,6 +4177,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "scehysteresis");
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_range(prop, 0, 100, 10, 1);
+ RNA_def_property_int_default(prop, 10);
RNA_def_property_ui_text(prop, "Hysteresis %",
"Minimum distance change required to transition to the previous level of detail");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -5792,6 +5825,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage");
RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
+ prop = RNA_def_property(srna, "simplify_subdivision_render", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "simplify_subsurf_render");
+ RNA_def_property_ui_range(prop, 0, 6, 1, -1);
+ RNA_def_property_ui_text(prop, "Simplify Subdivision", "Global maximum subdivision level during rendering");
+ RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
+
+ prop = RNA_def_property(srna, "simplify_child_particles_render", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "simplify_particles_render");
+ RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage during rendering");
+ RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
+
prop = RNA_def_property(srna, "simplify_shadow_samples", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "simplify_shadowsamples");
RNA_def_property_ui_range(prop, 1, 16, 1, -1);
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 881688281f3..44169fa641e 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -232,7 +232,8 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor
bSound *sound = BKE_sound_new_file(bmain, file);
- if (sound == NULL || sound->playback_handle == NULL) {
+ if (sound->playback_handle == NULL) {
+ BKE_libblock_free(bmain, sound);
BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file");
return NULL;
}
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index e174d1ce5d0..2b7ed3dc057 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1348,6 +1348,19 @@ static void rna_BackgroundImage_opacity_set(PointerRNA *ptr, float value)
bgpic->blend = 1.0f - value;
}
+/* radius internally (expose as a distance value) */
+static float rna_BackgroundImage_size_get(PointerRNA *ptr)
+{
+ BGpic *bgpic = ptr->data;
+ return bgpic->size * 2.0f;
+}
+
+static void rna_BackgroundImage_size_set(PointerRNA *ptr, float value)
+{
+ BGpic *bgpic = ptr->data;
+ bgpic->size = value * 0.5f;
+}
+
static BGpic *rna_BackgroundImage_new(View3D *v3d)
{
BGpic *bgpic = ED_view3D_background_image_new(v3d);
@@ -1917,6 +1930,11 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_METADATA);
+ RNA_def_property_ui_text(prop, "Draw Metadata", "Draw metadata properties of the image");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+
prop = RNA_def_property(srna, "show_texpaint", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_NO_DRAW_TEXPAINT);
RNA_def_property_ui_text(prop, "Draw Texture Paint UVs", "Draw overlay of texture paint uv layer");
@@ -2103,15 +2121,16 @@ static void rna_def_background_image(BlenderRNA *brna)
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_NONE);
+ prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_ui_text(prop, "Size", "Scaling factor for the background image");
+ RNA_def_property_float_funcs(prop, "rna_BackgroundImage_size_get", "rna_BackgroundImage_size_set", NULL);
+ RNA_def_property_ui_text(prop, "Size", "Size of the background image (ortho view only)");
RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER);
RNA_def_property_float_sdna(prop, NULL, "rotation");
- RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image");
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image (ortho view only)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
@@ -3055,6 +3074,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Center-Cut Safe Areas", "Show safe areas to fit content in a different aspect ratio");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+ prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_METADATA);
+ RNA_def_property_ui_text(prop, "Show Metadata", "Show metadata of first visible strip");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE);
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");
@@ -3679,6 +3703,14 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem thumbnail_size_items[] = {
+ {32, "TINY", 0, "Tiny", ""},
+ {64, "SMALL", 0, "Small", ""},
+ {128, "NORMAL", 0, "Normal", ""},
+ {256, "LARGE", 0, "Large", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "FileSelectParams", NULL);
RNA_def_struct_ui_text(srna, "File Select Parameters", "File Select Parameters");
@@ -3783,6 +3815,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Name Filter", "Filter by name, supports '*' wildcard");
RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+
+ prop = RNA_def_property(srna, "thumbnail_size", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "thumbnail_size");
+ RNA_def_property_enum_items(prop, thumbnail_size_items);
+ RNA_def_property_ui_text(prop, "Thumbnails Size", "Change the size of the thumbnails");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
static void rna_def_filemenu_entry(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index ef52fe2a084..a441f2f57dc 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2386,6 +2386,18 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatabg");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatatext");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Text", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
rna_def_userdef_theme_spaces_paint_curves(srna);
@@ -2488,6 +2500,18 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Preview Background", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatabg");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "metadatatext");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Metadata Text", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_action(BlenderRNA *brna)
@@ -3648,7 +3672,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Grease Pencil Eraser Radius", "Radius of eraser 'brush'");
- prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "gpencil_new_layer_col");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Grease Pencil Default Color", "Color of new Grease Pencil layers");
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index f01e1d02028..3b8ddd011c0 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -414,7 +414,7 @@ static EnumPropertyItem operator_flag_items[] = {
{OPTYPE_UNDO, "UNDO", 0, "Undo", "Push an undo event (needed for operator redo)"},
{OPTYPE_BLOCKING, "BLOCKING", 0, "Blocking", "Block anything else from using the cursor"},
{OPTYPE_MACRO, "MACRO", 0, "Macro", "Use to check if an operator is a macro"},
- {OPTYPE_GRAB_POINTER, "GRAB_POINTER", 0, "Grab Pointer",
+ {OPTYPE_GRAB_CURSOR, "GRAB_CURSOR", 0, "Grab Pointer",
"Use so the operator grabs the mouse focus, enables wrapping when continuous grab "
"is enabled"},
{OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"},
@@ -511,6 +511,11 @@ static int rna_Operator_has_reports_get(PointerRNA *ptr)
return (op->reports && op->reports->list.first);
}
+static PointerRNA rna_Operator_options_get(PointerRNA *ptr)
+{
+ return rna_pointer_inherit_refine(ptr, &RNA_OperatorOptions, ptr->data);
+}
+
static PointerRNA rna_Operator_properties_get(PointerRNA *ptr)
{
wmOperator *op = (wmOperator *)ptr->data;
@@ -1390,6 +1395,33 @@ static void rna_KeyMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
#else /* RNA_RUNTIME */
+/**
+ * expose ``Operator.options`` as its own type so we can control each flags use (some are read-only).
+ */
+static void rna_def_operator_options_runtime(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "OperatorOptions", NULL);
+ RNA_def_struct_ui_text(srna, "Operator Options", "Runtime options");
+ RNA_def_struct_sdna(srna, "wmOperator");
+
+ prop = RNA_def_property(srna, "is_grab_cursor", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_GRAB_CURSOR);
+ RNA_def_property_ui_text(prop, "Grab Cursor", "True when the cursor is grabbed");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "is_invoke", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE);
+ RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "use_cursor_region", PROP_BOOLEAN, PROP_BOOLEAN);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_CURSOR_REGION);
+ RNA_def_property_ui_text(prop, "Focus Region", "Enable to use the region under the cursor for modal execution");
+}
+
static void rna_def_operator(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1424,6 +1456,12 @@ static void rna_def_operator(BlenderRNA *brna)
prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "UILayout");
+ prop = RNA_def_property(srna, "options", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "OperatorOptions");
+ RNA_def_property_pointer_funcs(prop, "rna_Operator_options_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Options", "Runtime options");
+
/* Registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->idname");
@@ -2169,6 +2207,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
void RNA_def_wm(BlenderRNA *brna)
{
rna_def_operator(brna);
+ rna_def_operator_options_runtime(brna);
rna_def_operator_utils(brna);
rna_def_operator_filelist_element(brna);
rna_def_macro_operator(brna);
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index 8a92deec8eb..542c75f3276 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -163,7 +163,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
switch (dmd->mode) {
case MOD_DECIM_MODE_COLLAPSE:
{
- const int do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
+ const bool do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
BM_mesh_decimate_collapse(bm, dmd->percent, vweights, do_triangulate);
break;
}
@@ -174,7 +174,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
case MOD_DECIM_MODE_DISSOLVE:
{
- const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
+ const bool do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit);
break;
}
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 5285bc4124d..73bc61e5519 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -94,7 +94,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
int axis)
{
const float tolerance_sq = mmd->tolerance * mmd->tolerance;
- const int do_vtargetmap = !(mmd->flag & MOD_MIR_NO_MERGE);
+ const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) == 0;
int tot_vtargetmap = 0; /* total merge vertices */
DerivedMesh *result;
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 2c9f5e32440..a9160189a7b 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -138,14 +138,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm = derivedData;
DerivedMesh *result;
ScrewModifierData *ltmd = (ScrewModifierData *) md;
- const int useRenderParams = flag & MOD_APPLY_RENDER;
+ const bool use_render_params = (flag & MOD_APPLY_RENDER) != 0;
int *origindex;
int mpoly_index = 0;
unsigned int step;
unsigned int i, j;
unsigned int i1, i2;
- unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps;
+ unsigned int step_tot = use_render_params ? ltmd->render_steps : ltmd->steps;
const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;
const int quad_ord[4] = {
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index bd16fd07044..50b1404a8e5 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -249,6 +249,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe)
/* Apply face attributes to hull output */
BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) {
+ BM_face_normal_update(f);
if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING)
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
f->mat_nr = so->mat_nr;
@@ -960,6 +961,7 @@ static void add_poly(SkinOutput *so,
BLI_assert(v1 && v2 && v3);
f = BM_face_create_verts(so->bm, verts, v4 ? 4 : 3, NULL, BM_CREATE_NO_DOUBLE, true);
+ BM_face_normal_update(f);
if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING)
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
f->mat_nr = so->mat_nr;
@@ -1421,6 +1423,9 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
if (adj[0]->len == 3 && adj[1]->len == 3) {
BMVert *quad[4];
+ BLI_assert(BM_face_is_normal_valid(adj[0]));
+ BLI_assert(BM_face_is_normal_valid(adj[1]));
+
/* Construct quad using the two triangles adjacent to
* the edge */
quad_from_tris(e, adj, quad);
@@ -1783,6 +1788,9 @@ static BMesh *build_skin(SkinNode *skin_nodes,
skin_output_connections(&so, skin_nodes, medge, totedge);
hull_merge_triangles(&so, smd);
+ bmesh_edit_end(so.bm, 0);
+ BMO_pop(so.bm);
+
return so.bm;
}
@@ -1844,7 +1852,6 @@ static DerivedMesh *base_skin(DerivedMesh *origdm,
result = CDDM_from_bmesh(bm, false);
BM_mesh_free(bm);
- CDDM_calc_edges(result);
result->dirty |= DM_DIRTY_NORMALS;
skin_set_orig_indices(result);
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 08b8854c728..c96080d8cf9 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -255,7 +255,7 @@ static DerivedMesh *applyModifier(
/* weights */
MDeformVert *dvert;
- const int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0);
+ const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0;
int defgrp_index;
/* array size is doubled in case of using a shell */
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index f17858264f8..7ada058d883 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -88,7 +88,7 @@ static bool isDisabled(ModifierData *md, int useRenderParams)
SubsurfModifierData *smd = (SubsurfModifierData *) md;
int levels = (useRenderParams) ? smd->renderLevels : smd->levels;
- return get_render_subsurf_level(&md->scene->r, levels) == 0;
+ return get_render_subsurf_level(&md->scene->r, levels, useRenderParams != 0) == 0;
}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index a10386a6f41..113f1654d02 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -139,7 +139,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
Image *image = umd->image;
MPoly *mpoly, *mp;
MLoop *mloop;
- int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
+ const bool override_image = (umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0;
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
int num_projectors = 0;
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 4433922f9bb..266cfcc59a6 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -234,7 +234,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
int i;
/* Flags. */
#if 0
- int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
+ const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
#endif
/* Get number of verts. */
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 057674f1144..390475b57f5 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -366,7 +366,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
int i;
/* Flags. */
#if 0
- int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
+ const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
#endif
#ifdef USE_TIMEIT
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index 8e279cf6d68..bbfb07a316d 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -43,7 +43,7 @@ void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node)
for (sock = node->outputs.first; sock; sock = sock->next) {
if (sock->cache) {
//free_compbuf(sock->cache);
- //sock->cache= NULL;
+ //sock->cache = NULL;
}
}
node->need_exec = 1;
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 23d47065f59..19e93447608 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -190,7 +190,7 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node,
sockdata->pass_index = index;
sockdata->pass_flag = rpass->passtype;
- if (STREQ(rpass->chan_id, "RGBA")) {
+ 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;
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 93ce469c150..3482227f044 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -337,7 +337,7 @@ int ntreeTexExecTree(
data.osatex = osatex;
data.target = texres;
data.do_preview = preview;
- data.do_manage = (shi) ? shi->do_manage : 0;
+ data.do_manage = (shi) ? shi->do_manage : true;
data.thread = thread;
data.which_output = which_output;
data.cfra = cfra;
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index bc14e1ac3a6..f74737ba8f4 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -108,7 +108,7 @@ PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
" :type mesh: :class:`bpy.types.Mesh`\n"
" :arg tessface: Option to recalculate n-gon tessellation.\n"
" :type tessface: boolean\n"
-" :arg destructive: Use when grometry has been added or removed.\n"
+" :arg destructive: Use when geometry has been added or removed.\n"
" :type destructive: boolean\n"
);
static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 84c1031a24a..a4c057acac2 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -69,9 +69,10 @@ static int bpy_bm_op_as_py_error(BMesh *bm)
* \param htype Test \a value matches this type.
* \param descr Description text.
*/
-static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char htype,
- /* for error messages */
- const char *opname, const char *slot_name, const char *descr)
+static int bpy_slot_from_py_elem_check(
+ BPy_BMElem *value, BMesh *bm, const char htype,
+ /* for error messages */
+ const char *opname, const char *slot_name, const char *descr)
{
if (!BPy_BMElem_Check(value) ||
!(value->ele->head.htype & htype))
@@ -107,10 +108,11 @@ static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char
* \param htype_bmo The type(s) supported by the target slot.
* \param descr Description text.
*/
-static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm,
- const char htype_py, const char htype_bmo,
- /* for error messages */
- const char *opname, const char *slot_name, const char *descr)
+static int bpy_slot_from_py_elemseq_check(
+ BPy_BMGeneric *value, BMesh *bm,
+ const char htype_py, const char htype_bmo,
+ /* for error messages */
+ const char *opname, const char *slot_name, const char *descr)
{
if (value->bm == NULL) {
PyErr_Format(PyExc_TypeError,
@@ -142,9 +144,10 @@ static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm,
/**
* Use for giving py args to an operator.
*/
-static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value,
- /* the are just for exception messages */
- const char *opname, const char *slot_name)
+static int bpy_slot_from_py(
+ BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value,
+ /* the are just for exception messages */
+ const char *opname, const char *slot_name)
{
switch (slot->slot_type) {
case BMO_OP_SLOT_BOOL:
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 0edca96404f..14fdada66bb 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -3757,10 +3757,11 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
*
* The 'bm_r' value is assigned when empty, and used when set.
*/
-void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
- const char htype,
- const bool do_unique_check, const bool do_bm_check,
- const char *error_prefix)
+void *BPy_BMElem_PySeq_As_Array(
+ BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
+ const char htype,
+ const bool do_unique_check, const bool do_bm_check,
+ const char *error_prefix)
{
BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
PyObject *seq_fast;
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index 66059a642d1..630afcb32c0 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -158,10 +158,11 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm);
PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */
-void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
- const char htype,
- const bool do_unique_check, const bool do_bm_check,
- const char *error_prefix);
+void *BPy_BMElem_PySeq_As_Array(
+ BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
+ const char htype,
+ const bool do_unique_check, const bool do_bm_check,
+ const char *error_prefix);
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len);
PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len);
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index 7b6e062896f..3adf37f78f0 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -116,6 +116,9 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__color_doc,
PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc,
"Accessor for skin layer.\n\ntype: :class:`BMLayerCollection`"
);
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc,
+"Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`"
+);
#ifdef WITH_FREESTYLE
PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_edge_doc,
"Accessor for Freestyle edge layer.\n\ntype: :class:`BMLayerCollection`"
@@ -196,6 +199,7 @@ static PyGetSetDef bpy_bmlayeraccess_vert_getseters[] = {
{(char *)"shape", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__shape_doc, (void *)CD_SHAPEKEY},
{(char *)"bevel_weight", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__bevel_weight_doc, (void *)CD_BWEIGHT},
{(char *)"skin", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__skin_doc, (void *)CD_MVERT_SKIN},
+ {(char *)"paint_mask", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__paint_mask_doc, (void *)CD_PAINT_MASK},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -984,6 +988,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
break;
}
case CD_PROP_FLT:
+ case CD_PAINT_MASK:
{
ret = PyFloat_FromDouble(*(float *)value);
break;
@@ -1061,6 +1066,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
break;
}
case CD_PROP_FLT:
+ case CD_PAINT_MASK:
{
float tmp_val = PyFloat_AsDouble(py_value);
if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c
index 0dd6ee7d51a..b7890926a85 100644
--- a/source/blender/python/bmesh/bmesh_py_utils.c
+++ b/source/blender/python/bmesh/bmesh_py_utils.c
@@ -253,7 +253,7 @@ static PyObject *bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args
}
/* should always succeed */
- ok = BM_vert_splice(bm, py_vert->v, py_vert_target->v);
+ ok = BM_vert_splice(bm, py_vert_target->v, py_vert->v);
BLI_assert(ok == true);
UNUSED_VARS_NDEBUG(ok);
@@ -307,7 +307,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar
return NULL;
}
- BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len);
+ BM_vert_separate(bm, py_vert->v, edge_array, edge_array_len, false, &elem, &elem_len);
/* return collected verts */
ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len);
MEM_freeN(elem);
@@ -670,7 +670,7 @@ PyDoc_STRVAR(bpy_bm_utils_face_vert_separate_doc,
" :type face: :class:`bmesh.types.BMFace`\n"
" :arg vert: A vertex in the face to separate.\n"
" :type vert: :class:`bmesh.types.BMVert`\n"
-" :return vert: The newly created vertex or None of failure.\n"
+" :return vert: The newly created vertex or None on failure.\n"
" :rtype vert: :class:`bmesh.types.BMVert`\n"
"\n"
" .. note::\n"
@@ -749,9 +749,9 @@ PyDoc_STRVAR(bpy_bm_utils_loop_separate_doc,
"\n"
" Rip a vertex in a face away and add a new vertex.\n"
"\n"
-" :arg loop: The to separate.\n"
-" :type loop: :class:`bmesh.types.BMFace`\n"
-" :return vert: The newly created vertex or None of failure.\n"
+" :arg loop: The loop to separate.\n"
+" :type loop: :class:`bmesh.types.BMLoop`\n"
+" :return vert: The newly created vertex or None on failure.\n"
" :rtype vert: :class:`bmesh.types.BMVert`\n"
);
static PyObject *bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value)
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index c8a4971847b..04ab34efeb4 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -287,6 +287,7 @@ static PyGetSetDef bpy_app_getsets[] = {
{(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM},
{(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH},
{(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA},
+ {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM},
{(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL},
{(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 8370aea4c99..0e9e6b74396 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -2965,9 +2965,10 @@ static struct PyMethodDef props_methods[] = {
static struct PyModuleDef props_module = {
PyModuleDef_HEAD_INIT,
"bpy.props",
- "This module defines properties to extend blenders internal data, the result of these functions"
- " is used to assign properties to classes registered with blender and can't be used directly.\n"
- ".. warning:: All parameters to these functions must be passed as keywords.",
+ "This module defines properties to extend Blender's internal data. The result of these functions"
+ " is used to assign properties to classes registered with Blender and can't be used directly.\n"
+ "\n"
+ ".. warning:: All parameters to these functions must be passed as keywords.\n",
-1, /* multiple "initialization" just copies the module dict. */
props_methods,
NULL, NULL, NULL, NULL
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index bb4080decef..ae5c058406f 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -850,7 +850,7 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
"\n"
" Takes 5 vectors (using only the x and y coordinates): one is the point and the next 4 define the quad, \n"
" only the x and y are used from the vectors. Returns 1 if the point is within the quad, otherwise 0.\n"
-" Works only with convex quads without singular edges."
+" Works only with convex quads without singular edges.\n"
"\n"
" :arg pt: Point\n"
" :type pt: :class:`mathutils.Vector`\n"
diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h
index e8a8986714d..0750ea1aa28 100644
--- a/source/blender/render/extern/include/RE_bake.h
+++ b/source/blender/render/extern/include/RE_bake.h
@@ -61,10 +61,10 @@ typedef struct BakeHighPolyData {
struct ModifierData *tri_mod;
struct Mesh *me;
char restrict_flag;
+ bool is_flip_object;
float obmat[4][4];
float imat[4][4];
- float rotmat[4][4];
} BakeHighPolyData;
/* external_engine.c */
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 20678b29d0e..2df4cde2b27 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -49,6 +49,7 @@ struct Scene;
struct SceneRenderLayer;
struct EnvMap;
struct RenderResult;
+struct StampData;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* this include is what is exposed of render to outside world */
@@ -137,6 +138,9 @@ typedef struct RenderResult {
int rectx, recty;
short crop, sample_nr;
+ /* the following rect32, rectf and rectz buffers are for temporary storage only, for RenderResult structs
+ * created in #RE_AcquireResultImage - which do not have RenderView */
+
/* optional, 32 bits version of picture, used for ogl render and image curves */
int *rect32;
/* if this exists, a copy of one of layers, or result of composited layers */
@@ -171,6 +175,8 @@ typedef struct RenderResult {
/* render info text */
char *text;
char *error;
+
+ struct StampData *stamp_data;
} RenderResult;
@@ -261,7 +267,7 @@ void RE_init_threadcount(Render *re);
/* the main processor, assumes all was set OK! */
void RE_TileProcessor(struct Render *re);
-bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct Object *camera, const bool stamp, char *name);
+bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, const bool stamp, char *name);
bool RE_WriteRenderViewsMovie(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct RenderData *rd,
struct bMovieHandle *mh, const size_t width, const size_t height, void **movie_ctx_arr,
const size_t totvideos, bool preview);
@@ -350,12 +356,8 @@ bool RE_allow_render_generic_object(struct Object *ob);
bool RE_HasFakeLayer(RenderResult *res);
bool RE_RenderResult_is_stereo(RenderResult *res);
-
-float *RE_RenderViewGetRectf(struct RenderResult *rr, const int view_id);
-float *RE_RenderViewGetRectz(struct RenderResult *rr, const int view_id);
-int *RE_RenderViewGetRect32(struct RenderResult *rr, const int view_id);
-void RE_RenderViewSetRectf(struct RenderResult *res, const int view_id, float *rect);
-void RE_RenderViewSetRectz(struct RenderResult *res, const int view_id, float *rect);
+struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id);
+struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname);
#endif /* __RE_PIPELINE_H__ */
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index e7a2cbf99cd..f031be9e9c9 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -60,6 +60,7 @@ struct RenderResult *render_result_new_full_sample(struct Render *re,
struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty);
+void render_result_view_new(struct RenderResult *rr, const char *viewname);
void render_result_views_new(struct RenderResult *rr, struct RenderData *rd);
/* Merge */
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 1f7555bc5c5..bc5db5b9862 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -300,7 +300,7 @@ static bool cast_ray_highpoly(
mul_v3_m4v3(co_high, highpoly[i].imat, co);
/* rotates */
- mul_v3_m4v3(dir_high, highpoly[i].rotmat, dir);
+ mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir);
normalize_v3(dir_high);
/* cast ray */
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index d36ab46d145..87c886929d6 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1209,8 +1209,7 @@ static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re
sd->time = 0.0f;
sd->size = hasize;
- copy_v3_v3(vel, state->vel);
- mul_mat3_m4_v3(re->viewmat, vel);
+ mul_v3_mat3_m4v3(vel, re->viewmat, state->vel);
normalize_v3(vel);
if (part->draw & PART_DRAW_VEL_LENGTH)
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 6ba85ea5329..de57d4e7ba6 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -127,9 +127,13 @@ typedef struct {
static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index)
{
- unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2,
- data->mface[face_num].v3, data->mface[face_num].v4};
- const int smoothnormal = (data->mface[face_num].flag & ME_SMOOTH);
+ const unsigned int indices[] = {
+ data->mface[face_num].v1,
+ data->mface[face_num].v2,
+ data->mface[face_num].v3,
+ data->mface[face_num].v4,
+ };
+ const bool smoothnormal = (data->mface[face_num].flag & ME_SMOOTH) != 0;
if (!smoothnormal) { /* flat */
if (data->precomputed_normals) {
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index e9b0a2bcbf4..a4089002ba5 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -363,6 +363,7 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
rr->layers = re->result->layers;
rr->xof = re->disprect.xmin;
rr->yof = re->disprect.ymin;
+ rr->stamp_data = re->result->stamp_data;
}
}
}
@@ -379,6 +380,8 @@ void RE_ReleaseResultImageViews(Render *re, RenderResult *rr)
}
/* fill provided result struct with what's currently active or done */
+/* this RenderResult struct is the only exception to the rule of a RenderResult */
+/* always having at least one RenderView */
void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
{
memset(rr, 0, sizeof(RenderResult));
@@ -394,18 +397,16 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
rr->recty = re->result->recty;
/* actview view */
- rv = BLI_findlink(&re->result->views, view_id);
- if (rv == NULL)
- rv = (RenderView *)re->result->views.first;
+ rv = RE_RenderViewGetById(re->result, view_id);
- rr->rectf = rv ? rv->rectf : NULL;
- rr->rectz = rv ? rv->rectz : NULL;
- rr->rect32 = rv ? rv->rect32 : NULL;
+ rr->rectf = rv->rectf;
+ rr->rectz = rv->rectz;
+ rr->rect32 = rv->rect32;
/* active layer */
rl = render_get_active_layer(re, re->result);
- if (rl && rv) {
+ if (rl) {
if (rv->rectf == NULL)
rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name);
@@ -413,7 +414,7 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name);
}
- rr->have_combined = rv ? (rv->rectf != NULL) : false;
+ rr->have_combined = (rv->rectf != NULL);
rr->layers = re->result->layers;
rr->views = re->result->views;
@@ -435,9 +436,9 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
RenderResult rres;
const size_t view_id = BKE_scene_multiview_view_id_get(&re->r, re->viewname);
- RE_AcquireResultImage(re, &rres, view_id);
- render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, 0);
- RE_ReleaseResultImage(re);
+ RE_AcquireResultImageViews(re, &rres);
+ render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id);
+ RE_ReleaseResultImageViews(re, &rres);
}
/* caller is responsible for allocating rect in correct size! */
@@ -746,6 +747,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->result = MEM_callocN(sizeof(RenderResult), "new render result");
re->result->rectx = re->rectx;
re->result->recty = re->recty;
+ render_result_view_new(re->result, "new temporary view");
}
if (re->r.scemode & R_VIEWPORT_PREVIEW)
@@ -768,11 +770,14 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
static void render_result_rescale(Render *re)
{
RenderResult *result = re->result;
+ RenderView *rv;
int x, y;
float scale_x, scale_y;
float *src_rectf;
- src_rectf = result->rectf;
+ rv = RE_RenderViewGetById(result, 0);
+ src_rectf = rv->rectf;
+
if (src_rectf == NULL) {
RenderLayer *rl = render_get_active_layer(re, re->result);
if (rl != NULL) {
@@ -790,7 +795,7 @@ static void render_result_rescale(Render *re)
"");
if (re->result != NULL) {
- dst_rectf = re->result->rectf;
+ dst_rectf = RE_RenderViewGetById(re->result, 0)->rectf;
if (dst_rectf == NULL) {
RenderLayer *rl;
rl = render_get_active_layer(re, re->result);
@@ -2232,7 +2237,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
}
}
- for (nr = 0, rv = re->result->views.first; rv; rv = rv->next, nr++) {
+ for (nr = 0, rv = rectfs->first; rv; rv = rv->next, nr++) {
rectf = rv->rectf;
/* ensure we get either composited result or the active layer */
@@ -2285,7 +2290,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
/* store the final result */
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
- rv = BLI_findlink(&re->result->views, nr);
+ rv = RE_RenderViewGetById(re->result, nr);
if (rv->rectf)
MEM_freeN(rv->rectf);
rv->rectf = rectf;
@@ -2483,7 +2488,7 @@ static void renderresult_stampinfo(Render *re)
for (rv = re->result->views.first;rv;rv = rv->next, nr++) {
RE_SetActiveRenderView(re, rv->name);
RE_AcquireResultImage(re, &rres, nr);
- BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rv->rect32, rv->rectf, rres.rectx, rres.recty, 4);
+ BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4);
RE_ReleaseResultImage(re);
}
}
@@ -2569,7 +2574,7 @@ static void do_render_seq(Render *re)
BLI_rw_mutex_unlock(&re->resultmutex);
for (view_id = 0; view_id < tot_views; view_id++) {
- RenderView *rv = BLI_findlink(&rr->views, view_id);
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
if (ibuf_arr[view_id]) {
@@ -2614,6 +2619,8 @@ static void do_render_seq(Render *re)
/* main loop: doing sequence + fields + blur + 3d render + compositing */
static void do_render_all_options(Render *re)
{
+ Object *camera;
+
re->current_scene_update(re->suh, re->scene);
BKE_scene_camera_switch_update(re->scene);
@@ -2647,6 +2654,10 @@ static void do_render_all_options(Render *re)
re->stats_draw(re->sdh, &re->i);
+ /* save render result stamp if needed */
+ camera = RE_GetCamera(re);
+ BKE_render_result_stamp_info(re->scene, camera, re->result);
+
/* stamp image info here */
if ((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) {
renderresult_stampinfo(re);
@@ -3082,7 +3093,7 @@ void RE_RenderFreestyleExternal(Render *re)
}
#endif
-bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, struct Object *camera, const bool stamp, char *name)
+bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
{
bool is_mono;
bool ok = true;
@@ -3125,8 +3136,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
if (stamp) {
/* writes the name of the individual cameras */
- Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name);
- ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format);
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format);
}
else {
ok = BKE_imbuf_write(ibuf, name, &rd->im_format);
@@ -3152,8 +3162,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
if (stamp) {
/* writes the name of the individual cameras */
- Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name);
- ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format);
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format);
}
else {
ok = BKE_imbuf_write(ibuf, name, &rd->im_format);
@@ -3188,7 +3197,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]);
if (stamp)
- ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format);
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format);
else
ok = BKE_imbuf_write(ibuf_arr[2], name, &rd->im_format);
@@ -3214,7 +3223,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen
&scene->display_settings, &imf);
if (stamp)
- ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format);
+ ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format);
else
ok = BKE_imbuf_write(ibuf_arr[2], name, &imf);
@@ -3324,7 +3333,6 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
RenderResult rres;
double render_time;
bool ok = true;
- Object *camera = RE_GetCamera(re);
RE_AcquireResultImageViews(re, &rres);
@@ -3341,7 +3349,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
&scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
/* write images as individual images or stereo */
- ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, camera, true, name);
+ ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, true, name);
}
RE_ReleaseResultImageViews(re, &rres);
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 303494d2beb..019484f7ed2 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -115,7 +115,9 @@ void render_result_free(RenderResult *res)
MEM_freeN(res->text);
if (res->error)
MEM_freeN(res->error);
-
+ if (res->stamp_data)
+ MEM_freeN(res->stamp_data);
+
MEM_freeN(res);
}
@@ -484,7 +486,7 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int
const size_t 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);
- int rectsize = rr->rectx * rr->recty * channels;
+ size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
BLI_addtail(&rl->passes, rpass);
rpass->passtype = passtype;
@@ -909,10 +911,16 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace
return rr;
}
+void render_result_view_new(RenderResult *rr, const char *viewname)
+{
+ RenderView *rv = MEM_callocN(sizeof(RenderView), "new render view");
+ BLI_addtail(&rr->views, rv);
+ BLI_strncpy(rv->name, viewname, sizeof(rv->name));
+}
+
void render_result_views_new(RenderResult *rr, RenderData *rd)
{
SceneRenderView *srv;
- RenderView *rv;
/* clear previously existing views - for sequencer */
render_result_views_free(rr);
@@ -920,19 +928,15 @@ void render_result_views_new(RenderResult *rr, RenderData *rd)
/* check renderdata for amount of views */
if ((rd->scemode & R_MULTIVIEW)) {
for (srv = rd->views.first; srv; srv = srv->next) {
- if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) continue;
-
- rv = MEM_callocN(sizeof(RenderView), "new render view");
- BLI_addtail(&rr->views, rv);
-
- BLI_strncpy(rv->name, srv->name, sizeof(rv->name));
+ if (BKE_scene_multiview_is_render_view_active(rd, srv) == false)
+ continue;
+ render_result_view_new(rr, srv->name);
}
}
/* we always need at least one view */
if (BLI_listbase_count_ex(&rr->views, 1) == 0) {
- rv = MEM_callocN(sizeof(RenderView), "new render view");
- BLI_addtail(&rr->views, rv);
+ render_result_view_new(rr, "");
}
}
@@ -940,22 +944,23 @@ void render_result_views_new(RenderResult *rr, RenderData *rd)
static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
{
- int y, ofs, copylen, tilex, tiley;
+ int y, tilex, tiley;
+ size_t ofs, copylen;
copylen = tilex = rrpart->rectx;
tiley = rrpart->recty;
if (rrpart->crop) { /* filters add pixel extra */
- tile += pixsize * (rrpart->crop + rrpart->crop * tilex);
+ tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex);
copylen = tilex - 2 * rrpart->crop;
tiley -= 2 * rrpart->crop;
- ofs = (rrpart->tilerect.ymin + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
+ ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
target += pixsize * ofs;
}
else {
- ofs = (rrpart->tilerect.ymin * rr->rectx + rrpart->tilerect.xmin);
+ ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
target += pixsize * ofs;
}
@@ -1461,12 +1466,13 @@ bool render_result_exr_file_cache_read(Render *re)
ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id)
{
ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
-
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
/* if not exists, BKE_imbuf_write makes one */
- ibuf->rect = (unsigned int *) RE_RenderViewGetRect32(rr, view_id);
- ibuf->rect_float = RE_RenderViewGetRectf(rr, view_id);
- ibuf->zbuf_float = RE_RenderViewGetRectz(rr, view_id);
-
+ ibuf->rect = (unsigned int *) rv->rect32;
+ ibuf->rect_float = rv->rectf;
+ ibuf->zbuf_float = rv->rectz;
+
/* float factor for random dither, imbuf takes care of it */
ibuf->dither = rd->dither_intensity;
@@ -1503,7 +1509,7 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int vi
void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id)
{
- RenderView *rv = BLI_findlink(&rr->views, view_id);
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
if (ibuf->rect_float) {
if (!rv->rectf)
@@ -1524,15 +1530,11 @@ void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBu
/* Same things as above, old rectf can hang around from previous render. */
MEM_SAFE_FREE(rv->rectf);
}
-
- /* clean up non-view buffers */
- MEM_SAFE_FREE(rr->rect32);
- MEM_SAFE_FREE(rr->rectf);
}
void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
{
- RenderView *rv = BLI_findlink(&rr->views, view_id);
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
if (rv->rectf)
memset(rv->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty);
@@ -1546,15 +1548,13 @@ void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rec
const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings,
const int view_id)
{
- if (rr->rect32) {
- int *rect32 = RE_RenderViewGetRect32(rr, view_id);
- memcpy(rect, (rect32 ? rect32 : rr->rect32), sizeof(int) * rr->rectx * rr->recty);
- }
- else if (rr->rectf) {
- float *rectf = RE_RenderViewGetRectf(rr, view_id);
- IMB_display_buffer_transform_apply((unsigned char *) rect, (rectf ? rectf : rr->rectf), rr->rectx, rr->recty, 4,
+ RenderView *rv = RE_RenderViewGetById(rr, view_id);
+
+ if (rv->rect32)
+ memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty);
+ else if (rv->rectf)
+ IMB_display_buffer_transform_apply((unsigned char *) rect, rv->rectf, rr->rectx, rr->recty, 4,
view_settings, display_settings, true);
- }
else
/* else fill with black */
memset(rect, 0, sizeof(int) * rectx * recty);
@@ -1588,47 +1588,16 @@ bool RE_RenderResult_is_stereo(RenderResult *res)
return true;
}
-void RE_RenderViewSetRectf(RenderResult *res, const int view_id, float *rect)
-{
- RenderView *rv = BLI_findlink(&res->views, view_id);
- if (rv) {
- rv->rectf = rect;
- }
-}
-
-void RE_RenderViewSetRectz(RenderResult *res, const int view_id, float *rect)
+RenderView *RE_RenderViewGetById(RenderResult *res, const int view_id)
{
RenderView *rv = BLI_findlink(&res->views, view_id);
- if (rv) {
- rv->rectz = rect;
- }
+ BLI_assert(res->views.first);
+ return rv ? rv : res->views.first;
}
-float *RE_RenderViewGetRectz(RenderResult *res, const int view_id)
+RenderView *RE_RenderViewGetByName(RenderResult *res, const char *viewname)
{
- RenderView *rv = BLI_findlink(&res->views, view_id);
- if (rv) {
- return rv->rectz;
- }
- return res->rectz;
+ RenderView *rv = BLI_findstring(&res->views, viewname, offsetof(RenderView, name));
+ BLI_assert(res->views.first);
+ return rv ? rv : res->views.first;
}
-
-float *RE_RenderViewGetRectf(RenderResult *res, const int view_id)
-{
- RenderView *rv = BLI_findlink(&res->views, view_id);
- if (rv) {
- return rv->rectf;
- }
- return res->rectf;
-}
-
-int *RE_RenderViewGetRect32(RenderResult *res, const int view_id)
-{
- RenderView *rv = BLI_findlink(&res->views, view_id);
- if (rv) {
- return rv->rect32;
- }
- return res->rect32;
-}
-
-
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 9ea7cb62c58..5a5e67e1e43 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -423,14 +423,11 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
}
if (texco & TEXCO_GLOB) {
- copy_v3_v3(shi->gl, shi->co);
- mul_m4_v3(R.viewinv, shi->gl);
+ mul_v3_m4v3(shi->gl, R.viewinv, shi->co);
if (shi->osatex) {
- copy_v3_v3(shi->dxgl, shi->dxco);
- mul_mat3_m4_v3(R.viewinv, shi->dxgl);
- copy_v3_v3(shi->dygl, shi->dyco);
- mul_mat3_m4_v3(R.viewinv, shi->dygl);
+ mul_v3_mat3_m4v3(shi->dxgl, R.viewinv, shi->dxco);
+ mul_v3_mat3_m4v3(shi->dygl, R.viewinv, shi->dyco);
}
}
diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c
index 5261374b34d..a932123243d 100644
--- a/source/blender/render/intern/source/texture_ocean.c
+++ b/source/blender/render/intern/source/texture_ocean.c
@@ -73,7 +73,7 @@ int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres)
return 0;
}
else {
- const int do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
+ const bool do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS) != 0;
int cfra = R.r.cfra;
int retval = TEX_INT;
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index dbeea80ba82..d4148a56dd2 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -175,6 +175,7 @@ bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference);
void WM_main_add_notifier(unsigned int type, void *reference);
void WM_main_remove_notifier_reference(const void *reference);
+void WM_main_remove_editor_id_reference(const struct ID *id);
/* reports */
void WM_report(const struct bContext *C, ReportType type, const char *message);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 165ed6df091..c9a0849c192 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -123,17 +123,22 @@ struct ImBuf;
/* ************** wmOperatorType ************************ */
/* flag */
-#define OPTYPE_REGISTER 1 /* register operators in stack after finishing */
-#define OPTYPE_UNDO 2 /* do undo push after after */
-#define OPTYPE_BLOCKING 4 /* let blender grab all input from the WM (X11) */
-#define OPTYPE_MACRO 8
-#define OPTYPE_GRAB_POINTER 16 /* grabs the cursor and optionally enables continuous cursor wrapping */
-#define OPTYPE_PRESET 32 /* show preset menu */
-#define OPTYPE_INTERNAL 64 /* some operators are mainly for internal use
- * and don't make sense to be accessed from the
- * search menu, even if poll() returns true.
- * currently only used for the search toolbox */
-#define OPTYPE_LOCK_BYPASS 128 /* Allow operator to run when interface is locked */
+enum {
+ OPTYPE_REGISTER = (1 << 0), /* register operators in stack after finishing */
+ OPTYPE_UNDO = (1 << 1), /* do undo push after after */
+ OPTYPE_BLOCKING = (1 << 2), /* let blender grab all input from the WM (X11) */
+ OPTYPE_MACRO = (1 << 3),
+ OPTYPE_GRAB_CURSOR = (1 << 4), /* grabs the cursor and optionally enables continuous cursor wrapping */
+ OPTYPE_PRESET = (1 << 5), /* show preset menu */
+
+ /* some operators are mainly for internal use
+ * and don't make sense to be accessed from the
+ * search menu, even if poll() returns true.
+ * currently only used for the search toolbox */
+ OPTYPE_INTERNAL = (1 << 6),
+
+ OPTYPE_LOCK_BYPASS = (1 << 7), /* Allow operator to run when interface is locked */
+};
/* context to call operator in for WM_operator_name_call */
/* rna_ui.c contains EnumPropertyItem's of these, keep in sync */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 2280782f7bd..69bee8bab80 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -63,6 +63,7 @@
#include "ED_fileselect.h"
#include "ED_info.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
@@ -217,6 +218,7 @@ void WM_main_remove_notifier_reference(const void *reference)
{
Main *bmain = G.main;
wmWindowManager *wm = bmain->wm.first;
+
if (wm) {
wmNotifier *note, *note_next;
@@ -232,6 +234,24 @@ void WM_main_remove_notifier_reference(const void *reference)
}
}
+void WM_main_remove_editor_id_reference(const ID *id)
+{
+ Main *bmain = G.main;
+ bScreen *sc;
+
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ ED_spacedata_id_unref(sl, id);
+ }
+ }
+ }
+}
+
static void wm_notifier_clear(wmNotifier *note)
{
/* NULL the entire notifier, only leaving (next, prev) members intact */
@@ -293,7 +313,7 @@ void wm_event_do_notifiers(bContext *C)
do_anim = true;
}
}
- if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) {
+ if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) {
ED_info_stats_clear(win->screen->scene);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
}
@@ -1085,11 +1105,11 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
if (op->opm) {
wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) &&
- ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER));
+ ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR));
}
else {
wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) &&
- ((op->flag & OP_GRAB_POINTER) || (ot->flag & OPTYPE_GRAB_POINTER));
+ ((op->flag & OP_IS_MODAL_GRAB_CURSOR) || (ot->flag & OPTYPE_GRAB_CURSOR));
}
/* exception, cont. grab in header is annoying */
@@ -1337,7 +1357,7 @@ void wm_event_free_handler(wmEventHandler *handler)
}
/* only set context when area/region is part of screen */
-static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
+static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event)
{
bScreen *screen = CTX_wm_screen(C);
@@ -1358,10 +1378,27 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler)
}
else {
ARegion *ar;
+ wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL;
CTX_wm_area_set(C, sa);
- for (ar = sa->regionbase.first; ar; ar = ar->next)
- if (ar == handler->op_region)
- break;
+
+ if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) {
+ ar = BKE_area_find_region_xy(sa, handler->op_region_type, event->x, event->y);
+ if (ar) {
+ handler->op_region = ar;
+ }
+ }
+ else {
+ ar = NULL;
+ }
+
+ if (ar == NULL) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar == handler->op_region) {
+ break;
+ }
+ }
+ }
+
/* XXX no warning print here, after full-area and back regions are remade */
if (ar)
CTX_wm_region_set(C, ar);
@@ -1379,11 +1416,12 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
/* C is zero on freeing database, modal handlers then already were freed */
while ((handler = BLI_pophead(handlers))) {
if (handler->op) {
+ wmWindow *win = CTX_wm_window(C);
if (handler->op->type->cancel) {
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
- wm_handler_op_context(C, handler);
+ wm_handler_op_context(C, handler, win->eventstate);
if (handler->op->type->flag & OPTYPE_UNDO)
wm->op_undo_depth++;
@@ -1397,7 +1435,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
CTX_wm_region_set(C, region);
}
- WM_cursor_grab_disable(CTX_wm_window(C), NULL);
+ WM_cursor_grab_disable(win, NULL);
WM_operator_free(handler->op);
}
else if (handler->ui_remove) {
@@ -1569,7 +1607,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
ARegion *region = CTX_wm_region(C);
bool dbl_click_disabled = false;
- wm_handler_op_context(C, handler);
+ wm_handler_op_context(C, handler, event);
wm_region_mouse_co(C, event);
wm_event_modalkeymap(C, op, event, &dbl_click_disabled);
@@ -1717,7 +1755,7 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
ED_screen_full_prevspace(C, CTX_wm_area(C));
}
- wm_handler_op_context(C, handler);
+ wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate);
/* needed for UI_popup_menu_reports */
@@ -1843,7 +1881,7 @@ static int wm_action_not_handled(int action)
static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers)
{
#ifndef NDEBUG
- const int do_debug_handler = (G.debug & G_DEBUG_HANDLERS) &&
+ const bool do_debug_handler = (G.debug & G_DEBUG_HANDLERS) &&
/* comment this out to flood the console! (if you really want to test) */
!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)
;
@@ -2330,6 +2368,11 @@ void wm_event_do_handlers(bContext *C)
break;
}
+ /* update azones if needed - done here because it needs to be independent from redraws */
+ if (sa->flag & AREA_FLAG_ACTIONZONES_UPDATE) {
+ ED_area_azones_update(sa, &event->x);
+ }
+
if (wm_event_inside_i(event, &sa->totrct)) {
CTX_wm_area_set(C, sa);
@@ -2529,6 +2572,7 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op)
handler->op_area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */
handler->op_region = CTX_wm_region(C);
+ handler->op_region_type = handler->op_region ? handler->op_region->regiontype : -1;
BLI_addhead(&win->modalhandlers, handler);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index df0d27bc43e..a3cbb2b6eec 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -951,7 +951,7 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
/* operator now handles overwrite checks */
if (G.fileflags & G_AUTOPACK) {
- packAll(G.main, reports);
+ packAll(G.main, reports, false);
}
/* don't forget not to return without! */
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 71a025f3660..b5c267e8a39 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -149,9 +149,11 @@ void WM_init(bContext *C, int argc, const char **argv)
WM_menutype_init();
WM_uilisttype_init();
- set_free_windowmanager_cb(wm_close_and_free); /* library.c */
- set_free_notifier_reference_cb(WM_main_remove_notifier_reference); /* library.c */
- set_blender_test_break_cb(wm_window_testbreak); /* blender.c */
+ BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
+ BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
+ BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */
+ BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
+ BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */
DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */
ED_spacetypes_init(); /* editors/space_api/spacetype.c */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index cb2db94f609..dfff5b4982f 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -341,7 +341,9 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event)
* */
if (op->opm->type->flag & OPTYPE_BLOCKING) {
int bounds[4] = {-1, -1, -1, -1};
- int wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER));
+ const bool wrap = (
+ (U.uiflag & USER_CONTINUOUS_MOUSE) &&
+ ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR)));
if (wrap) {
ARegion *ar = CTX_wm_region(C);
@@ -4831,6 +4833,38 @@ static void WM_OT_previews_ensure(wmOperatorType *ot)
ot->exec = previews_ensure_exec;
}
+static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr_props;
+ char buf[512];
+ short retval = OPERATOR_CANCELLED;
+
+ if (UI_but_online_manual_id_from_active(C, buf, sizeof(buf))) {
+ WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
+ RNA_string_set(&ptr_props, "doc_id", buf);
+
+ retval = WM_operator_name_call_ptr(
+ C, WM_operatortype_find("WM_OT_doc_view_manual", false),
+ WM_OP_EXEC_DEFAULT, &ptr_props);
+
+ WM_operator_properties_free(&ptr_props);
+ }
+
+ return retval;
+}
+
+static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View Online Manual";
+ ot->idname = "WM_OT_doc_view_manual_ui_context";
+ ot->description = "View a context based online manual in a web browser";
+
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = doc_view_manual_ui_context_exec;
+}
+
/* ******************************************************* */
static void operatortype_ghash_free_cb(wmOperatorType *ot)
@@ -4927,6 +4961,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_console_toggle);
#endif
WM_operatortype_append(WM_OT_previews_ensure);
+ WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
}
/* circleselect-like modal operators */
@@ -5153,6 +5188,8 @@ void wm_window_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "WM_OT_window_fullscreen_toggle", F11KEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "WM_OT_quit_blender", QKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "WM_OT_doc_view_manual_ui_context", F1KEY, KM_PRESS, KM_ALT, 0);
+
/* debug/testing */
WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index 328223645bc..717583f69ba 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -363,8 +363,7 @@ static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display
{
return ELEM(stereo_display,
S3D_DISPLAY_SIDEBYSIDE,
- S3D_DISPLAY_TOPBOTTOM,
- S3D_DISPLAY_PAGEFLIP);
+ S3D_DISPLAY_TOPBOTTOM);
}
bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
@@ -451,44 +450,61 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
const bool is_fullscreen = WM_window_is_fullscreen(win);
- char display_mode = win->stereo3d_format->display_mode;
+ char prev_display_mode = win->stereo3d_format->display_mode;
+ Stereo3dData *s3dd;
if (G.background)
return OPERATOR_CANCELLED;
- if (op->customdata) {
- Stereo3dData *s3dd = op->customdata;
- *win->stereo3d_format = s3dd->stereo3d_format;
+ if (op->customdata == NULL) {
+ /* no invoke means we need to set the operator properties here */
+ wm_stereo3d_set_init(C, op);
+ wm_stereo3d_set_properties(C, op);
}
- /* pageflip requires a new window to be created with the proper OS flags */
- if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
- if (wm_stereo3d_quadbuffer_supported() == false) {
- BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system");
- win->stereo3d_format->display_mode = display_mode;
- return OPERATOR_CANCELLED;
- }
+ s3dd = op->customdata;
+ *win->stereo3d_format = s3dd->stereo3d_format;
+
+ if (prev_display_mode == S3D_DISPLAY_PAGEFLIP &&
+ prev_display_mode != win->stereo3d_format->display_mode)
+ {
+ /* in case the hardward supports pageflip but not the display */
if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) {
wm_window_close(C, wm, win);
- win = wm->windows.last;
}
else {
BKE_report(op->reports, RPT_ERROR,
- "Fail to create a window compatible with time sequential (page-flip) display method");
- win->stereo3d_format->display_mode = display_mode;
- return OPERATOR_CANCELLED;
+ "Failed to create a window without quad-buffer support, you may experience flickering");
+ }
+ }
+ else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
+ /* pageflip requires a new window to be created with the proper OS flags */
+ if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) {
+ if (wm_stereo3d_quadbuffer_supported()) {
+ wm_window_close(C, wm, win);
+ BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created");
+ }
+ else {
+ wmWindow *win_new = wm->windows.last;
+ wm_window_close(C, wm, win_new);
+ win->stereo3d_format->display_mode = prev_display_mode;
+ BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system");
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR,
+ "Failed to create a window compatible with the time sequential display method");
+ win->stereo3d_format->display_mode = prev_display_mode;
}
}
- if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) {
+ if (wm_stereo3d_is_fullscreen_required(s3dd->stereo3d_format.display_mode)) {
if (!is_fullscreen) {
BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen");
}
}
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
+ MEM_freeN(op->customdata);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index f89177a82ea..a097343d037 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -56,6 +56,7 @@ typedef struct wmEventHandler {
wmOperator *op; /* for derived/modal handlers */
struct ScrArea *op_area; /* for derived/modal handlers */
struct ARegion *op_region; /* for derived/modal handlers */
+ short op_region_type; /* for derived/modal handlers */
/* ui handler */
wmUIHandlerFunc ui_handle; /* callback receiving events */
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index f8a42159c27..08d01a9c79e 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -227,8 +227,6 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name)
void RE_init_texture_rng() RET_NONE
void RE_exit_texture_rng() RET_NONE
-float *RE_RenderViewGetRectf(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;}
-float *RE_RenderViewGetRectz(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;}
bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;}
void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);}
void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, float *r_modelmat) {STUB_ASSERT(0);}
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 440710f0572..721e43cda4d 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -1024,6 +1024,7 @@ static int set_ge_parameters(int argc, const char **argv, void *data)
}
/* linearMipMap */
if (STREQ(argv[a], "linearmipmap")) {
+ GPU_set_mipmap(1);
GPU_set_linear_mipmap(1); //linearMipMap = 1;
}
@@ -1491,6 +1492,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL);
BLI_argsAdd(ba, 1, NULL, "--debug-jobs", "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS);
BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH);
+ BLI_argsAdd(ba, 1, NULL, "--debug-gpumem", "\n\tEnable GPU memory stats in status bar", debug_mode_generic, (void *)G_DEBUG_GPU_MEM);
BLI_argsAdd(ba, 1, NULL, "--verbose", "<verbose>\n\tSet logging verbosity level.", set_verbosity, NULL);
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index 4f251a66ccf..1a489c301e2 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -117,11 +117,9 @@ typedef struct ThreadInfo {
} ThreadInfo;
KX_BlenderSceneConverter::KX_BlenderSceneConverter(
- struct Main* maggie,
- class KX_KetsjiEngine* engine
- )
- : m_maggie(maggie),
- /*m_maggie_dyn(NULL),*/
+ Main *maggie,
+ KX_KetsjiEngine *engine)
+ :m_maggie(maggie),
m_ketsjiEngine(engine),
m_alwaysUseExpandFraming(false),
m_usemat(false),
@@ -134,13 +132,11 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter(
pthread_mutex_init(&m_threadinfo->merge_lock, NULL);
}
-
KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
{
// clears meshes, and hashmaps from blender to gameengine data
- int i;
// delete sumoshapes
-
+
if (m_threadinfo) {
vector<pthread_t>::iterator pit = m_threadinfo->threads.begin();
while (pit != m_threadinfo->threads.end()) {
@@ -153,104 +149,83 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
}
int numAdtLists = m_map_blender_to_gameAdtList.size();
- for (i=0; i<numAdtLists; i++) {
- BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i);
+ for (int i = 0; i < numAdtLists; i++) {
+ BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i);
delete (adtList);
}
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin();
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itw = m_worldinfos.begin();
while (itw != m_worldinfos.end()) {
delete (*itw).second;
itw++;
}
m_worldinfos.clear();
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
+ vector<pair<KX_Scene *,RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin();
while (itp != m_polymaterials.end()) {
- //m_polymat_cache.erase((*itp).second->GetBlenderMaterial());
delete (*itp).second;
itp++;
}
m_polymaterials.clear();
// delete after RAS_IPolyMaterial
- vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
+ vector<pair<KX_Scene *,BL_Material *> >::iterator itmat = m_materials.begin();
while (itmat != m_materials.end()) {
- //m_mat_cache.erase((*itmat).second->material);
delete (*itmat).second;
itmat++;
}
m_materials.clear();
-
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
+ vector<pair<KX_Scene *,RAS_MeshObject *> >::iterator itm = m_meshobjects.begin();
while (itm != m_meshobjects.end()) {
delete (*itm).second;
itm++;
}
m_meshobjects.clear();
-
/* free any data that was dynamically loaded */
- while (m_DynamicMaggie.size() != 0)
- {
+ while (m_DynamicMaggie.size() != 0) {
FreeBlendFile(m_DynamicMaggie[0]);
}
m_DynamicMaggie.clear();
}
-void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
+void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename)
{
m_newfilename = filename;
}
-
-
bool KX_BlenderSceneConverter::TryAndLoadNewFile()
{
bool result = false;
- // find the file
-/* if ()
- {
- result = true;
- }
- // if not, clear the newfilename
- else
- {
- m_newfilename = "";
- }
-*/
return result;
}
-Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
+Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name)
{
Scene *sce;
/**
* Find the specified scene by name, or NULL if nothing matches.
*/
- if ((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
+ if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
return sce;
- for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
- Main *main= *it;
+ for (vector<Main *>::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) {
+ Main *main = *it;
if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
return sce;
}
return NULL;
-
}
-void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
- class RAS_IRasterizer* rendertools,
- class RAS_ICanvas* canvas,
- bool libloading)
+void KX_BlenderSceneConverter::ConvertScene(KX_Scene *destinationscene, RAS_IRasterizer *rendertools,
+ RAS_ICanvas *canvas, bool libloading)
{
//find out which physics engine
Scene *blenderscene = destinationscene->GetBlenderScene();
@@ -266,13 +241,12 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
// when doing threaded conversion, so it's disabled for now.
// SG_SetActiveStage(SG_STAGE_CONVERTER);
- switch (blenderscene->gm.physicsEngine)
- {
+ switch (blenderscene->gm.physicsEngine) {
#ifdef WITH_BULLET
case WOPHY_BULLET:
{
SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/
- int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0);
+ int visualizePhysics = SYS_GetCommandLineInt(syshandle, "show_physics", 0);
phy_env = CcdPhysicsEnvironment::Create(blenderscene, visualizePhysics);
physics_engine = UseBullet;
@@ -291,7 +265,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
destinationscene->SetPhysicsEnvironment(phy_env);
- BL_ConvertBlenderObjects(m_maggie,
+ BL_ConvertBlenderObjects(
+ m_maggie,
destinationscene,
m_ketsjiEngine,
physics_engine,
@@ -299,8 +274,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
canvas,
this,
m_alwaysUseExpandFraming,
- libloading
- );
+ libloading);
//These lookup are not needed during game
m_map_blender_to_gameactuator.clear();
@@ -326,30 +300,32 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
// delete the scene first as it will stop the use of entities
delete scene;
// delete the entities of this scene
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit;
size = m_worldinfos.size();
- for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
+ for (i = 0, worldit = m_worldinfos.begin(); i < size; ) {
if ((*worldit).first == scene) {
delete (*worldit).second;
*worldit = m_worldinfos.back();
m_worldinfos.pop_back();
size--;
- } else {
+ }
+ else {
i++;
worldit++;
}
}
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit;
size = m_polymaterials.size();
- for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
+ for (i = 0, polymit = m_polymaterials.begin(); i < size; ) {
if ((*polymit).first == scene) {
m_polymat_cache[scene].erase((*polymit).second->GetBlenderMaterial());
delete (*polymit).second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
size--;
- } else {
+ }
+ else {
i++;
polymit++;
}
@@ -357,16 +333,17 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
m_polymat_cache.erase(scene);
- vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
+ vector<pair<KX_Scene *, BL_Material *> >::iterator matit;
size = m_materials.size();
- for (i=0, matit=m_materials.begin(); i<size; ) {
+ for (i = 0, matit = m_materials.begin(); i < size; ) {
if ((*matit).first == scene) {
m_mat_cache[scene].erase((*matit).second->material);
delete (*matit).second;
*matit = m_materials.back();
m_materials.pop_back();
size--;
- } else {
+ }
+ else {
i++;
matit++;
}
@@ -374,15 +351,16 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
m_mat_cache.erase(scene);
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
+ vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit;
size = m_meshobjects.size();
- for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
+ for (i = 0, meshit = m_meshobjects.begin(); i < size; ) {
if ((*meshit).first == scene) {
delete (*meshit).second;
*meshit = m_meshobjects.back();
m_meshobjects.pop_back();
size--;
- } else {
+ }
+ else {
i++;
meshit++;
}
@@ -425,43 +403,34 @@ bool KX_BlenderSceneConverter::GetCacheMaterials()
void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
{
// First make sure we don't register the material twice
- vector<pair<KX_Scene*,BL_Material*> >::iterator it;
+ vector<pair<KX_Scene *, BL_Material *> >::iterator it;
for (it = m_materials.begin(); it != m_materials.end(); ++it)
if (it->second == mat)
return;
- m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat));
+ m_materials.push_back(pair<KX_Scene *, BL_Material *> (m_currentScene, mat));
}
-
-
-void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
- bool to_what)
+void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(bool to_what)
{
m_alwaysUseExpandFraming= to_what;
}
-
-
-void KX_BlenderSceneConverter::RegisterGameObject(
- KX_GameObject *gameobject,
- struct Object *for_blenderobject)
+void KX_BlenderSceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *for_blenderobject)
{
/* only maintained while converting, freed during game runtime */
- m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
+ m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject), gameobject);
}
/* only need to run this during conversion since
* m_map_blender_to_gameobject is freed after conversion */
-void KX_BlenderSceneConverter::UnregisterGameObject(
- KX_GameObject *gameobject)
+void KX_BlenderSceneConverter::UnregisterGameObject(KX_GameObject *gameobject)
{
- struct Object *bobp= gameobject->GetBlenderObject();
+ Object *bobp = gameobject->GetBlenderObject();
if (bobp) {
CHashedPtr bptr(bobp);
- KX_GameObject **gobp= m_map_blender_to_gameobject[bptr];
- if (gobp && *gobp == gameobject)
- {
+ KX_GameObject **gobp = m_map_blender_to_gameobject[bptr];
+ if (gobp && *gobp == gameobject) {
// also maintain m_map_blender_to_gameobject if the gameobject
// being removed is matching the blender object
m_map_blender_to_gameobject.remove(bptr);
@@ -469,47 +438,41 @@ void KX_BlenderSceneConverter::UnregisterGameObject(
}
}
-KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
- struct Object *for_blenderobject)
+KX_GameObject *KX_BlenderSceneConverter::FindGameObject(Object *for_blenderobject)
{
- KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
-
- return obp?*obp:NULL;
+ KX_GameObject **obp = m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
+
+ return obp ? *obp : NULL;
}
-void KX_BlenderSceneConverter::RegisterGameMesh(
- RAS_MeshObject *gamemesh,
- struct Mesh *for_blendermesh)
+void KX_BlenderSceneConverter::RegisterGameMesh(RAS_MeshObject *gamemesh, Mesh *for_blendermesh)
{
if (for_blendermesh) { /* dynamically loaded meshes we don't want to keep lookups for */
m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
}
- m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh));
+ m_meshobjects.push_back(pair<KX_Scene *, RAS_MeshObject *> (m_currentScene,gamemesh));
}
-
-
-RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
- struct Mesh *for_blendermesh/*,
- unsigned int onlayer*/)
+RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(Mesh *for_blendermesh)
{
- RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
-
- if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) {
+ RAS_MeshObject **meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
+
+ if (meshp) {
return *meshp;
- } else {
+ }
+ else {
return NULL;
}
-}
+}
void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
{
// First make sure we don't register the material twice
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator it;
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator it;
for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it)
if (it->second == polymat)
return;
- m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat));
+ m_polymaterials.push_back(pair<KX_Scene *, RAS_IPolyMaterial *> (m_currentScene, polymat));
}
void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, RAS_IPolyMaterial *polymat)
@@ -518,94 +481,82 @@ void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat,
m_polymat_cache[scene][mat] = polymat;
}
-RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, struct Material *mat)
+RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, Material *mat)
{
return (m_use_mat_cache) ? m_polymat_cache[scene][mat] : NULL;
}
-void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, struct Material *mat, BL_Material *blmat)
+void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, Material *mat, BL_Material *blmat)
{
if (m_use_mat_cache && mat)
m_mat_cache[scene][mat] = blmat;
}
-
-BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, struct Material *mat)
+BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, Material *mat)
{
return (m_use_mat_cache) ? m_mat_cache[scene][mat] : NULL;
}
-
-void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act)
+void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, bAction *for_act)
{
m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList);
}
-BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(struct bAction *for_act)
+BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(bAction *for_act)
{
BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)];
- return listp?*listp:NULL;
+ return listp ? *listp : NULL;
}
-
-void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, struct bActuator *for_actuator)
+void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, bActuator *for_actuator)
{
m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act);
}
-SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(struct bActuator *for_actuator)
+SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(bActuator *for_actuator)
{
SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)];
- return actp?*actp:NULL;
+ return actp ? *actp : NULL;
}
-
-void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, struct bController *for_controller)
+void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, bController *for_controller)
{
m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont);
}
-SCA_IController *KX_BlenderSceneConverter::FindGameController(struct bController *for_controller)
+SCA_IController *KX_BlenderSceneConverter::FindGameController(bController *for_controller)
{
SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)];
- return contp?*contp:NULL;
+ return contp ? *contp : NULL;
}
-
-
void KX_BlenderSceneConverter::RegisterWorldInfo(KX_WorldInfo *worldinfo)
{
- m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo));
+ m_worldinfos.push_back(pair<KX_Scene *, KX_WorldInfo *> (m_currentScene, worldinfo));
}
-void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
+void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
{
//TODO this entire function is deprecated, written for 2.4x
//the functionality should be rewritten, currently it does nothing
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
int i;
- for (i=0;i<numScenes;i++)
- {
- KX_Scene* scene = scenes->at(i);
- //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
- CListValue* parentList = scene->GetRootParentList();
+ for (i = 0; i < numScenes; i++) {
+ KX_Scene *scene = scenes->at(i);
+ CListValue *parentList = scene->GetRootParentList();
int numObjects = parentList->GetCount();
int g;
- for (g=0;g<numObjects;g++)
- {
- KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
+ for (g = 0; g < numObjects; g++) {
+ KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g);
if (gameObj->IsRecordAnimation()) {
-
- Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject)
- {
+ Object *blenderObject = gameObj->GetBlenderObject();
+ if (blenderObject) {
#if 0
//erase existing ipo's
Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2);
- if (ipo)
- { //clear the curve data
+ if (ipo) { //clear the curve data
if (clearIpo) {//rcruiz
IpoCurve *icu1;
@@ -630,64 +581,52 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
localDel_ipoCurve( tmpicu );
}
}
- } else
- { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB);
+ }
+ else {
+ ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB);
blenderObject->ipo = ipo;
-
}
#endif
}
}
-
}
-
-
}
-
-
-
}
-void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
+void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo()
{
//TODO the functionality should be rewritten
}
-
- ///this generates ipo curves for position, rotation, allowing to use game physics in animation
-void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
+// this generates ipo curves for position, rotation, allowing to use game physics in animation
+void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
{
-
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
int i;
- for (i=0;i<numScenes;i++)
- {
- KX_Scene* scene = scenes->at(i);
+ for (i = 0; i < numScenes; i++) {
+ KX_Scene *scene = scenes->at(i);
//PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
- CListValue* parentList = scene->GetObjectList();
+ CListValue *parentList = scene->GetObjectList();
int numObjects = parentList->GetCount();
int g;
- for (g=0;g<numObjects;g++)
- {
- KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
- Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) {
-
- if (blenderObject->adt==NULL)
+ for (g = 0; g < numObjects; g++) {
+ KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g);
+ Object *blenderObject = gameObj->GetBlenderObject();
+ if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) {
+ if (blenderObject->adt == NULL)
BKE_animdata_add_id(&blenderObject->id);
- if (blenderObject->adt)
- {
- const MT_Point3& position = gameObj->NodeGetWorldPosition();
+ if (blenderObject->adt) {
+ const MT_Point3 &position = gameObj->NodeGetWorldPosition();
//const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
- const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
+ const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation();
position.getValue(blenderObject->loc);
float tmat[3][3];
- for (int r=0;r<3;r++)
- for (int c=0;c<3;c++)
+ for (int r = 0; r < 3; r++)
+ for (int c = 0; c < 3; c++)
tmat[r][c] = (float)orn[c][r];
mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat);
@@ -772,27 +711,22 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
}
}
-
-void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
+void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
{
-
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
int i;
- for (i=0;i<numScenes;i++)
- {
- KX_Scene* scene = scenes->at(i);
+ for (i = 0; i < numScenes; i++) {
+ KX_Scene *scene = scenes->at(i);
//PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
- CListValue* parentList = scene->GetRootParentList();
+ CListValue *parentList = scene->GetRootParentList();
int numObjects = parentList->GetCount();
int g;
- for (g=0;g<numObjects;g++)
- {
- KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
+ for (g = 0; g < numObjects; g++) {
+ KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g);
if (gameObj->IsRecordAnimation()) {
- Object* blenderObject = gameObj->GetBlenderObject();
- if (blenderObject && blenderObject->adt)
- {
+ Object *blenderObject = gameObj->GetBlenderObject();
+ if (blenderObject && blenderObject->adt) {
bAction *act = verify_adt_action(&blenderObject->id, false);
FCurve *fcu;
@@ -832,14 +766,14 @@ PyObject *KX_BlenderSceneConverter::GetPyNamespace()
}
#endif
-vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic()
+vector<Main *> &KX_BlenderSceneConverter::GetMainDynamic()
{
return m_DynamicMaggie;
}
-Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
+Main *KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
{
- for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++)
+ for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++)
if (BLI_path_cmp((*it)->name, path) == 0)
return *it;
@@ -848,22 +782,21 @@ Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
void KX_BlenderSceneConverter::MergeAsyncLoads()
{
- vector<KX_Scene*> *merge_scenes;
+ vector<KX_Scene *> *merge_scenes;
- vector<KX_LibLoadStatus*>::iterator mit;
- vector<KX_Scene*>::iterator sit;
+ vector<KX_LibLoadStatus *>::iterator mit;
+ vector<KX_Scene *>::iterator sit;
pthread_mutex_lock(&m_threadinfo->merge_lock);
- for (mit=m_mergequeue.begin(); mit!=m_mergequeue.end(); ++mit) {
- merge_scenes = (vector<KX_Scene*>*)(*mit)->GetData();
+ for (mit = m_mergequeue.begin(); mit != m_mergequeue.end(); ++mit) {
+ merge_scenes = (vector<KX_Scene *> *)(*mit)->GetData();
for (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) {
(*mit)->GetMergeScene()->MergeScene(*sit);
delete (*sit);
}
-
delete merge_scenes;
(*mit)->SetData(NULL);
@@ -885,17 +818,17 @@ void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status)
static void *async_convert(void *ptr)
{
KX_Scene *new_scene = NULL;
- KX_LibLoadStatus *status = (KX_LibLoadStatus*)ptr;
- vector<Scene*> *scenes = (vector<Scene*>*)status->GetData();
- vector<KX_Scene*> *merge_scenes = new vector<KX_Scene*>(); // Deleted in MergeAsyncLoads
+ KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr;
+ vector<Scene *> *scenes = (vector<Scene *> *)status->GetData();
+ vector<KX_Scene *> *merge_scenes = new vector<KX_Scene *>(); // Deleted in MergeAsyncLoads
- for (unsigned int i=0; i<scenes->size(); ++i) {
+ for (unsigned int i = 0; i < scenes->size(); ++i) {
new_scene = status->GetEngine()->CreateScene((*scenes)[i], true);
if (new_scene)
merge_scenes->push_back(new_scene);
- status->AddProgress((1.f/scenes->size())*0.9f); // We'll call conversion 90% and merging 10% for now
+ status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now
}
delete scenes;
@@ -922,28 +855,21 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepa
return LinkBlendFile(bpy_openlib, filepath, group, scene_merge, err_str, options);
}
-static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const char *path, int idcode)
+static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode)
{
- Main *main_tmp= NULL; /* created only for linking, then freed */
LinkNode *names = NULL;
- short flag= 0; /* don't need any special options */
-
- /* here appending/linking starts */
- main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);
int totnames_dummy;
- names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy);
+ names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy);
- int i=0;
- LinkNode *n= names;
+ int i = 0;
+ LinkNode *n = names;
while (n) {
BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode);
- n= (LinkNode *)n->next;
+ n = (LinkNode *)n->next;
i++;
}
BLI_linklist_free(names, free); /* free linklist *and* each node's data */
-
- BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag);
}
KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
@@ -956,42 +882,48 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
// TIMEIT_START(bge_link_blend_file);
KX_LibLoadStatus *status;
-
+
/* only scene and mesh supported right now */
- if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) {
+ if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) {
snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group);
- *err_str= err_local;
+ *err_str = err_local;
BLO_blendhandle_close(bpy_openlib);
return NULL;
}
if (GetMainDynamicPath(path)) {
snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path);
- *err_str= err_local;
+ *err_str = err_local;
BLO_blendhandle_close(bpy_openlib);
return NULL;
}
- if (bpy_openlib==NULL) {
+ if (bpy_openlib == NULL) {
snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
- *err_str= err_local;
+ *err_str = err_local;
return NULL;
}
main_newlib = BKE_main_new();
BKE_reports_init(&reports, RPT_STORE);
- load_datablocks(main_newlib, bpy_openlib, path, idcode);
+ short flag = 0; /* don't need any special options */
+ /* created only for linking, then freed */
+ Main *main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path);
+
+ load_datablocks(main_tmp, bpy_openlib, path, idcode);
- if (idcode==ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) {
- load_datablocks(main_newlib, bpy_openlib, path, ID_TXT);
+ if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) {
+ load_datablocks(main_tmp, bpy_openlib, path, ID_TXT);
}
/* now do another round of linking for Scenes so all actions are properly loaded */
- if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) {
- load_datablocks(main_newlib, bpy_openlib, path, ID_AC);
+ if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) {
+ load_datablocks(main_tmp, bpy_openlib, path, ID_AC);
}
-
+
+ BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag);
+
BLO_blendhandle_close(bpy_openlib);
BKE_reports_clear(&reports);
@@ -1004,42 +936,43 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path);
- if (idcode==ID_ME) {
+ if (idcode == ID_ME) {
/* Convert all new meshes into BGE meshes */
- ID* mesh;
+ ID *mesh;
- for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
+ for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) {
if (options & LIB_LOAD_VERBOSE)
- printf("MeshName: %s\n", mesh->name+2);
+ printf("MeshName: %s\n", mesh->name + 2);
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders
- scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
+ scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);
}
}
- else if (idcode==ID_AC) {
+ else if (idcode == ID_AC) {
/* Convert all actions */
ID *action;
- for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) {
+ for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) {
if (options & LIB_LOAD_VERBOSE)
- printf("ActionName: %s\n", action->name+2);
- scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action);
+ printf("ActionName: %s\n", action->name + 2);
+ scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action);
}
}
- else if (idcode==ID_SCE) {
+ else if (idcode == ID_SCE) {
/* Merge all new linked in scene into the existing one */
ID *scene;
// scenes gets deleted by the thread when it's done using it (look in async_convert())
- vector<Scene*> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene*>() : NULL;
+ vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL;
- for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
+ for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) {
if (options & LIB_LOAD_VERBOSE)
- printf("SceneName: %s\n", scene->name+2);
+ printf("SceneName: %s\n", scene->name + 2);
if (options & LIB_LOAD_ASYNC) {
- scenes->push_back((Scene*)scene);
- } else {
+ scenes->push_back((Scene *)scene);
+ }
+ else {
/* merge into the base scene */
- KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true);
+ KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true);
scene_merge->MergeScene(other);
// RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene
@@ -1050,7 +983,7 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
if (options & LIB_LOAD_ASYNC) {
pthread_t id;
status->SetData(scenes);
- pthread_create(&id, NULL, &async_convert, (void*)status);
+ pthread_create(&id, NULL, &async_convert, (void *)status);
m_threadinfo->threads.push_back(id);
}
@@ -1064,17 +997,16 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
if (options & LIB_LOAD_LOAD_ACTIONS) {
ID *action;
- for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) {
+ for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) {
if (options & LIB_LOAD_VERBOSE)
- printf("ActionName: %s\n", action->name+2);
- scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action);
+ printf("ActionName: %s\n", action->name + 2);
+ scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action);
}
}
}
if (!(options & LIB_LOAD_ASYNC))
status->Finish();
-
// TIMEIT_END(bge_link_blend_file);
@@ -1084,22 +1016,22 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl
/* Note m_map_*** are all ok and don't need to be freed
* most are temp and NewRemoveObject frees m_map_gameobject_to_blender */
-bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
+bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie)
{
- int maggie_index= -1;
- int i=0;
+ int maggie_index = -1;
+ int i = 0;
- if (maggie==NULL)
+ if (maggie == NULL)
return false;
/* tag all false except the one we remove */
- for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
- Main *main= *it;
+ for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) {
+ Main *main = *it;
if (main != maggie) {
BKE_main_id_tag_all(main, false);
}
else {
- maggie_index= i;
+ maggie_index = i;
}
i++;
}
@@ -1111,15 +1043,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index);
BKE_main_id_tag_all(maggie, true);
-
/* free all tagged objects */
- KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
+ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
int numScenes = scenes->size();
-
- for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
- {
- KX_Scene* scene = scenes->at(scene_idx);
+ for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) {
+ KX_Scene *scene = scenes->at(scene_idx);
if (IS_TAGGED(scene->GetBlenderScene())) {
m_ketsjiEngine->RemoveScene(scene->GetName());
m_mat_cache.erase(scene);
@@ -1128,16 +1057,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
numScenes--;
}
else {
-
/* in case the mesh might be refered to later */
{
- CTR_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
+ CTR_Map<STR_HashedString, void *> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
- for (int i=0; i<mapStringToMeshes.size(); i++)
- {
- RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
- if (meshobj && IS_TAGGED(meshobj->GetMesh()))
- {
+ for (int i = 0; i < mapStringToMeshes.size(); i++) {
+ RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i);
+ if (meshobj && IS_TAGGED(meshobj->GetMesh())) {
STR_HashedString mn = meshobj->GetName();
mapStringToMeshes.remove(mn);
m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh()));
@@ -1148,15 +1074,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
/* Now unregister actions */
{
- CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap();
+ CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap();
- for (int i=0; i<mapStringToActions.size(); i++)
- {
- ID *action= (ID*) *mapStringToActions.at(i);
+ for (int i = 0; i < mapStringToActions.size(); i++) {
+ ID *action = (ID*) *mapStringToActions.at(i);
- if (IS_TAGGED(action))
- {
- STR_HashedString an = action->name+2;
+ if (IS_TAGGED(action)) {
+ STR_HashedString an = action->name + 2;
mapStringToActions.remove(an);
i--;
}
@@ -1166,16 +1090,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
//scene->FreeTagged(); /* removed tagged objects and meshes*/
CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL};
- for (int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++)
- {
- CListValue *obs= obj_lists[ob_ls_idx];
- RAS_MeshObject* mesh;
+ for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) {
+ CListValue *obs = obj_lists[ob_ls_idx];
+ RAS_MeshObject *mesh;
- for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++)
- {
- KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
+ for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) {
+ KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
if (IS_TAGGED(gameobj->GetBlenderObject())) {
-
int size_before = obs->GetCount();
/* Eventually calls RemoveNodeDestructObject
@@ -1190,9 +1111,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
else {
/* free the mesh, we could be referecing a linked one! */
- int mesh_index= gameobj->GetMeshCount();
+ int mesh_index = gameobj->GetMeshCount();
while (mesh_index--) {
- mesh= gameobj->GetMesh(mesh_index);
+ mesh = gameobj->GetMesh(mesh_index);
if (IS_TAGGED(mesh->GetMesh())) {
gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */
break;
@@ -1210,11 +1131,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
/* make sure action actuators are not referencing tagged actions */
- for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++)
- {
- if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION))
- {
- BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx];
+ for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) {
+ if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) {
+ BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx];
if (IS_TAGGED(act->GetAction()))
act->SetAction(NULL);
}
@@ -1225,7 +1144,6 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
}
-
int size;
// delete the entities of this scene
@@ -1248,24 +1166,24 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
/* Worlds don't reference original blender data so we need to make a set from them */
- typedef std::set<KX_WorldInfo*> KX_WorldInfoSet;
+ typedef std::set<KX_WorldInfo *> KX_WorldInfoSet;
KX_WorldInfoSet worldset;
- for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
- {
- KX_Scene* scene = scenes->at(scene_idx);
+ for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) {
+ KX_Scene *scene = scenes->at(scene_idx);
if (scene->GetWorldInfo())
- worldset.insert( scene->GetWorldInfo() );
+ worldset.insert(scene->GetWorldInfo());
}
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit;
size = m_worldinfos.size();
- for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
+ for (i = 0, worldit = m_worldinfos.begin(); i < size;) {
if ((*worldit).second && (worldset.count((*worldit).second)) == 0) {
delete (*worldit).second;
*worldit = m_worldinfos.back();
m_worldinfos.pop_back();
size--;
- } else {
+ }
+ else {
i++;
worldit++;
}
@@ -1273,20 +1191,15 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
worldset.clear();
/* done freeing the worlds */
-
-
-
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit;
size = m_polymaterials.size();
+ for (i = 0, polymit = m_polymaterials.begin(); i < size; ) {
+ RAS_IPolyMaterial *mat = (*polymit).second;
+ Material *bmat = NULL;
-
- for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
- RAS_IPolyMaterial *mat= (*polymit).second;
- Material *bmat= NULL;
-
- KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
- bmat= bl_mat->GetBlenderMaterial();
+ KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat);
+ bmat = bl_mat->GetBlenderMaterial();
if (IS_TAGGED(bmat)) {
/* only remove from bucket */
@@ -1297,63 +1210,53 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
polymit++;
}
-
-
- for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
- RAS_IPolyMaterial *mat= (*polymit).second;
- Material *bmat= NULL;
+ for (i = 0, polymit = m_polymaterials.begin(); i < size; ) {
+ RAS_IPolyMaterial *mat = (*polymit).second;
+ Material *bmat = NULL;
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
- bmat= bl_mat->GetBlenderMaterial();
-
- if (bmat) {
- //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
- }
- else {
- //printf("LOST MAT !!!");
- }
+ bmat = bl_mat->GetBlenderMaterial();
if (IS_TAGGED(bmat)) {
delete (*polymit).second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
size--;
- //printf("tagged !\n");
} else {
i++;
polymit++;
- //printf("(un)tagged !\n");
}
}
- vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
+ vector<pair<KX_Scene *, BL_Material *> >::iterator matit;
size = m_materials.size();
- for (i=0, matit=m_materials.begin(); i<size; ) {
- BL_Material *mat= (*matit).second;
+ for (i = 0, matit = m_materials.begin(); i < size; ) {
+ BL_Material *mat = (*matit).second;
if (IS_TAGGED(mat->material)) {
delete (*matit).second;
*matit = m_materials.back();
m_materials.pop_back();
size--;
- } else {
+ }
+ else {
i++;
matit++;
}
}
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
+ vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit;
RAS_BucketManager::BucketList::iterator bit;
list<RAS_MeshSlot>::iterator msit;
RAS_BucketManager::BucketList buckets;
size = m_meshobjects.size();
- for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
- RAS_MeshObject *me= (*meshit).second;
+ for (i = 0, meshit = m_meshobjects.begin(); i < size;) {
+ RAS_MeshObject *me = (*meshit).second;
if (IS_TAGGED(me->GetMesh())) {
// Before deleting the mesh object, make sure the rasterizer is
// no longer referencing it.
buckets = meshit->first->GetBucketManager()->GetSolidBuckets();
- for (bit=buckets.begin(); bit!=buckets.end(); bit++) {
+ for (bit = buckets.begin(); bit != buckets.end(); bit++) {
msit = (*bit)->msBegin();
while (msit != (*bit)->msEnd()) {
@@ -1366,7 +1269,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
// And now the alpha buckets
buckets = meshit->first->GetBucketManager()->GetAlphaBuckets();
- for (bit=buckets.begin(); bit!=buckets.end(); bit++) {
+ for (bit = buckets.begin(); bit != buckets.end(); bit++) {
msit = (*bit)->msBegin();
while (msit != (*bit)->msEnd()) {
@@ -1382,7 +1285,8 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
*meshit = m_meshobjects.back();
m_meshobjects.pop_back();
size--;
- } else {
+ }
+ else {
i++;
meshit++;
}
@@ -1409,24 +1313,23 @@ bool KX_BlenderSceneConverter::FreeBlendFile(const char *path)
bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
{
-
{
- vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin();
+ vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itp = m_worldinfos.begin();
while (itp != m_worldinfos.end()) {
- if ((*itp).first==from)
- (*itp).first= to;
+ if ((*itp).first == from)
+ (*itp).first = to;
itp++;
}
}
{
- vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
+ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin();
while (itp != m_polymaterials.end()) {
- if ((*itp).first==from) {
- (*itp).first= to;
+ if ((*itp).first == from) {
+ (*itp).first = to;
/* also switch internal data */
- RAS_IPolyMaterial*mat= (*itp).second;
+ RAS_IPolyMaterial *mat = (*itp).second;
mat->Replace_IScene(to);
}
itp++;
@@ -1434,29 +1337,29 @@ bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
}
{
- vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin();
+ vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator itp = m_meshobjects.begin();
while (itp != m_meshobjects.end()) {
- if ((*itp).first==from)
- (*itp).first= to;
+ if ((*itp).first == from)
+ (*itp).first = to;
itp++;
}
}
{
- vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin();
+ vector<pair<KX_Scene *, BL_Material *> >::iterator itp = m_materials.begin();
while (itp != m_materials.end()) {
- if ((*itp).first==from)
- (*itp).first= to;
+ if ((*itp).first == from)
+ (*itp).first = to;
itp++;
}
}
-
+
return true;
}
/* This function merges a mesh from the current scene into another main
* it does not convert */
-RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name)
+RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name)
{
/* Find a mesh in the current main */
ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2));
@@ -1464,7 +1367,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
if (me == NULL) {
// The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones
- vector<Main*>::iterator it;
+ vector<Main *>::iterator it;
for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) {
me = static_cast<ID *>(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2));
@@ -1474,12 +1377,12 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
break;
}
}
-
- if (me==NULL) {
+
+ if (me == NULL) {
printf("Could not be found \"%s\"\n", name);
return NULL;
}
-
+
/* Watch this!, if its used in the original scene can cause big troubles */
if (me->us > 0) {
#ifdef DEBUG
@@ -1491,34 +1394,32 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */
BLI_addtail(&maggie->mesh, me);
-
/* Must copy the materials this uses else we cant free them */
{
- Mesh *mesh= (Mesh *)me;
-
+ Mesh *mesh = (Mesh *)me;
+
/* ensure all materials are tagged */
- for (int i=0; i<mesh->totcol; i++)
+ for (int i = 0; i < mesh->totcol; i++) {
if (mesh->mat[i])
mesh->mat[i]->id.flag &= ~LIB_DOIT;
-
- for (int i=0; i<mesh->totcol; i++)
- {
- Material *mat_old= mesh->mat[i];
-
+ }
+
+ for (int i = 0; i < mesh->totcol; i++) {
+ Material *mat_old = mesh->mat[i];
+
/* if its tagged its a replaced material */
- if (mat_old && (mat_old->id.flag & LIB_DOIT)==0)
- {
- Material *mat_old= mesh->mat[i];
- Material *mat_new= BKE_material_copy( mat_old );
-
+ if (mat_old && (mat_old->id.flag & LIB_DOIT) == 0) {
+ Material *mat_old = mesh->mat[i];
+ Material *mat_new = BKE_material_copy(mat_old);
+
mat_new->id.flag |= LIB_DOIT;
mat_old->id.us--;
-
+
BLI_remlink(&G.main->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex
BLI_addtail(&maggie->mat, mat_new);
-
+
mesh->mat[i] = mat_new;
-
+
/* the same material may be used twice */
for (int j = i + 1; j < mesh->totcol; j++) {
if (mesh->mat[j] == mat_old) {
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index a4c9472df2f..9e5b1464ac0 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -519,7 +519,7 @@ int main(int argc, char** argv)
BKE_sound_init_once();
- set_free_windowmanager_cb(wm_free);
+ BKE_library_callback_free_window_manager_set(wm_free);
/* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */
isBlenderPlayer = !BLO_is_a_runtime(argv[0]);
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index e464883016e..44d9bfa0cf4 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -1907,7 +1907,7 @@ PyMethodDef KX_GameObject::Methods[] = {
{"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
{"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
{"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
- {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
+ {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS},
{"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
{"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
{"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
@@ -3318,10 +3318,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args)
-PyObject *KX_GameObject::PySuspendDynamics()
+PyObject *KX_GameObject::PySuspendDynamics(PyObject *args)
{
+ bool ghost = false;
+
+ if (!PyArg_ParseTuple(args, "|b", &ghost))
+ return NULL;
+
if (GetPhysicsController())
- GetPhysicsController()->SuspendDynamics();
+ GetPhysicsController()->SuspendDynamics(ghost);
+
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 54bb6ee2605..9c081b449ec 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -517,7 +517,14 @@ public:
*/
void ActivateGraphicController(bool recurse);
+ /** Set the object's collison group
+ * \param filter The group bitfield
+ */
void SetUserCollisionGroup(unsigned short filter);
+
+ /** Set the object's collison mask
+ * \param filter The mask bitfield
+ */
void SetUserCollisionMask(unsigned short mask);
unsigned short GetUserCollisionGroup();
unsigned short GetUserCollisionMask();
@@ -907,7 +914,7 @@ public:
* Change the layer of the object (when it is added in another layer
* than the original layer)
*/
- void
+ virtual void
SetLayer(
int l
);
@@ -998,7 +1005,7 @@ public:
KX_PYMETHOD_O(KX_GameObject,SetState);
KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);
KX_PYMETHOD_O(KX_GameObject,GetAxisVect);
- KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics);
KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics);
KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody);
KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody);
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index f0b47684092..40af9b4ca39 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -1108,6 +1108,10 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
KX_SetActiveScene(scene);
+#ifdef WITH_PYTHON
+ scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB());
+#endif
+
GetSceneViewport(scene, cam, area, viewport);
// store the computed viewport in the scene
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index d6b84e98aec..0dec5715588 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -108,6 +108,7 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene)
void KX_LightObject::SetLayer(int layer)
{
+ KX_GameObject::SetLayer(layer);
m_lightobj->m_layer = layer;
}
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 386f8e95789..3a58584223d 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -60,7 +60,7 @@ public:
RAS_ILightObject* GetLightData() { return m_lightobj;}
void UpdateScene(class KX_Scene *kxscene);
- void SetLayer(int layer);
+ virtual void SetLayer(int layer);
virtual int GetGameObjectType() { return OBJ_LIGHT; }
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index a3e1d1562c9..a460d9bd392 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -238,6 +238,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_attr_dict = NULL;
m_draw_call_pre = NULL;
m_draw_call_post = NULL;
+ m_draw_setup_call_pre = NULL;
#endif
}
@@ -834,12 +835,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
(*git)->Relink(&m_map_gameobject_to_replica);
// add the object in the layer of the parent
(*git)->SetLayer(groupobj->GetLayer());
- // If the object was a light, we need to update it's RAS_LightObject as well
- if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
- {
- KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
- lightobj->SetLayer(groupobj->GetLayer());
- }
}
// replicate crosslinks etc. between logic bricks
@@ -915,18 +910,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
replica->GetSGNode()->AddChild(childreplicanode);
}
- // At this stage all the objects in the hierarchy have been duplicated,
- // we can update the scenegraph, we need it for the duplication of logic
- MT_Point3 newpos = referenceobj->NodeGetWorldPosition();
- replica->NodeSetLocalPosition(newpos);
+ if (referenceobj) {
+ // At this stage all the objects in the hierarchy have been duplicated,
+ // we can update the scenegraph, we need it for the duplication of logic
+ MT_Point3 newpos = referenceobj->NodeGetWorldPosition();
+ replica->NodeSetLocalPosition(newpos);
- MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation();
- replica->NodeSetLocalOrientation(newori);
-
- // get the rootnode's scale
- MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
- // set the replica's relative scale with the rootnode's scale
- replica->NodeSetRelativeScale(newscale);
+ MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation();
+ replica->NodeSetLocalOrientation(newori);
+
+ // get the rootnode's scale
+ MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
+ // set the replica's relative scale with the rootnode's scale
+ replica->NodeSetRelativeScale(newscale);
+ }
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
@@ -946,13 +943,13 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
{
// this will also relink the actuators in the hierarchy
(*git)->Relink(&m_map_gameobject_to_replica);
- // add the object in the layer of the reference object
- (*git)->SetLayer(referenceobj->GetLayer());
- // If the object was a light, we need to update it's RAS_LightObject as well
- if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
- {
- KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
- lightobj->SetLayer(referenceobj->GetLayer());
+ if (referenceobj) {
+ // add the object in the layer of the reference object
+ (*git)->SetLayer(referenceobj->GetLayer());
+ }
+ else {
+ // We don't know what layer set, so we set all visible layers in the blender scene.
+ (*git)->SetLayer(m_blenderScene->lay);
}
}
@@ -2399,6 +2396,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT
return self->m_draw_call_post;
}
+PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+ if (self->m_draw_setup_call_pre == NULL)
+ self->m_draw_setup_call_pre = PyList_New(0);
+
+ Py_INCREF(self->m_draw_setup_call_pre);
+ return self->m_draw_setup_call_pre;
+}
+
int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_Scene* self = static_cast<KX_Scene*>(self_v);
@@ -2433,6 +2441,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT
return PY_SET_ATTR_SUCCESS;
}
+int KX_Scene::pyattr_set_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_Scene* self = static_cast<KX_Scene*>(self_v);
+
+ if (!PyList_CheckExact(value)) {
+ PyErr_SetString(PyExc_ValueError, "Expected a list");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ Py_XDECREF(self->m_draw_setup_call_pre);
+ Py_INCREF(value);
+
+ self->m_draw_setup_call_pre = value;
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_Scene* self = static_cast<KX_Scene*>(self_v);
@@ -2462,6 +2486,7 @@ PyAttributeDef KX_Scene::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera),
KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre),
KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post),
+ KX_PYATTRIBUTE_RW_FUNCTION("pre_draw_setup", KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre),
KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity),
KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend),
KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling),
@@ -2474,23 +2499,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject,
"addObject(object, other, time=0)\n"
"Returns the added object.\n")
{
- PyObject *pyob, *pyreference;
+ PyObject *pyob, *pyreference = Py_None;
KX_GameObject *ob, *reference;
int time = 0;
- if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyreference, &time))
+ if (!PyArg_ParseTuple(args, "O|Oi:addObject", &pyob, &pyreference, &time))
return NULL;
- if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") ||
- !ConvertPythonToGameObject(pyreference, &reference, false, "scene.addObject(object, reference, time): KX_Scene (second argument)") )
+ if (!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") ||
+ !ConvertPythonToGameObject(pyreference, &reference, true, "scene.addObject(object, reference, time): KX_Scene (second argument)"))
return NULL;
if (!m_inactivelist->SearchValue(ob)) {
PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer");
return NULL;
}
- SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, reference, time);
+ SCA_IObject *replica = AddReplicaObject((SCA_IObject*)ob, reference, time);
// release here because AddReplicaObject AddRef's
// the object is added to the scene so we don't want python to own a reference
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index 93e764851a9..a5645ea6448 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene
PyObject* m_attr_dict;
PyObject* m_draw_call_pre;
PyObject* m_draw_call_post;
+ PyObject* m_draw_setup_call_pre;
#endif
struct CullingInfo {
@@ -631,6 +632,8 @@ public:
static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
@@ -647,6 +650,7 @@ public:
PyObject *GetPreDrawCB() { return m_draw_call_pre; }
PyObject *GetPostDrawCB() { return m_draw_call_post; }
+ PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; }
#endif
/**
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index b2b8f30a706..0a71c0a7aac 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -123,10 +123,8 @@ bool CleanPairCallback::processOverlap(btBroadphasePair &pair)
m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer());
CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer());
- if (ctrl0 && ctrl1) {
- ctrl0->GetRigidBody()->activate(true);
- ctrl1->GetRigidBody()->activate(true);
- }
+ ctrl0->GetCollisionObject()->activate(false);
+ ctrl1->GetCollisionObject()->activate(false);
}
return false;
}
@@ -1097,6 +1095,10 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel
void CcdPhysicsController::RefreshCollisions()
{
+ // the object is in an inactive layer so it's useless to update it and can cause problems
+ if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this))
+ return;
+
btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld();
btBroadphaseProxy *proxy = m_object->getBroadphaseHandle();
btDispatcher *dispatcher = dw->getDispatcher();
@@ -1104,8 +1106,10 @@ void CcdPhysicsController::RefreshCollisions()
CleanPairCallback cleanPairs(proxy, pairCache, dispatcher);
pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher);
+
// Forcibly recreate the physics object
- GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, m_cci.m_mass, m_cci.m_collisionFlags, m_cci.m_collisionFilterGroup, m_cci.m_collisionFilterMask);
+ btBroadphaseProxy* handle = m_object->getBroadphaseHandle();
+ GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask);
}
void CcdPhysicsController::SuspendDynamics(bool ghost)
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index 984273ec63e..0ecb79d91ea 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -569,6 +569,7 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
// this function is used when the collisionning group of a controller is changed
// remove and add the collistioning object
btRigidBody* body = ctrl->GetRigidBody();
+ btSoftBody *softBody = ctrl->GetSoftBody();
btCollisionObject* obj = ctrl->GetCollisionObject();
if (obj)
{
@@ -582,6 +583,9 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
body->setMassProps(newMass, inertia);
m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask);
}
+ else if (softBody) {
+ m_dynamicsWorld->addSoftBody(softBody);
+ }
else {
m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
}
@@ -643,6 +647,11 @@ void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ct
}
}
+bool CcdPhysicsEnvironment::IsActiveCcdPhysicsController(CcdPhysicsController *ctrl)
+{
+ return (m_controllers.find(ctrl) != m_controllers.end());
+}
+
void CcdPhysicsEnvironment::AddCcdGraphicController(CcdGraphicController* ctrl)
{
if (m_cullingTree && !ctrl->GetBroadphaseHandle())
@@ -3672,7 +3681,7 @@ void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_Ga
break;
}
- for (dof; dof < dof_max; dof++) {
+ for (; dof < dof_max; dof++) {
if (dat->flag & dofbit) {
phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]);
}
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index 113db3348ca..3b1fe63db0b 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -227,6 +227,8 @@ protected:
void RefreshCcdPhysicsController(CcdPhysicsController* ctrl);
+ bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl);
+
void AddCcdGraphicController(CcdGraphicController* ctrl);
void RemoveCcdGraphicController(CcdGraphicController* ctrl);
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index f47f56541ba..95c153a7e2a 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -1074,12 +1074,17 @@ void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val)
RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping()
{
- if (GPU_get_linear_mipmap())
- return RAS_IRasterizer::RAS_MIPMAP_LINEAR;
- else if (GPU_get_mipmap())
- return RAS_IRasterizer::RAS_MIPMAP_NEAREST;
- else
+ if (GPU_get_mipmap()) {
+ if (GPU_get_linear_mipmap()) {
+ return RAS_IRasterizer::RAS_MIPMAP_LINEAR;
+ }
+ else {
+ return RAS_IRasterizer::RAS_MIPMAP_NEAREST;
+ }
+ }
+ else {
return RAS_IRasterizer::RAS_MIPMAP_NONE;
+ }
}
void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val)